/* * Copyright 2011 gitblit.com. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.gitblit.models; import java.io.Serializable; import java.security.Principal; import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; import com.gitblit.Constants.AccessPermission; import com.gitblit.Constants.AccessRestrictionType; import com.gitblit.Constants.AuthorizationControl; import com.gitblit.Constants.Unused; import com.gitblit.utils.StringUtils; /** * UserModel is a serializable model class that represents a user and the user's * restricted repository memberships. Instances of UserModels are also used as * servlet user principals. * * @author James Moger * */ public class UserModel implements Principal, Serializable, Comparable { private static final long serialVersionUID = 1L; public static final UserModel ANONYMOUS = new UserModel(); // field names are reflectively mapped in EditUser page public String username; public String password; public String cookie; public String displayName; public String emailAddress; public boolean canAdmin; public boolean canFork; public boolean canCreate; public boolean excludeFromFederation; // retained for backwards-compatibility with RPC clients @Deprecated public final Set repositories = new HashSet(); public final Map permissions = new HashMap(); public final Set teams = new HashSet(); // non-persisted fields public boolean isAuthenticated; public UserModel(String username) { this.username = username; this.isAuthenticated = true; } private UserModel() { this.username = "$anonymous"; this.isAuthenticated = false; } /** * This method does not take into consideration Ownership where the * administrator has not explicitly granted access to the owner. * * @param repositoryName * @return */ @Deprecated public boolean canAccessRepository(String repositoryName) { return canAdmin || repositories.contains(repositoryName.toLowerCase()) || hasTeamAccess(repositoryName); } @Deprecated @Unused public boolean canAccessRepository(RepositoryModel repository) { boolean isOwner = !StringUtils.isEmpty(repository.owner) && repository.owner.equals(username); boolean allowAuthenticated = isAuthenticated && AuthorizationControl.AUTHENTICATED.equals(repository.authorizationControl); return canAdmin || isOwner || repositories.contains(repository.name.toLowerCase()) || hasTeamAccess(repository.name) || allowAuthenticated; } @Deprecated @Unused public boolean hasTeamAccess(String repositoryName) { for (TeamModel team : teams) { if (team.hasRepositoryPermission(repositoryName)) { return true; } } return false; } @Deprecated @Unused public boolean hasRepository(String name) { return hasRepositoryPermission(name); } @Deprecated @Unused public void addRepository(String name) { addRepositoryPermission(name); } @Deprecated @Unused public void removeRepository(String name) { removeRepositoryPermission(name); } /** * Returns true if the user has any type of specified access permission for * this repository. * * @param name * @return true if user 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. *

* Role may be formatted as: *

    *
  • myrepo.git (this is implicitly RW+) *
  • RW+:myrepo.git *
* @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 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); } public AccessPermission getRepositoryPermission(RepositoryModel repository) { if (canAdmin || repository.isOwner(username) || repository.isUsersPersonalRepository(username)) { return AccessPermission.REWIND; } if (AuthorizationControl.AUTHENTICATED.equals(repository.authorizationControl) && isAuthenticated) { // AUTHENTICATED is a shortcut for authorizing all logged-in users RW access return AccessPermission.REWIND; } // determine best permission available based on user's personal permissions // and the permissions of teams of which the user belongs AccessPermission permission = AccessPermission.NONE; if (permissions.containsKey(repository.name.toLowerCase())) { // exact repository permission specified AccessPermission p = permissions.get(repository.name.toLowerCase()); if (p != null) { permission = p; } } else { // search for regex permission match for (String key : permissions.keySet()) { if (repository.name.matches(key)) { AccessPermission p = permissions.get(key); if (p != null) { permission = p; } } } } for (TeamModel team : teams) { AccessPermission p = team.getRepositoryPermission(repository); if (permission == null || p.exceeds(permission)) { // use team permission 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 canFork(RepositoryModel repository) { if (repository.isUsersPersonalRepository(username)) { // can not fork your own repository return false; } if (canAdmin || repository.isOwner(username)) { return true; } if (!repository.allowForks) { return false; } if (!isAuthenticated || !canFork) { return false; } return canClone(repository); } public boolean canDelete(RepositoryModel model) { return canAdmin || model.isUsersPersonalRepository(username); } public boolean canEdit(RepositoryModel model) { return canAdmin || model.isUsersPersonalRepository(username) || model.isOwner(username); } public boolean isTeamMember(String teamname) { for (TeamModel team : teams) { if (team.name.equalsIgnoreCase(teamname)) { return true; } } return false; } public TeamModel getTeam(String teamname) { if (teams == null) { return null; } for (TeamModel team : teams) { if (team.name.equalsIgnoreCase(teamname)) { return team; } } return null; } @Override public String getName() { return username; } public String getDisplayName() { if (StringUtils.isEmpty(displayName)) { return username; } return displayName; } public String getPersonalPath() { return "~" + username; } @Override public int hashCode() { return username.hashCode(); } @Override public boolean equals(Object o) { if (o instanceof UserModel) { return username.equals(((UserModel) o).username); } return false; } @Override public String toString() { return username; } @Override public int compareTo(UserModel o) { return username.compareTo(o.username); } }