From 27ae9095639bb228a1b7ff86a3ebe4264abf05be Mon Sep 17 00:00:00 2001
From: mschaefers <mschaefers@scoop-gmbh.de>
Date: Thu, 29 Nov 2012 12:33:09 -0500
Subject: [PATCH] feature: when using LdapUserService one can configure Gitblit to fetch all users from ldap that can possibly login. This allows to see newly generated LDAP users instantly in Gitblit. By now an LDAP user had to log in once to appear in GitBlit.
---
src/com/gitblit/ConfigUserService.java | 221 +++++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 190 insertions(+), 31 deletions(-)
diff --git a/src/com/gitblit/ConfigUserService.java b/src/com/gitblit/ConfigUserService.java
index faad691..068bbe3 100644
--- a/src/com/gitblit/ConfigUserService.java
+++ b/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,11 +827,32 @@
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>();
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 (model.excludeFromFederation) {
roles.add(Constants.NOT_FEDERATED_ROLE);
@@ -761,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
@@ -849,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);
@@ -858,13 +1003,18 @@
Set<String> roles = new HashSet<String>(Arrays.asList(config.getStringList(
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
@@ -878,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)));
--
Gitblit v1.9.1