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/GitFilter.java |  195 ++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 154 insertions(+), 41 deletions(-)

diff --git a/src/com/gitblit/GitFilter.java b/src/com/gitblit/GitFilter.java
index 83e7ac8..2b769d4 100644
--- a/src/com/gitblit/GitFilter.java
+++ b/src/com/gitblit/GitFilter.java
@@ -18,6 +18,7 @@
 import java.text.MessageFormat;
 
 import com.gitblit.Constants.AccessRestrictionType;
+import com.gitblit.Constants.AuthorizationControl;
 import com.gitblit.models.RepositoryModel;
 import com.gitblit.models.UserModel;
 import com.gitblit.utils.StringUtils;
@@ -32,12 +33,29 @@
  */
 public class GitFilter extends AccessRestrictionFilter {
 
-	protected final String gitReceivePack = "/git-receive-pack";
+	protected static final String gitReceivePack = "/git-receive-pack";
 
-	protected final String gitUploadPack = "/git-upload-pack";
+	protected static final String gitUploadPack = "/git-upload-pack";
 
-	protected final String[] suffixes = { gitReceivePack, gitUploadPack, "/info/refs", "/HEAD",
+	protected static final String[] suffixes = { gitReceivePack, gitUploadPack, "/info/refs", "/HEAD",
 			"/objects" };
+
+	/**
+	 * Extract the repository name from the url.
+	 * 
+	 * @param url
+	 * @return repository name
+	 */
+	public static String getRepositoryName(String value) {
+		String repository = value;
+		// get the repository name from the url by finding a known url suffix
+		for (String urlSuffix : suffixes) {
+			if (repository.indexOf(urlSuffix) > -1) {
+				repository = repository.substring(0, repository.indexOf(urlSuffix));
+			}
+		}
+		return repository;
+	}
 
 	/**
 	 * Extract the repository name from the url.
@@ -47,14 +65,7 @@
 	 */
 	@Override
 	protected String extractRepositoryName(String url) {
-		String repository = url;
-		// get the repository name from the url by finding a known url suffix
-		for (String urlSuffix : suffixes) {
-			if (repository.indexOf(urlSuffix) > -1) {
-				repository = repository.substring(0, repository.indexOf(urlSuffix));
-			}
-		}
-		return repository;
+		return GitFilter.getRepositoryName(url);
 	}
 
 	/**
@@ -75,20 +86,66 @@
 				return gitReceivePack;
 			} else if (suffix.contains("?service=git-upload-pack")) {
 				return gitUploadPack;
+			} else {
+				return gitUploadPack;
 			}
 		}
 		return null;
+	}
+	
+	/**
+	 * Determine if a non-existing repository can be created using this filter.
+	 *  
+	 * @return true if the server allows repository creation on-push
+	 */
+	@Override
+	protected boolean isCreationAllowed() {
+		return GitBlit.getBoolean(Keys.git.allowCreateOnPush, true);
+	}
+	
+	/**
+	 * Determine if the repository can receive pushes.
+	 * 
+	 * @param repository
+	 * @param action
+	 * @return true if the action may be performed
+	 */
+	@Override
+	protected boolean isActionAllowed(RepositoryModel repository, String action) {
+		if (!StringUtils.isEmpty(action)) {
+			if (action.equals(gitReceivePack)) {
+				// Push request
+				if (!repository.isBare) {
+					logger.warn("Gitblit does not allow pushes to repositories with a working copy");
+					return false;
+				}
+			}
+		}
+		return true;
+	}
+
+	@Override
+	protected boolean requiresClientCertificate() {
+		return GitBlit.getBoolean(Keys.git.requiresClientCertificate, false);
 	}
 
 	/**
 	 * Determine if the repository requires authentication.
 	 * 
 	 * @param repository
+	 * @param action
 	 * @return true if authentication required
 	 */
 	@Override
-	protected boolean requiresAuthentication(RepositoryModel repository) {
-		return repository.accessRestriction.atLeast(AccessRestrictionType.PUSH);
+	protected boolean requiresAuthentication(RepositoryModel repository, String action) {
+		if (gitUploadPack.equals(action)) {
+			// send to client
+			return repository.accessRestriction.atLeast(AccessRestrictionType.CLONE);	
+		} else if (gitReceivePack.equals(action)) {
+			// receive from client
+			return repository.accessRestriction.atLeast(AccessRestrictionType.PUSH);
+		}
+		return false;
 	}
 
 	/**
@@ -105,36 +162,92 @@
 		if (!GitBlit.getBoolean(Keys.git.enableGitServlet, true)) {
 			// Git Servlet disabled
 			return false;
-		}
-		boolean readOnly = repository.isFrozen;
-		if (readOnly || repository.accessRestriction.atLeast(AccessRestrictionType.PUSH)) {
-			boolean authorizedUser = user.canAccessRepository(repository.name);
-			if (action.equals(gitReceivePack)) {
-				// Push request
-				if (!readOnly && authorizedUser) {
-					// clone-restricted or push-authorized
-					return true;
-				} else {
-					// user is unauthorized to push to this repository
-					logger.warn(MessageFormat.format("user {0} is not authorized to push to {1}",
-							user.username, repository));
-					return false;
-				}
-			} else if (action.equals(gitUploadPack)) {
-				// Clone request
-				boolean cloneRestricted = repository.accessRestriction
-						.atLeast(AccessRestrictionType.CLONE);
-				if (!cloneRestricted || (cloneRestricted && authorizedUser)) {
-					// push-restricted or clone-authorized
-					return true;
-				} else {
-					// user is unauthorized to clone this repository
-					logger.warn(MessageFormat.format("user {0} is not authorized to clone {1}",
-							user.username, repository));
-					return false;
-				}
+		}		
+		if (action.equals(gitReceivePack)) {
+			// Push request
+			if (user.canPush(repository)) {
+				return true;
+			} else {
+				// user is unauthorized to push to this repository
+				logger.warn(MessageFormat.format("user {0} is not authorized to push to {1}",
+						user.username, repository));
+				return false;
+			}
+		} else if (action.equals(gitUploadPack)) {
+			// Clone request
+			if (user.canClone(repository)) {
+				return true;
+			} else {
+				// user is unauthorized to clone this repository
+				logger.warn(MessageFormat.format("user {0} is not authorized to clone {1}",
+						user.username, repository));
+				return false;
 			}
 		}
 		return true;
 	}
+	
+	/**
+	 * An authenticated user with the CREATE role can create a repository on
+	 * push.
+	 * 
+	 * @param user
+	 * @param repository
+	 * @param action
+	 * @return the repository model, if it is created, null otherwise
+	 */
+	@Override
+	protected RepositoryModel createRepository(UserModel user, String repository, String action) {
+		boolean isPush = !StringUtils.isEmpty(action) && gitReceivePack.equals(action);
+		if (isPush) {
+			if (user.canCreate(repository)) {
+				// user is pushing to a new repository
+				// validate name
+				if (repository.startsWith("../")) {
+					logger.error(MessageFormat.format("Illegal relative path in repository name! {0}", repository));
+					return null;
+				}
+				if (repository.contains("/../")) {
+					logger.error(MessageFormat.format("Illegal relative path in repository name! {0}", repository));
+					return null;
+				}					
+
+				// confirm valid characters in repository name
+				Character c = StringUtils.findInvalidCharacter(repository);
+				if (c != null) {
+					logger.error(MessageFormat.format("Invalid character '{0}' in repository name {1}!", c, repository));
+					return null;
+				}
+
+				// create repository
+				RepositoryModel model = new RepositoryModel();
+				model.name = repository;
+				model.owner = user.username;
+				model.projectPath = StringUtils.getFirstPathElement(repository);
+				if (model.isUsersPersonalRepository(user.username)) {
+					// personal repository, default to private for user
+					model.authorizationControl = AuthorizationControl.NAMED;
+					model.accessRestriction = AccessRestrictionType.VIEW;
+				} else {
+					// common repository, user default server settings
+					model.authorizationControl = AuthorizationControl.fromName(GitBlit.getString(Keys.git.defaultAuthorizationControl, ""));
+					model.accessRestriction = AccessRestrictionType.fromName(GitBlit.getString(Keys.git.defaultAccessRestriction, ""));
+				}
+
+				// create the repository
+				try {
+					GitBlit.self().updateRepositoryModel(model.name, model, true);
+					logger.info(MessageFormat.format("{0} created {1} ON-PUSH", user.username, model.name));
+					return GitBlit.self().getRepositoryModel(model.name);
+				} catch (GitBlitException e) {
+					logger.error(MessageFormat.format("{0} failed to create repository {1} ON-PUSH!", user.username, model.name), e);
+				}
+			} else {
+				logger.warn(MessageFormat.format("{0} is not permitted to create repository {1} ON-PUSH!", user.username, repository));
+			}
+		}
+		
+		// repository could not be created or action was not a push
+		return null;
+	}
 }

--
Gitblit v1.9.1