From 20714aee0d2d2a989d93d6065e081aed8ac85fbf Mon Sep 17 00:00:00 2001 From: James Moger <james.moger@gitblit.com> Date: Wed, 10 Oct 2012 00:05:34 -0400 Subject: [PATCH] Finer-grained repository access permissions (issue 36) --- src/com/gitblit/models/TeamModel.java | 135 ++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 128 insertions(+), 7 deletions(-) diff --git a/src/com/gitblit/models/TeamModel.java b/src/com/gitblit/models/TeamModel.java index 3d176e5..d185b9d 100644 --- a/src/com/gitblit/models/TeamModel.java +++ b/src/com/gitblit/models/TeamModel.java @@ -18,9 +18,15 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.Collection; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; + +import com.gitblit.Constants.AccessPermission; +import com.gitblit.Constants.AccessRestrictionType; +import com.gitblit.Constants.Unused; /** * TeamModel is a serializable model class that represents a group of users and @@ -36,7 +42,10 @@ // field names are reflectively mapped in EditTeam page public String name; public final Set<String> users = new HashSet<String>(); + // retained for backwards-compatibility with RPC clients + @Deprecated public final Set<String> repositories = new HashSet<String>(); + public final Map<String, AccessPermission> permissions = new HashMap<String, AccessPermission>(); public final Set<String> mailingLists = new HashSet<String>(); public final List<String> preReceiveScripts = new ArrayList<String>(); public final List<String> postReceiveScripts = new ArrayList<String>(); @@ -45,24 +54,136 @@ this.name = name; } + /** + * @use hasRepositoryPermission + * @param name + * @return + */ + @Deprecated + @Unused public boolean hasRepository(String name) { - return repositories.contains(name.toLowerCase()); + return hasRepositoryPermission(name); } + @Deprecated + @Unused public void addRepository(String name) { - repositories.add(name.toLowerCase()); + addRepositoryPermission(name); } + @Deprecated + @Unused public void addRepositories(Collection<String> names) { - for (String name:names) { - repositories.add(name.toLowerCase()); - } - } + addRepositoryPermissions(names); + } + @Deprecated + @Unused public void removeRepository(String name) { - repositories.remove(name.toLowerCase()); + removeRepositoryPermission(name); } + /** + * Returns true if the team has any type of specified access permission for + * this repository. + * + * @param name + * @return true if team has a specified access permission for the repository + */ + public boolean hasRepositoryPermission(String name) { + String repository = AccessPermission.repositoryFromRole(name).toLowerCase(); + return permissions.containsKey(repository) || repositories.contains(repository); + } + + /** + * Adds a repository permission to the team. + * <p> + * Role may be formatted as: + * <ul> + * <li> myrepo.git <i>(this is implicitly RW+)</i> + * <li> RW+:myrepo.git + * </ul> + * @param role + */ + public void addRepositoryPermission(String role) { + AccessPermission permission = AccessPermission.permissionFromRole(role); + String repository = AccessPermission.repositoryFromRole(role).toLowerCase(); + repositories.add(repository); + permissions.put(repository, permission); + } + + public void addRepositoryPermissions(Collection<String> roles) { + for (String role:roles) { + addRepositoryPermission(role); + } + } + + public AccessPermission removeRepositoryPermission(String name) { + String repository = AccessPermission.repositoryFromRole(name).toLowerCase(); + repositories.remove(repository); + return permissions.remove(repository); + } + + public void setRepositoryPermission(String repository, AccessPermission permission) { + permissions.put(repository.toLowerCase(), permission); + repositories.add(repository.toLowerCase()); + } + + public AccessPermission getRepositoryPermission(RepositoryModel repository) { + AccessPermission permission = AccessPermission.NONE; + if (permissions.containsKey(repository.name.toLowerCase())) { + AccessPermission p = permissions.get(repository.name.toLowerCase()); + if (p != null) { + permission = p; + } + } + return permission; + } + + private boolean canAccess(RepositoryModel repository, AccessRestrictionType ifRestriction, AccessPermission requirePermission) { + if (repository.accessRestriction.atLeast(ifRestriction)) { + AccessPermission permission = getRepositoryPermission(repository); + return permission.atLeast(requirePermission); + } + return true; + } + + public boolean canView(RepositoryModel repository) { + return canAccess(repository, AccessRestrictionType.VIEW, AccessPermission.VIEW); + } + + public boolean canClone(RepositoryModel repository) { + return canAccess(repository, AccessRestrictionType.CLONE, AccessPermission.CLONE); + } + + public boolean canPush(RepositoryModel repository) { + if (repository.isFrozen) { + return false; + } + return canAccess(repository, AccessRestrictionType.PUSH, AccessPermission.PUSH); + } + + public boolean canCreateRef(RepositoryModel repository) { + if (repository.isFrozen) { + return false; + } + return canAccess(repository, AccessRestrictionType.PUSH, AccessPermission.CREATE); + } + + public boolean canDeleteRef(RepositoryModel repository) { + if (repository.isFrozen) { + return false; + } + return canAccess(repository, AccessRestrictionType.PUSH, AccessPermission.DELETE); + } + + public boolean canRewindRef(RepositoryModel repository) { + if (repository.isFrozen) { + return false; + } + return canAccess(repository, AccessRestrictionType.PUSH, AccessPermission.REWIND); + } + public boolean hasUser(String name) { return users.contains(name.toLowerCase()); } -- Gitblit v1.9.1