]> source.dussan.org Git - gitblit.git/commitdiff
Support local accounts with LdapUserService and RedmineUserService (issue-183)
authorJames Moger <james.moger@gitblit.com>
Fri, 4 Jan 2013 22:23:23 +0000 (17:23 -0500)
committerJames Moger <james.moger@gitblit.com>
Fri, 4 Jan 2013 22:23:23 +0000 (17:23 -0500)
19 files changed:
docs/04_releases.mkd
src/com/gitblit/ConfigUserService.java
src/com/gitblit/Constants.java
src/com/gitblit/GitBlit.java
src/com/gitblit/GitblitUserService.java
src/com/gitblit/LdapUserService.java
src/com/gitblit/RedmineUserService.java
src/com/gitblit/client/UsersPanel.java
src/com/gitblit/client/UsersTableModel.java
src/com/gitblit/models/UserModel.java
src/com/gitblit/wicket/pages/BasePage.java
src/com/gitblit/wicket/pages/ChangePasswordPage.java
src/com/gitblit/wicket/pages/EditTeamPage.java
src/com/gitblit/wicket/pages/EditUserPage.java
src/com/gitblit/wicket/panels/TeamsPanel.java
src/com/gitblit/wicket/panels/UsersPanel.html
src/com/gitblit/wicket/panels/UsersPanel.java
tests/com/gitblit/tests/LdapUserServiceTest.java
tests/com/gitblit/tests/RedmineUserServiceTest.java

index 6aec85c2a839220e6f1ebd9ab8d1ce5be16ea038..d5e777ca2d484c1c1ee6856994902258b858d329 100644 (file)
@@ -12,6 +12,7 @@
 \r
 #### additions\r
 \r
+- Support for locally and remotely authenticated accounts in LdapUserService and RedmineUserService (issue 183)\r
 - Added Dutch translation (github/kwoot)\r
 \r
 #### changes\r
index 068bbe3a8d595a2ad98de317d9cd7237d9bf720c..67ad0537ad9262ad090ec36b8fdc127ddffe2a1a 100644 (file)
@@ -409,6 +409,10 @@ public class ConfigUserService implements IUserService {
                        // Read realm file\r
                        read();\r
                        UserModel model = users.remove(username.toLowerCase());\r
+                       if (model == null) {\r
+                               // user does not exist\r
+                               return false;\r
+                       }\r
                        // remove user from team\r
                        for (TeamModel team : model.teams) {\r
                                TeamModel t = teams.get(team.name);\r
index f2067f69bcbb08d4e4b667d0c4b158f5dd37bf5c..ca3326900a88480c56364e15a703b783c9fd3f2b 100644 (file)
@@ -405,6 +405,14 @@ public class Constants {
                        return ordinal() <= COOKIE.ordinal();\r
                }\r
        }\r
+       \r
+       public static enum AccountType {\r
+               LOCAL, LDAP, REDMINE;\r
+               \r
+               public boolean isLocal() {\r
+                       return this == LOCAL;\r
+               }\r
+       }\r
 \r
        @Documented\r
        @Retention(RetentionPolicy.RUNTIME)\r
index 30071bb680148e186b0b7cfaefb3e6a943812a70..74d32df083f86b9ecdc9138041b23a8ad29ed4c6 100644 (file)
@@ -471,36 +471,48 @@ public class GitBlit implements ServletContextListener {
                this.userService.setup(settings);\r
        }\r
        \r
+       public boolean supportsAddUser() {\r
+               return supportsCredentialChanges(new UserModel(""));\r
+       }\r
+       \r
        /**\r
+        * Returns true if the user's credentials can be changed.\r
         * \r
+        * @param user\r
         * @return true if the user service supports credential changes\r
         */\r
-       public boolean supportsCredentialChanges() {\r
-               return userService.supportsCredentialChanges();\r
+       public boolean supportsCredentialChanges(UserModel user) {\r
+               return (user != null && user.isLocalAccount()) || userService.supportsCredentialChanges();\r
        }\r
 \r
        /**\r
+        * Returns true if the user's display name can be changed.\r
         * \r
+        * @param user\r
         * @return true if the user service supports display name changes\r
         */\r
-       public boolean supportsDisplayNameChanges() {\r
-               return userService.supportsDisplayNameChanges();\r
+       public boolean supportsDisplayNameChanges(UserModel user) {\r
+               return (user != null && user.isLocalAccount()) || userService.supportsDisplayNameChanges();\r
        }\r
 \r
        /**\r
+        * Returns true if the user's email address can be changed.\r
         * \r
+        * @param user\r
         * @return true if the user service supports email address changes\r
         */\r
-       public boolean supportsEmailAddressChanges() {\r
-               return userService.supportsEmailAddressChanges();\r
+       public boolean supportsEmailAddressChanges(UserModel user) {\r
+               return (user != null && user.isLocalAccount()) || userService.supportsEmailAddressChanges();\r
        }\r
 \r
        /**\r
+        * Returns true if the user's team memberships can be changed.\r
         * \r
+        * @param user\r
         * @return true if the user service supports team membership changes\r
         */\r
-       public boolean supportsTeamMembershipChanges() {\r
-               return userService.supportsTeamMembershipChanges();\r
+       public boolean supportsTeamMembershipChanges(UserModel user) {\r
+               return (user != null && user.isLocalAccount()) || userService.supportsTeamMembershipChanges();\r
        }\r
 \r
        /**\r
@@ -789,6 +801,10 @@ public class GitBlit implements ServletContextListener {
         * @return the effective list of permissions for the user\r
         */\r
        public List<RegistrantAccessPermission> getUserAccessPermissions(UserModel user) {\r
+               if (StringUtils.isEmpty(user.username)) {\r
+                       // new user\r
+                       return new ArrayList<RegistrantAccessPermission>();\r
+               }\r
                Set<RegistrantAccessPermission> set = new LinkedHashSet<RegistrantAccessPermission>();\r
                set.addAll(user.getRepositoryPermissions());\r
                // Flag missing repositories\r
index 141ad8f11cdf228414d864e80342745012900a6f..db450cfcaadfa8f0f5e2c09d786e7c91e69dbef8 100644 (file)
@@ -23,9 +23,11 @@ import java.util.List;
 import org.slf4j.Logger;\r
 import org.slf4j.LoggerFactory;\r
 \r
+import com.gitblit.Constants.AccountType;\r
 import com.gitblit.models.TeamModel;\r
 import com.gitblit.models.UserModel;\r
 import com.gitblit.utils.DeepCopier;\r
+import com.gitblit.utils.StringUtils;\r
 \r
 /**\r
  * This class wraps the default user service and is recommended as the starting\r
@@ -48,6 +50,8 @@ import com.gitblit.utils.DeepCopier;
 public class GitblitUserService implements IUserService {\r
 \r
        protected IUserService serviceImpl;\r
+       \r
+       protected final String ExternalAccount = "#externalAccount";\r
 \r
        private final Logger logger = LoggerFactory.getLogger(GitblitUserService.class);\r
 \r
@@ -144,12 +148,16 @@ public class GitblitUserService implements IUserService {
 \r
        @Override\r
        public UserModel authenticate(char[] cookie) {\r
-               return serviceImpl.authenticate(cookie);\r
+               UserModel user = serviceImpl.authenticate(cookie);\r
+               setAccountType(user);\r
+               return user;\r
        }\r
 \r
        @Override\r
        public UserModel authenticate(String username, char[] password) {\r
-               return serviceImpl.authenticate(username, password);\r
+               UserModel user = serviceImpl.authenticate(username, password);\r
+               setAccountType(user);\r
+               return user;\r
        }\r
        \r
        @Override\r
@@ -159,7 +167,9 @@ public class GitblitUserService implements IUserService {
 \r
        @Override\r
        public UserModel getUserModel(String username) {\r
-               return serviceImpl.getUserModel(username);\r
+               UserModel user = serviceImpl.getUserModel(username);\r
+               setAccountType(user);\r
+               return user;\r
        }\r
 \r
        @Override\r
@@ -174,8 +184,8 @@ public class GitblitUserService implements IUserService {
 \r
        @Override\r
        public boolean updateUserModel(String username, UserModel model) {\r
-               if (supportsCredentialChanges()) {\r
-                       if (!supportsTeamMembershipChanges()) {\r
+               if (model.isLocalAccount() || supportsCredentialChanges()) {\r
+                       if (!model.isLocalAccount() && !supportsTeamMembershipChanges()) {\r
                                //  teams are externally controlled - copy from original model\r
                                UserModel existingModel = getUserModel(username);\r
                                \r
@@ -188,7 +198,7 @@ public class GitblitUserService implements IUserService {
                if (model.username.equals(username)) {\r
                        // passwords are not persisted by the backing user service\r
                        model.password = null;\r
-                       if (!supportsTeamMembershipChanges()) {\r
+                       if (!model.isLocalAccount() && !supportsTeamMembershipChanges()) {\r
                                //  teams are externally controlled- copy from original model\r
                                UserModel existingModel = getUserModel(username);\r
                                \r
@@ -218,7 +228,11 @@ public class GitblitUserService implements IUserService {
 \r
        @Override\r
        public List<UserModel> getAllUsers() {\r
-               return serviceImpl.getAllUsers();\r
+               List<UserModel> users = serviceImpl.getAllUsers();\r
+       for (UserModel user : users) {\r
+               setAccountType(user);\r
+       }\r
+               return users; \r
        }\r
 \r
        @Override\r
@@ -300,4 +314,25 @@ public class GitblitUserService implements IUserService {
        public boolean deleteRepositoryRole(String role) {\r
                return serviceImpl.deleteRepositoryRole(role);\r
        }\r
+       \r
+       protected boolean isLocalAccount(String username) {\r
+               UserModel user = getUserModel(username);\r
+               return user != null && user.isLocalAccount();\r
+       }\r
+       \r
+       protected void setAccountType(UserModel user) {\r
+               if (user != null) {\r
+                       if (!StringUtils.isEmpty(user.password)\r
+                                       && !ExternalAccount.equalsIgnoreCase(user.password)\r
+                                       && !"StoredInLDAP".equalsIgnoreCase(user.password)) {\r
+                               user.accountType = AccountType.LOCAL;\r
+                       } else {\r
+                               user.accountType = getAccountType();\r
+                       }\r
+               }\r
+       }\r
+       \r
+       protected AccountType getAccountType() {\r
+               return AccountType.LOCAL;\r
+       }\r
 }\r
index 9ce18f6d7ceecaca2ac10f72470e7e70fc7b65b6..3c032b5673895a689e7a360256e29304bd838c77 100644 (file)
@@ -25,6 +25,7 @@ import java.util.List;
 import org.slf4j.Logger;\r
 import org.slf4j.LoggerFactory;\r
 \r
+import com.gitblit.Constants.AccountType;\r
 import com.gitblit.models.TeamModel;\r
 import com.gitblit.models.UserModel;\r
 import com.gitblit.utils.ArrayUtils;\r
@@ -50,9 +51,9 @@ import com.unboundid.util.ssl.TrustAllTrustManager;
 public class LdapUserService extends GitblitUserService {\r
 \r
        public static final Logger logger = LoggerFactory.getLogger(LdapUserService.class);\r
-       \r
-       private IStoredSettings settings;\r
 \r
+       private IStoredSettings settings;\r
+       \r
        public LdapUserService() {\r
                super();\r
        }\r
@@ -155,9 +156,19 @@ public class LdapUserService extends GitblitUserService {
        public boolean supportsTeamMembershipChanges() {\r
                return !settings.getBoolean(Keys.realm.ldap.maintainTeams, false);\r
        }\r
+       \r
+       @Override\r
+       protected AccountType getAccountType() {\r
+                return AccountType.LDAP;\r
+       }\r
 \r
        @Override\r
        public UserModel authenticate(String username, char[] password) {\r
+               if (isLocalAccount(username)) {\r
+                       // local account, bypass LDAP authentication\r
+                       return super.authenticate(username, password);\r
+               }\r
+               \r
                String simpleUsername = getSimpleUsername(username);\r
                \r
                LDAPConnection ldapConnection = getLdapConnection();\r
@@ -239,7 +250,8 @@ public class LdapUserService extends GitblitUserService {
                setAdminAttribute(user);\r
                \r
                // Don't want visibility into the real password, make up a dummy\r
-               user.password = "StoredInLDAP";\r
+               user.password = ExternalAccount;\r
+               user.accountType = getAccountType();\r
                \r
                // Get full name Attribute\r
                String displayName = settings.getString(Keys.realm.ldap.displayName, "");               \r
index b890f21b45b2befe3071a369cb422cc26ccc81c1..2fa14b73e7ddc1bf78b80c24066488bc625ffedb 100644 (file)
@@ -9,7 +9,9 @@ import org.apache.wicket.util.io.IOUtils;
 import org.slf4j.Logger;\r
 import org.slf4j.LoggerFactory;\r
 \r
+import com.gitblit.Constants.AccountType;\r
 import com.gitblit.models.UserModel;\r
+import com.gitblit.utils.ArrayUtils;\r
 import com.gitblit.utils.ConnectionUtils;\r
 import com.gitblit.utils.StringUtils;\r
 import com.google.gson.Gson;\r
@@ -71,9 +73,19 @@ public class RedmineUserService extends GitblitUserService {
     public boolean supportsTeamMembershipChanges() {\r
         return false;\r
     }\r
+    \r
+        @Override\r
+       protected AccountType getAccountType() {\r
+               return AccountType.REDMINE;\r
+       }\r
 \r
     @Override\r
     public UserModel authenticate(String username, char[] password) {\r
+               if (isLocalAccount(username)) {\r
+                       // local account, bypass Redmine authentication\r
+                       return super.authenticate(username, password);\r
+               }\r
+\r
         String urlText = this.settings.getString(Keys.realm.redmine.url, "");\r
         if (!urlText.endsWith("/")) {\r
             urlText.concat("/");\r
@@ -87,19 +99,37 @@ public class RedmineUserService extends GitblitUserService {
             String login = current.user.login;\r
 \r
             boolean canAdmin = true;\r
-            // non admin user can not get login name\r
             if (StringUtils.isEmpty(login)) {\r
-                canAdmin = false;\r
                 login = current.user.mail;\r
+                \r
+               // non admin user can not get login name\r
+               // TODO review this assumption, if it is true, it is undocumented\r
+                canAdmin = false;\r
             }\r
-\r
-            UserModel userModel = new UserModel(login);\r
-            userModel.canAdmin = canAdmin;\r
-            userModel.displayName = current.user.firstname + " " + current.user.lastname;\r
-            userModel.emailAddress = current.user.mail;\r
-            userModel.cookie = StringUtils.getSHA1(userModel.username + new String(password));\r
-\r
-            return userModel;\r
+            \r
+            UserModel user = getUserModel(login);\r
+            if (user == null)  // create user object for new authenticated user\r
+               user = new UserModel(login);\r
+            \r
+            // create a user cookie\r
+                       if (StringUtils.isEmpty(user.cookie) && !ArrayUtils.isEmpty(password)) {\r
+                               user.cookie = StringUtils.getSHA1(user.username + new String(password));\r
+                       }\r
+            \r
+            // update user attributes from Redmine\r
+                       user.accountType = getAccountType();\r
+                       user.canAdmin = canAdmin;\r
+               user.displayName = current.user.firstname + " " + current.user.lastname;\r
+               user.emailAddress = current.user.mail;\r
+               user.password = ExternalAccount;\r
+               \r
+               // TODO Redmine group mapping for administration & teams\r
+               // http://www.redmine.org/projects/redmine/wiki/Rest_Users\r
+               \r
+               // push the changes to the backing user service\r
+               super.updateUserModel(user);\r
+               \r
+            return user;\r
         } catch (IOException e) {\r
             logger.error("authenticate", e);\r
         }\r
@@ -126,5 +156,4 @@ public class RedmineUserService extends GitblitUserService {
     public void setTestingCurrentUserAsJson(String json) {\r
         this.testingJson = json;\r
     }\r
-\r
 }\r
index e14c0010767caa31d99ae0e433cada3961a2b0ee..c53a5791864de2452a8a56a282b425c8d0a6ea5e 100644 (file)
@@ -112,8 +112,8 @@ public abstract class UsersPanel extends JPanel {
                String name = table.getColumnName(UsersTableModel.Columns.Name.ordinal());\r
                table.getColumn(name).setCellRenderer(nameRenderer);\r
                \r
-               int w = 125;\r
-               name = table.getColumnName(UsersTableModel.Columns.AccessLevel.ordinal());\r
+               int w = 130;\r
+               name = table.getColumnName(UsersTableModel.Columns.Type.ordinal());\r
                table.getColumn(name).setMinWidth(w);\r
                table.getColumn(name).setMaxWidth(w);\r
                name = table.getColumnName(UsersTableModel.Columns.Teams.ordinal());\r
index b8ce45d4a046bef2d7f02c115437389942a8c1da..439d5afb21ffd2cbeef2c6c9e6f99be70cf18330 100644 (file)
@@ -36,7 +36,7 @@ public class UsersTableModel extends AbstractTableModel {
        List<UserModel> list;\r
 \r
        enum Columns {\r
-               Name, Display_Name, AccessLevel, Teams, Repositories;\r
+               Name, Display_Name, Type, Teams, Repositories;\r
 \r
                @Override\r
                public String toString() {\r
@@ -71,8 +71,8 @@ public class UsersTableModel extends AbstractTableModel {
                        return Translation.get("gb.name");\r
                case Display_Name:\r
                        return Translation.get("gb.displayName");\r
-               case AccessLevel:\r
-                       return Translation.get("gb.accessLevel");\r
+               case Type:\r
+                       return Translation.get("gb.type");\r
                case Teams:\r
                        return Translation.get("gb.teamMemberships");\r
                case Repositories:\r
@@ -101,11 +101,18 @@ public class UsersTableModel extends AbstractTableModel {
                        return model.username;\r
                case Display_Name:\r
                        return model.displayName;\r
-               case AccessLevel:\r
+               case Type:\r
+                       StringBuilder sb = new StringBuilder();\r
+                       if (model.accountType != null) {\r
+                               sb.append(model.accountType.name());\r
+                       }\r
                        if (model.canAdmin()) {\r
-                               return "administrator";\r
+                               if (sb.length() > 0) {\r
+                                       sb.append(", ");\r
+                               }\r
+                               sb.append("admin");\r
                        }\r
-                       return "";\r
+                       return sb.toString();\r
                case Teams:\r
                        return (model.teams == null || model.teams.size() == 0) ? "" : String\r
                                        .valueOf(model.teams.size());\r
index ac67ff7872b6e2085fea4eaeab2d30fa1676ba88..54e81cb5008b23947997965674cc5f6a6c249543 100644 (file)
@@ -29,6 +29,7 @@ import java.util.TreeSet;
 \r
 import com.gitblit.Constants.AccessPermission;\r
 import com.gitblit.Constants.AccessRestrictionType;\r
+import com.gitblit.Constants.AccountType;\r
 import com.gitblit.Constants.AuthorizationControl;\r
 import com.gitblit.Constants.PermissionType;\r
 import com.gitblit.Constants.RegistrantType;\r
@@ -73,15 +74,22 @@ public class UserModel implements Principal, Serializable, Comparable<UserModel>
 \r
        // non-persisted fields\r
        public boolean isAuthenticated;\r
+       public AccountType accountType;\r
        \r
        public UserModel(String username) {\r
                this.username = username;\r
                this.isAuthenticated = true;\r
+               this.accountType = AccountType.LOCAL;\r
        }\r
 \r
        private UserModel() {\r
                this.username = "$anonymous";\r
                this.isAuthenticated = false;\r
+               this.accountType = AccountType.LOCAL;\r
+       }\r
+       \r
+       public boolean isLocalAccount() {\r
+               return accountType.isLocal();\r
        }\r
 \r
        /**\r
index 9d46908332f24256e874838fec3742fb3bea8da8..9f9813531752473234b473abcce2eed35c7b7988 100644 (file)
@@ -433,7 +433,7 @@ public abstract class BasePage extends WebPage {
                        GitBlitWebSession session = GitBlitWebSession.get();\r
                        if (session.isLoggedIn()) {                             \r
                                UserModel user = session.getUser();\r
-                               boolean editCredentials = GitBlit.self().supportsCredentialChanges();\r
+                               boolean editCredentials = GitBlit.self().supportsCredentialChanges(user);\r
                                boolean standardLogin = session.authenticationType.isStandard();\r
 \r
                                // username, logout, and change password\r
index 5e66300645e52abae968c6e34dac4f4351771e39..3741853f4f32bc41701001e2684ca1906362c1a0 100644 (file)
@@ -51,12 +51,13 @@ public class ChangePasswordPage extends RootSubPage {
                        throw new RestartResponseException(getApplication().getHomePage());\r
                }\r
                \r
-               if (!GitBlit.self().supportsCredentialChanges()) {\r
+               UserModel user = GitBlitWebSession.get().getUser();             \r
+               if (!GitBlit.self().supportsCredentialChanges(user)) {\r
                        error(MessageFormat.format(getString("gb.userServiceDoesNotPermitPasswordChanges"),\r
                                        GitBlit.getString(Keys.realm.userService, "users.conf")), true);\r
                }\r
                \r
-               setupPage(getString("gb.changePassword"), GitBlitWebSession.get().getUsername());\r
+               setupPage(getString("gb.changePassword"), user.username);\r
 \r
                StatelessForm<Void> form = new StatelessForm<Void>("passwordForm") {\r
 \r
index 1991c02a155eb44408bc9075b504d1e8b9fb4a1d..8344d387e1c89bb25934790e7c26202517954fca 100644 (file)
@@ -212,7 +212,7 @@ public class EditTeamPage extends RootSubPage {
                form.add(new SimpleAttributeModifier("autocomplete", "off"));\r
 \r
                // not all user services support manipulating team memberships\r
-               boolean editMemberships = GitBlit.self().supportsTeamMembershipChanges();\r
+               boolean editMemberships = GitBlit.self().supportsTeamMembershipChanges(null);\r
                \r
                // field names reflective match TeamModel fields\r
                form.add(new TextField<String>("name"));\r
index 7a01fb68346aea2e1d94289fee74265247647307..4939e97c22f0b67ce6396c3ba6f166d33401dce5 100644 (file)
@@ -55,7 +55,7 @@ public class EditUserPage extends RootSubPage {
        public EditUserPage() {\r
                // create constructor\r
                super();\r
-               if (!GitBlit.self().supportsCredentialChanges()) {\r
+               if (!GitBlit.self().supportsAddUser()) {\r
                        error(MessageFormat.format(getString("gb.userServiceDoesNotPermitAddUser"),\r
                                        GitBlit.getString(Keys.realm.userService, "users.conf")), true);\r
                }\r
@@ -134,7 +134,7 @@ public class EditUserPage extends RootSubPage {
                                }\r
                                boolean rename = !StringUtils.isEmpty(oldName)\r
                                                && !oldName.equalsIgnoreCase(username);\r
-                               if (GitBlit.self().supportsCredentialChanges()) {\r
+                               if (GitBlit.self().supportsCredentialChanges(userModel)) {\r
                                        if (!userModel.password.equals(confirmPassword.getObject())) {\r
                                                error(getString("gb.passwordsDoNotMatch"));\r
                                                return;\r
@@ -210,16 +210,16 @@ public class EditUserPage extends RootSubPage {
                form.add(new SimpleAttributeModifier("autocomplete", "off"));\r
                \r
                // not all user services support manipulating username and password\r
-               boolean editCredentials = GitBlit.self().supportsCredentialChanges();\r
+               boolean editCredentials = GitBlit.self().supportsCredentialChanges(userModel);\r
                \r
                // not all user services support manipulating display name\r
-               boolean editDisplayName = GitBlit.self().supportsDisplayNameChanges();\r
+               boolean editDisplayName = GitBlit.self().supportsDisplayNameChanges(userModel);\r
 \r
                // not all user services support manipulating email address\r
-               boolean editEmailAddress = GitBlit.self().supportsEmailAddressChanges();\r
+               boolean editEmailAddress = GitBlit.self().supportsEmailAddressChanges(userModel);\r
 \r
                // not all user services support manipulating team memberships\r
-               boolean editTeams = GitBlit.self().supportsTeamMembershipChanges();\r
+               boolean editTeams = GitBlit.self().supportsTeamMembershipChanges(userModel);\r
 \r
                // field names reflective match UserModel fields\r
                form.add(new TextField<String>("username").setEnabled(editCredentials));\r
index cc37c519a14e92c2f7308590a9df8ce369116052..b76388b35a324b5788b8a6d5a837013eef4617a6 100644 (file)
@@ -40,7 +40,7 @@ public class TeamsPanel extends BasePanel {
 \r
                Fragment adminLinks = new Fragment("adminPanel", "adminLinks", this);\r
                adminLinks.add(new BookmarkablePageLink<Void>("newTeam", EditTeamPage.class));\r
-               add(adminLinks.setVisible(showAdmin && GitBlit.self().supportsTeamMembershipChanges()));\r
+               add(adminLinks.setVisible(showAdmin && GitBlit.self().supportsTeamMembershipChanges(null)));\r
 \r
                final List<TeamModel> teams = GitBlit.self().getAllTeams();\r
                DataView<TeamModel> teamsView = new DataView<TeamModel>("teamRow",\r
index aed985c1cd262463246165bbc122c77b338d2319..801596108ef940a876d4b51c45355ed0d0eb0c14 100644 (file)
@@ -17,7 +17,7 @@
                        </th>\r
                        <th class="hidden-phone hidden-tablet left"><wicket:message key="gb.displayName">[display name]</wicket:message></th>\r
                        <th class="hidden-phone hidden-tablet left"><wicket:message key="gb.emailAddress">[email address]</wicket:message></th>\r
-                       <th class="hidden-phone" style="width:120px;"><wicket:message key="gb.accessLevel">[access level]</wicket:message></th>\r
+                       <th class="hidden-phone" style="width:140px;"><wicket:message key="gb.type">[type]</wicket:message></th>\r
                        <th class="hidden-phone" style="width:140px;"><wicket:message key="gb.teamMemberships">[team memberships]</wicket:message></th>\r
                        <th class="hidden-phone" style="width:100px;"><wicket:message key="gb.repositories">[repositories]</wicket:message></th>\r
                        <th style="width:80px;" class="right"></th>\r
@@ -27,7 +27,7 @@
                                <td class="left" ><span class="list" wicket:id="username">[username]</span></td>\r
                                <td class="hidden-phone hidden-tablet left" ><span class="list" wicket:id="displayName">[display name]</span></td>\r
                                <td class="hidden-phone hidden-tablet left" ><span class="list" wicket:id="emailAddress">[email address]</span></td>\r
-                               <td class="hidden-phone left" ><span class="list" wicket:id="accesslevel">[access level]</span></td>\r
+                               <td class="hidden-phone left" ><span style="font-size: 0.8em;" wicket:id="accountType">[account type]</span></td>\r
                                <td class="hidden-phone left" ><span class="list" wicket:id="teams">[team memberships]</span></td>\r
                                <td class="hidden-phone left" ><span class="list" wicket:id="repositories">[repositories]</span></td>\r
                                <td class="rightAlign"><span wicket:id="userLinks"></span></td>                         \r
index 46c502e5749508ffb53a2c6371372c5efcc7fba0..f5b95e2033d3233c31e3f58caf5fcf9f9a32cc8d 100644 (file)
@@ -41,7 +41,7 @@ public class UsersPanel extends BasePanel {
 \r
                Fragment adminLinks = new Fragment("adminPanel", "adminLinks", this);\r
                adminLinks.add(new BookmarkablePageLink<Void>("newUser", EditUserPage.class)\r
-                               .setVisible(GitBlit.self().supportsCredentialChanges()));\r
+                               .setVisible(GitBlit.self().supportsAddUser()));\r
                add(adminLinks.setVisible(showAdmin));\r
 \r
                final List<UserModel> users = GitBlit.self().getAllUsers();\r
@@ -81,7 +81,7 @@ public class UsersPanel extends BasePanel {
                                        item.add(editLink);\r
                                }\r
 \r
-                               item.add(new Label("accesslevel", entry.canAdmin() ? "administrator" : ""));\r
+                               item.add(new Label("accountType", entry.accountType.name() + (entry.canAdmin() ? ", admin":"")));\r
                                item.add(new Label("teams", entry.teams.size() > 0 ? ("" + entry.teams.size()) : ""));\r
                                item.add(new Label("repositories",\r
                                                entry.permissions.size() > 0 ? ("" + entry.permissions.size()) : ""));\r
index ffe826403c40e280f99b430931e8efc4e1fd8adb..a928f4a57d1a1f2984361bedeefbb19b100d5414 100644 (file)
@@ -31,6 +31,7 @@ import org.junit.Test;
 import com.gitblit.LdapUserService;
 import com.gitblit.models.UserModel;
 import com.gitblit.tests.mock.MemorySettings;
+import com.gitblit.utils.StringUtils;
 import com.unboundid.ldap.listener.InMemoryDirectoryServer;
 import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
 import com.unboundid.ldap.listener.InMemoryListenerConfig;
@@ -154,5 +155,20 @@ public class LdapUserServiceTest {
                UserModel userOneModel = ldapUserService.authenticate("*)(userPassword=userOnePassword", "userOnePassword".toCharArray());
                assertNull(userOneModel);
        }
+       
+       @Test
+       public void testLocalAccount() {
+               UserModel localAccount = new UserModel("bruce");
+               localAccount.displayName = "Bruce Campbell";
+               localAccount.password = StringUtils.MD5_TYPE + StringUtils.getMD5("gimmesomesugar");
+               ldapUserService.deleteUser(localAccount.username);
+               assertTrue("Failed to add local account",
+                               ldapUserService.updateUserModel(localAccount));
+               assertEquals("Accounts are not equal!", 
+                               localAccount, 
+                               ldapUserService.authenticate(localAccount.username, "gimmesomesugar".toCharArray()));
+               assertTrue("Failed to delete local account!",
+                               ldapUserService.deleteUser(localAccount.username));
+       }
 
 }
index 30a8fb2085d0e78f5ecab742af8ad2415179b14e..0e12542db11d38bab50c6c85bdce2e2df6637c9f 100644 (file)
@@ -1,9 +1,10 @@
 package com.gitblit.tests;\r
 \r
 import static org.hamcrest.CoreMatchers.is;\r
+import static org.junit.Assert.assertEquals;\r
 import static org.junit.Assert.assertNotNull;\r
-import static org.junit.Assert.assertNull;\r
 import static org.junit.Assert.assertThat;\r
+import static org.junit.Assert.assertTrue;\r
 \r
 import java.util.HashMap;\r
 \r
@@ -12,6 +13,7 @@ import org.junit.Test;
 import com.gitblit.RedmineUserService;\r
 import com.gitblit.models.UserModel;\r
 import com.gitblit.tests.mock.MemorySettings;\r
+import com.gitblit.utils.StringUtils;\r
 \r
 public class RedmineUserServiceTest {\r
 \r
@@ -29,7 +31,7 @@ public class RedmineUserServiceTest {
         redmineUserService.setup(new MemorySettings(new HashMap<String, Object>()));\r
         redmineUserService.setTestingCurrentUserAsJson(JSON);\r
         UserModel userModel = redmineUserService.authenticate("RedmineUserId", "RedmineAPIKey".toCharArray());\r
-        assertThat(userModel.getName(), is("RedmineUserId"));\r
+        assertThat(userModel.getName(), is("redmineuserid"));\r
         assertThat(userModel.getDisplayName(), is("baz foo"));\r
         assertThat(userModel.emailAddress, is("baz@example.com"));\r
         assertNotNull(userModel.cookie);\r
@@ -48,5 +50,23 @@ public class RedmineUserServiceTest {
         assertNotNull(userModel.cookie);\r
         assertThat(userModel.canAdmin, is(false));\r
     }\r
+    \r
+    @Test\r
+       public void testLocalAccount() {\r
+        RedmineUserService redmineUserService = new RedmineUserService();\r
+        redmineUserService.setup(new MemorySettings(new HashMap<String, Object>()));\r
+\r
+               UserModel localAccount = new UserModel("bruce");\r
+               localAccount.displayName = "Bruce Campbell";\r
+               localAccount.password = StringUtils.MD5_TYPE + StringUtils.getMD5("gimmesomesugar");\r
+               redmineUserService.deleteUser(localAccount.username);\r
+               assertTrue("Failed to add local account",\r
+                               redmineUserService.updateUserModel(localAccount));\r
+               assertEquals("Accounts are not equal!", \r
+                               localAccount, \r
+                               redmineUserService.authenticate(localAccount.username, "gimmesomesugar".toCharArray()));\r
+               assertTrue("Failed to delete local account!",\r
+                               redmineUserService.deleteUser(localAccount.username));\r
+       }\r
 \r
 }\r