From f76fee63ed9cb3a30d3c0c092d860b1cb93a481b Mon Sep 17 00:00:00 2001
From: Gerard Smyth <gerard.smyth@gmail.com>
Date: Thu, 08 May 2014 13:09:30 -0400
Subject: [PATCH] Updated the SyndicationServlet to provide an additional option to return details of the tags in the repository instead of the commits. This uses a new 'ot' request parameter to indicate the object type of the content to return, which can be ither TAG or COMMIT. If this is not provided, then COMMIT is assumed to maintain backwards compatability. If tags are returned, then the paging parameters, 'l' and 'pg' are still supported, but searching options are currently ignored.

---
 src/main/java/com/gitblit/models/UserModel.java |  227 ++++++++++++++++++++++++++++----------------------------
 1 files changed, 112 insertions(+), 115 deletions(-)

diff --git a/src/main/java/com/gitblit/models/UserModel.java b/src/main/java/com/gitblit/models/UserModel.java
index e4c659c..e152274 100644
--- a/src/main/java/com/gitblit/models/UserModel.java
+++ b/src/main/java/com/gitblit/models/UserModel.java
@@ -27,30 +27,31 @@
 import java.util.Set;
 import java.util.TreeSet;
 
+import com.gitblit.Constants;
 import com.gitblit.Constants.AccessPermission;
 import com.gitblit.Constants.AccessRestrictionType;
 import com.gitblit.Constants.AccountType;
 import com.gitblit.Constants.AuthorizationControl;
 import com.gitblit.Constants.PermissionType;
 import com.gitblit.Constants.RegistrantType;
-import com.gitblit.Constants.Unused;
 import com.gitblit.utils.ArrayUtils;
+import com.gitblit.utils.ModelUtils;
 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<UserModel> {
 
 	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;
@@ -66,6 +67,7 @@
 	public boolean canFork;
 	public boolean canCreate;
 	public boolean excludeFromFederation;
+	public boolean disabled;
 	// retained for backwards-compatibility with RPC clients
 	@Deprecated
 	public final Set<String> repositories = new HashSet<String>();
@@ -75,78 +77,33 @@
 	// non-persisted fields
 	public boolean isAuthenticated;
 	public AccountType accountType;
-	
+
+	public UserPreferences userPreferences;
+
 	public UserModel(String username) {
 		this.username = username;
 		this.isAuthenticated = true;
 		this.accountType = AccountType.LOCAL;
+		this.userPreferences = new UserPreferences(this.username);
 	}
 
 	private UserModel() {
 		this.username = "$anonymous";
 		this.isAuthenticated = false;
 		this.accountType = AccountType.LOCAL;
+		this.userPreferences = new UserPreferences(this.username);
 	}
-	
+
 	public boolean isLocalAccount() {
-		return accountType.isLocal();
+		return !Constants.EXTERNAL_ACCOUNT.equals(password)
+				|| accountType == null
+				|| accountType.isLocal();
 	}
 
-	/**
-	 * 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 = repository.isOwner(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 a list of repository permissions for this user exclusive of
 	 * permissions inherited from team memberships.
-	 * 
+	 *
 	 * @return the user's list of permissions
 	 */
 	public List<RegistrantAccessPermission> getRepositoryPermissions() {
@@ -173,7 +130,7 @@
 			list.add(new RegistrantAccessPermission(registrant, ap, pType, RegistrantType.REPOSITORY, source, mutable));
 		}
 		Collections.sort(list);
-		
+
 		// include immutable team permissions, being careful to preserve order
 		Set<RegistrantAccessPermission> set = new LinkedHashSet<RegistrantAccessPermission>(list);
 		for (TeamModel team : teams) {
@@ -188,11 +145,11 @@
 		}
 		return new ArrayList<RegistrantAccessPermission>(set);
 	}
-	
+
 	/**
 	 * 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
 	 */
@@ -214,11 +171,11 @@
 		}
 		return false;
 	}
-	
+
 	/**
 	 * Returns true if the user has an explicitly specified access permission for
 	 * this repository.
-	 * 
+	 *
 	 * @param name
 	 * @return if the user has an explicitly specified access permission
 	 */
@@ -226,11 +183,11 @@
 		String repository = AccessPermission.repositoryFromRole(name).toLowerCase();
 		return permissions.containsKey(repository);
 	}
-	
+
 	/**
 	 * Returns true if the user's team memberships specify an access permission for
 	 * this repository.
-	 * 
+	 *
 	 * @param name
 	 * @return if the user's team memberships specifi an access permission
 	 */
@@ -244,7 +201,7 @@
 		}
 		return false;
 	}
-	
+
 	/**
 	 * Adds a repository permission to the team.
 	 * <p>
@@ -261,15 +218,21 @@
 		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);
+		if (permission == null) {
+			// remove the permission
+			permissions.remove(repository.toLowerCase());
+		} else {
+			// set the new permission
+			permissions.put(repository.toLowerCase(), permission);
+		}
 	}
 
 	public RegistrantAccessPermission getRepositoryPermission(RepositoryModel repository) {
@@ -278,10 +241,10 @@
 		ap.registrantType = RegistrantType.USER;
 		ap.permission = AccessPermission.NONE;
 		ap.mutable = false;
-		
+
 		// determine maximum permission for the repository
-		final AccessPermission maxPermission = 
-				(repository.isFrozen || !repository.isBare) ?
+		final AccessPermission maxPermission =
+				(repository.isFrozen || !repository.isBare || repository.isMirror) ?
 						AccessPermission.CLONE : AccessPermission.REWIND;
 
 		if (AccessRestrictionType.NONE.equals(repository.accessRestriction)) {
@@ -314,7 +277,7 @@
 			}
 			return ap;
 		}
-		
+
 		// repository owner - either specified owner or personal repository
 		if (repository.isOwner(username) || repository.isUsersPersonalRepository(username)) {
 			ap.permissionType = PermissionType.OWNER;
@@ -325,7 +288,7 @@
 			}
 			return ap;
 		}
-		
+
 		if (AuthorizationControl.AUTHENTICATED.equals(repository.authorizationControl) && isAuthenticated) {
 			// AUTHENTICATED is a shortcut for authorizing all logged-in users RW+ access
 			if (AccessPermission.REWIND.atMost(maxPermission)) {
@@ -335,7 +298,7 @@
 			}
 			return ap;
 		}
-		
+
 		// explicit user permission OR user regex match is used
 		// if that fails, then the best team permission is used
 		if (permissions.containsKey(repository.name.toLowerCase())) {
@@ -370,7 +333,7 @@
 				}
 			}
 		}
-		
+
 		// try to find a team match
 		for (TeamModel team : teams) {
 			RegistrantAccessPermission p = team.getRepositoryPermission(repository);
@@ -381,7 +344,7 @@
 				ap.permissionType = PermissionType.TEAM;
 			}
 		}
-		
+
 		// still no explicit, regex, or team match, check for implicit permissions
 		if (AccessPermission.NONE == ap.permission) {
 			switch (repository.accessRestriction) {
@@ -405,10 +368,10 @@
 				break;
 			}
 		}
-		
+
 		return ap;
 	}
-	
+
 	protected boolean canAccess(RepositoryModel repository, AccessRestrictionType ifRestriction, AccessPermission requirePermission) {
 		if (repository.accessRestriction.atLeast(ifRestriction)) {
 			RegistrantAccessPermission ap = getRepositoryPermission(repository);
@@ -416,11 +379,11 @@
 		}
 		return true;
 	}
-	
+
 	public boolean canView(RepositoryModel repository) {
 		return canAccess(repository, AccessRestrictionType.VIEW, AccessPermission.VIEW);
 	}
-	
+
 	public boolean canView(RepositoryModel repository, String ref) {
 		// Default UserModel doesn't implement ref-level security.
 		// Other Realms (i.e. Gerrit) may override this method.
@@ -475,19 +438,44 @@
 		}
 		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 canEdit(TicketModel ticket, RepositoryModel repository) {
+		 return isAuthenticated() &&
+				 (canPush(repository)
+				 || (ticket != null && username.equals(ticket.responsible))
+				 || (ticket != null && username.equals(ticket.createdBy)));
+	}
+
+	public boolean canAdmin(TicketModel ticket, RepositoryModel repository) {
+		 return isAuthenticated() &&
+				 (canPush(repository)
+				 || ticket != null && username.equals(ticket.responsible));
+	}
+
+	public boolean canReviewPatchset(RepositoryModel model) {
+		return isAuthenticated() && canClone(model);
+	}
+
+	public boolean canApprovePatchset(RepositoryModel model) {
+		return isAuthenticated() && canPush(model);
+	}
+
+	public boolean canVetoPatchset(RepositoryModel model) {
+		return isAuthenticated() && canPush(model);
+	}
+
 	/**
 	 * This returns true if the user has fork privileges or the user has fork
 	 * privileges because of a team membership.
-	 * 
+	 *
 	 * @return true if the user can fork
 	 */
 	public boolean canFork() {
@@ -507,7 +495,7 @@
 	/**
 	 * This returns true if the user has admin privileges or the user has admin
 	 * privileges because of a team membership.
-	 * 
+	 *
 	 * @return true if the user can admin
 	 */
 	public boolean canAdmin() {
@@ -527,7 +515,7 @@
 	/**
 	 * This returns true if the user has create privileges or the user has create
 	 * privileges because of a team membership.
-	 * 
+	 *
 	 * @return true if the user can admin
 	 */
 	public boolean canCreate() {
@@ -543,10 +531,10 @@
 		}
 		return false;
 	}
-	
+
 	/**
 	 * Returns true if the user is allowed to create the specified repository.
-	 * 
+	 *
 	 * @param repository
 	 * @return true if the user can create the repository
 	 */
@@ -555,14 +543,28 @@
 			// admins can create any repository
 			return true;
 		}
-		if (canCreate) {
+		if (canCreate()) {
 			String projectPath = StringUtils.getFirstPathElement(repository);
-			if (!StringUtils.isEmpty(projectPath) && projectPath.equalsIgnoreCase("~" + username)) {
+			if (!StringUtils.isEmpty(projectPath) && projectPath.equalsIgnoreCase(getPersonalPath())) {
 				// personal repository
 				return true;
 			}
 		}
 		return false;
+	}
+
+	/**
+	 * Returns true if the user is allowed to administer the specified repository
+	 *
+	 * @param repo
+	 * @return true if the user can administer the repository
+	 */
+	public boolean canAdmin(RepositoryModel repo) {
+		return canAdmin() || repo.isOwner(username) || isMyPersonalRepository(repo.name);
+	}
+
+	public boolean isAuthenticated() {
+		return !UserModel.ANONYMOUS.equals(this) && isAuthenticated;
 	}
 
 	public boolean isTeamMember(String teamname) {
@@ -590,23 +592,27 @@
 	public String getName() {
 		return username;
 	}
-	
+
 	public String getDisplayName() {
 		if (StringUtils.isEmpty(displayName)) {
 			return username;
 		}
 		return displayName;
 	}
-	
+
 	public String getPersonalPath() {
-		return "~" + username;
+		return ModelUtils.getPersonalPath(username);
 	}
-	
+
+	public UserPreferences getPreferences() {
+		return userPreferences;
+	}
+
 	@Override
 	public int hashCode() {
 		return username.hashCode();
 	}
-	
+
 	@Override
 	public boolean equals(Object o) {
 		if (o instanceof UserModel) {
@@ -624,43 +630,34 @@
 	public int compareTo(UserModel o) {
 		return username.compareTo(o.username);
 	}
-	
+
 	/**
 	 * Returns true if the name/email pair match this user account.
-	 * 
+	 *
 	 * @param name
 	 * @param email
 	 * @return true, if the name and email address match this account
 	 */
 	public boolean is(String name, String email) {
-		// at a minimum a usename or display name must be supplied
-		if (StringUtils.isEmpty(name)) {
+		// at a minimum a username or display name AND email address must be supplied
+		if (StringUtils.isEmpty(name) || StringUtils.isEmpty(email)) {
 			return false;
 		}
 		boolean nameVerified = name.equalsIgnoreCase(username) || name.equalsIgnoreCase(getDisplayName());
 		boolean emailVerified = false;
 		if (StringUtils.isEmpty(emailAddress)) {
 			// user account has not specified an email address
-			// rely on username/displayname verification
-			emailVerified = true;
+			// fail
+			emailVerified = false;
 		} else {
 			// user account has specified an email address
-			// require email address verification
-			if (!StringUtils.isEmpty(email)) {
-				emailVerified = email.equalsIgnoreCase(emailAddress);
-			}
+			emailVerified = email.equalsIgnoreCase(emailAddress);
 		}
 		return nameVerified && emailVerified;
 	}
-	
-	@Deprecated
-	public boolean hasBranchPermission(String repositoryName, String branch) {
-		// Default UserModel doesn't implement branch-level security. Other Realms (i.e. Gerrit) may override this method.
-		return hasRepositoryPermission(repositoryName) || hasTeamRepositoryPermission(repositoryName);
-	}
-	
+
 	public boolean isMyPersonalRepository(String repository) {
 		String projectPath = StringUtils.getFirstPathElement(repository);
-		return !StringUtils.isEmpty(projectPath) && projectPath.equalsIgnoreCase("~" + username);
+		return !StringUtils.isEmpty(projectPath) && projectPath.equalsIgnoreCase(getPersonalPath());
 	}
 }

--
Gitblit v1.9.1