James Moger
2012-11-23 e8c417f4e63f84ac6e14f6d5540dcb1f0f9862fc
src/com/gitblit/ConfigUserService.java
@@ -33,6 +33,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.gitblit.Constants.AccessPermission;
import com.gitblit.models.TeamModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.ArrayUtils;
@@ -64,6 +65,16 @@
   private static final String DISPLAYNAME = "displayName";
   
   private static final String EMAILADDRESS = "emailAddress";
   private static final String ORGANIZATIONALUNIT = "organizationalUnit";
   private static final String ORGANIZATION = "organization";
   private static final String LOCALITY = "locality";
   private static final String STATEPROVINCE = "stateProvince";
   private static final String COUNTRYCODE = "countryCode";
   
   private static final String COOKIE = "cookie";
@@ -268,6 +279,55 @@
   }
   /**
    * Updates/writes all specified user objects.
    *
    * @param models a list of user models
    * @return true if update is successful
    * @since 1.2.0
    */
   @Override
   public boolean updateUserModels(List<UserModel> models) {
      try {
         read();
         for (UserModel model : models) {
            UserModel originalUser = users.remove(model.username.toLowerCase());
            users.put(model.username.toLowerCase(), model);
            // null check on "final" teams because JSON-sourced UserModel
            // can have a null teams object
            if (model.teams != null) {
               for (TeamModel team : model.teams) {
                  TeamModel t = teams.get(team.name.toLowerCase());
                  if (t == null) {
                     // new team
                     team.addUser(model.username);
                     teams.put(team.name.toLowerCase(), team);
                  } else {
                     // do not clobber existing team definition
                     // maybe because this is a federated user
                     t.addUser(model.username);
                  }
               }
               // check for implicit team removal
               if (originalUser != null) {
                  for (TeamModel team : originalUser.teams) {
                     if (!model.isTeamMember(team.name)) {
                        team.removeUser(model.username);
                     }
                  }
               }
            }
         }
         write();
         return true;
      } catch (Throwable t) {
         logger.error(MessageFormat.format("Failed to update user {0} models!", models.size()),
               t);
      }
      return false;
   }
   /**
    * Updates/writes and replaces a complete user object keyed by username.
    * This method allows for renaming a user.
    * 
@@ -413,7 +473,7 @@
         read();
         for (Map.Entry<String, TeamModel> entry : teams.entrySet()) {
            TeamModel model = entry.getValue();
            if (model.hasRepository(role)) {
            if (model.hasRepositoryPermission(role)) {
               list.add(model.name);
            }
         }
@@ -447,10 +507,10 @@
         for (TeamModel team : teams.values()) {
            // team has role, check against revised team list
            if (specifiedTeams.contains(team.name.toLowerCase())) {
               team.addRepository(role);
               team.addRepositoryPermission(role);
            } else {
               // remove role from team
               team.removeRepository(role);
               team.removeRepositoryPermission(role);
            }
         }
@@ -492,6 +552,28 @@
   @Override
   public boolean updateTeamModel(TeamModel model) {
      return updateTeamModel(model.name, model);
   }
   /**
    * Updates/writes all specified team objects.
    *
    * @param models a list of team models
    * @return true if update is successful
    * @since 1.2.0
    */
   @Override
   public boolean updateTeamModels(List<TeamModel> models) {
      try {
         read();
         for (TeamModel team : models) {
            teams.put(team.name.toLowerCase(), team);
         }
         write();
         return true;
      } catch (Throwable t) {
         logger.error(MessageFormat.format("Failed to update team {0} models!", models.size()), t);
      }
      return false;
   }
   /**
@@ -602,7 +684,7 @@
         read();
         for (Map.Entry<String, UserModel> entry : users.entrySet()) {
            UserModel model = entry.getValue();
            if (model.hasRepository(role)) {
            if (model.hasRepositoryPermission(role)) {
               list.add(model.username);
            }
         }
@@ -623,6 +705,7 @@
    * @return true if successful
    */
   @Override
   @Deprecated
   public boolean setUsernamesForRepositoryRole(String role, List<String> usernames) {
      try {
         Set<String> specifiedUsers = new HashSet<String>();
@@ -636,10 +719,10 @@
         for (UserModel user : users.values()) {
            // user has role, check against revised user list
            if (specifiedUsers.contains(user.username.toLowerCase())) {
               user.addRepository(role);
               user.addRepositoryPermission(role);
            } else {
               // remove role from user
               user.removeRepository(role);
               user.removeRepositoryPermission(role);
            }
         }
@@ -665,17 +748,17 @@
         read();
         // identify users which require role rename
         for (UserModel model : users.values()) {
            if (model.hasRepository(oldRole)) {
               model.removeRepository(oldRole);
               model.addRepository(newRole);
            if (model.hasRepositoryPermission(oldRole)) {
               AccessPermission permission = model.removeRepositoryPermission(oldRole);
               model.setRepositoryPermission(newRole, permission);
            }
         }
         // identify teams which require role rename
         for (TeamModel model : teams.values()) {
            if (model.hasRepository(oldRole)) {
               model.removeRepository(oldRole);
               model.addRepository(newRole);
            if (model.hasRepositoryPermission(oldRole)) {
               AccessPermission permission = model.removeRepositoryPermission(oldRole);
               model.setRepositoryPermission(newRole, permission);
            }
         }
         // persist changes
@@ -701,12 +784,12 @@
         // identify users which require role rename
         for (UserModel user : users.values()) {
            user.removeRepository(role);
            user.removeRepositoryPermission(role);
         }
         // identify teams which require role rename
         for (TeamModel team : teams.values()) {
            team.removeRepository(role);
            team.removeRepositoryPermission(role);
         }
         // persist changes
@@ -744,6 +827,21 @@
         if (!StringUtils.isEmpty(model.emailAddress)) {
            config.setString(USER, model.username, EMAILADDRESS, model.emailAddress);
         }
         if (!StringUtils.isEmpty(model.organizationalUnit)) {
            config.setString(USER, model.username, ORGANIZATIONALUNIT, model.organizationalUnit);
         }
         if (!StringUtils.isEmpty(model.organization)) {
            config.setString(USER, model.username, ORGANIZATION, model.organization);
         }
         if (!StringUtils.isEmpty(model.locality)) {
            config.setString(USER, model.username, LOCALITY, model.locality);
         }
         if (!StringUtils.isEmpty(model.stateProvince)) {
            config.setString(USER, model.username, STATEPROVINCE, model.stateProvince);
         }
         if (!StringUtils.isEmpty(model.countryCode)) {
            config.setString(USER, model.username, COUNTRYCODE, model.countryCode);
         }
         // user roles
         List<String> roles = new ArrayList<String>();
@@ -752,6 +850,9 @@
         }
         if (model.canFork) {
            roles.add(Constants.FORK_ROLE);
         }
         if (model.canCreate) {
            roles.add(Constants.CREATE_ROLE);
         }
         if (model.excludeFromFederation) {
            roles.add(Constants.NOT_FEDERATED_ROLE);
@@ -764,22 +865,58 @@
         }
         config.setStringList(USER, model.username, ROLE, roles);
         // repository memberships
         // null check on "final" repositories because JSON-sourced UserModel
         // can have a null repositories object
         if (!ArrayUtils.isEmpty(model.repositories)) {
            config.setStringList(USER, model.username, REPOSITORY, new ArrayList<String>(
                  model.repositories));
         // discrete repository permissions
         if (model.permissions != null && !model.canAdmin) {
            List<String> permissions = new ArrayList<String>();
            for (Map.Entry<String, AccessPermission> entry : model.permissions.entrySet()) {
               if (entry.getValue().exceeds(AccessPermission.NONE)) {
                  permissions.add(entry.getValue().asRole(entry.getKey()));
               }
            }
            config.setStringList(USER, model.username, REPOSITORY, permissions);
         }
      }
      // write teams
      for (TeamModel model : teams.values()) {
         // null check on "final" repositories because JSON-sourced TeamModel
         // can have a null repositories object
         if (!ArrayUtils.isEmpty(model.repositories)) {
            config.setStringList(TEAM, model.name, REPOSITORY, new ArrayList<String>(
                  model.repositories));
         // team roles
         List<String> roles = new ArrayList<String>();
         if (model.canAdmin) {
            roles.add(Constants.ADMIN_ROLE);
         }
         if (model.canFork) {
            roles.add(Constants.FORK_ROLE);
         }
         if (model.canCreate) {
            roles.add(Constants.CREATE_ROLE);
         }
         if (roles.size() == 0) {
            // we do this to ensure that team record is written.
            // Otherwise, StoredConfig might optimizes that record away.
            roles.add(Constants.NO_ROLE);
         }
         config.setStringList(TEAM, model.name, ROLE, roles);
         if (!model.canAdmin) {
            // write team permission for non-admin teams
            if (model.permissions == null) {
               // null check on "final" repositories because JSON-sourced TeamModel
               // can have a null repositories object
               if (!ArrayUtils.isEmpty(model.repositories)) {
                  config.setStringList(TEAM, model.name, REPOSITORY, new ArrayList<String>(
                        model.repositories));
               }
            } else {
               // discrete repository permissions
               List<String> permissions = new ArrayList<String>();
               for (Map.Entry<String, AccessPermission> entry : model.permissions.entrySet()) {
                  if (entry.getValue().exceeds(AccessPermission.NONE)) {
                     // code:repository (e.g. RW+:~james/myrepo.git
                     permissions.add(entry.getValue().asRole(entry.getKey()));
                  }
               }
               config.setStringList(TEAM, model.name, REPOSITORY, permissions);
            }
         }
         // null check on "final" users because JSON-sourced TeamModel
@@ -852,6 +989,11 @@
               user.password = config.getString(USER, username, PASSWORD);               
               user.displayName = config.getString(USER, username, DISPLAYNAME);
               user.emailAddress = config.getString(USER, username, EMAILADDRESS);
               user.organizationalUnit = config.getString(USER, username, ORGANIZATIONALUNIT);
               user.organization = config.getString(USER, username, ORGANIZATION);
               user.locality = config.getString(USER, username, LOCALITY);
               user.stateProvince = config.getString(USER, username, STATEPROVINCE);
               user.countryCode = config.getString(USER, username, COUNTRYCODE);
               user.cookie = config.getString(USER, username, COOKIE);
               if (StringUtils.isEmpty(user.cookie) && !StringUtils.isEmpty(user.password)) {
                  user.cookie = StringUtils.getSHA1(user.username + user.password);
@@ -862,13 +1004,17 @@
                     USER, username, ROLE)));
               user.canAdmin = roles.contains(Constants.ADMIN_ROLE);
               user.canFork = roles.contains(Constants.FORK_ROLE);
               user.canCreate = roles.contains(Constants.CREATE_ROLE);
               user.excludeFromFederation = roles.contains(Constants.NOT_FEDERATED_ROLE);
               // repository memberships
               Set<String> repositories = new HashSet<String>(Arrays.asList(config
                     .getStringList(USER, username, REPOSITORY)));
               for (String repository : repositories) {
                  user.addRepository(repository);
               if (!user.canAdmin) {
                  // non-admin, read permissions
                  Set<String> repositories = new HashSet<String>(Arrays.asList(config
                        .getStringList(USER, username, REPOSITORY)));
                  for (String repository : repositories) {
                     user.addRepositoryPermission(repository);
                  }
               }
               // update cache
@@ -882,8 +1028,17 @@
            Set<String> teamnames = config.getSubsections(TEAM);
            for (String teamname : teamnames) {
               TeamModel team = new TeamModel(teamname);
               team.addRepositories(Arrays.asList(config.getStringList(TEAM, teamname,
                     REPOSITORY)));
               Set<String> roles = new HashSet<String>(Arrays.asList(config.getStringList(
                     TEAM, teamname, ROLE)));
               team.canAdmin = roles.contains(Constants.ADMIN_ROLE);
               team.canFork = roles.contains(Constants.FORK_ROLE);
               team.canCreate = roles.contains(Constants.CREATE_ROLE);
               if (!team.canAdmin) {
                  // non-admin team, read permissions
                  team.addRepositoryPermissions(Arrays.asList(config.getStringList(TEAM, teamname,
                        REPOSITORY)));
               }
               team.addUsers(Arrays.asList(config.getStringList(TEAM, teamname, USER)));
               team.addMailingLists(Arrays.asList(config.getStringList(TEAM, teamname,
                     MAILINGLIST)));