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.

---
 tests/com/gitblit/tests/GitServletTest.java |  275 ++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 252 insertions(+), 23 deletions(-)

diff --git a/tests/com/gitblit/tests/GitServletTest.java b/tests/com/gitblit/tests/GitServletTest.java
index 09e0e5a..e65c61c 100644
--- a/tests/com/gitblit/tests/GitServletTest.java
+++ b/tests/com/gitblit/tests/GitServletTest.java
@@ -1,5 +1,6 @@
 package com.gitblit.tests;
 
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
@@ -32,6 +33,7 @@
 import com.gitblit.Constants.AccessRestrictionType;
 import com.gitblit.Constants.AuthorizationControl;
 import com.gitblit.GitBlit;
+import com.gitblit.Keys;
 import com.gitblit.models.RepositoryModel;
 import com.gitblit.models.UserModel;
 import com.gitblit.utils.JGitUtils;
@@ -67,15 +69,19 @@
 	
 	public static void deleteWorkingFolders() throws Exception {
 		if (ticgitFolder.exists()) {
+			GitBlitSuite.close(ticgitFolder);
 			FileUtils.delete(ticgitFolder, FileUtils.RECURSIVE);
 		}
 		if (ticgit2Folder.exists()) {
+			GitBlitSuite.close(ticgit2Folder);
 			FileUtils.delete(ticgit2Folder, FileUtils.RECURSIVE);
 		}
 		if (jgitFolder.exists()) {
+			GitBlitSuite.close(jgitFolder);
 			FileUtils.delete(jgitFolder, FileUtils.RECURSIVE);
 		}
 		if (jgit2Folder.exists()) {
+			GitBlitSuite.close(jgit2Folder);
 			FileUtils.delete(jgit2Folder, FileUtils.RECURSIVE);
 		}
 	}
@@ -88,7 +94,7 @@
 		clone.setBare(false);
 		clone.setCloneAllBranches(true);
 		clone.setCredentialsProvider(new UsernamePasswordCredentialsProvider(account, password));
-		close(clone.call());		
+		GitBlitSuite.close(clone.call());		
 		assertTrue(true);
 	}
 
@@ -108,7 +114,7 @@
 			clone.setBare(false);
 			clone.setCloneAllBranches(true);
 			clone.setCredentialsProvider(new UsernamePasswordCredentialsProvider("bogus", "bogus"));
-			close(clone.call());
+			GitBlitSuite.close(clone.call());
 			cloned = true;
 		} catch (Exception e) {
 			// swallow the exception which we expect
@@ -143,7 +149,7 @@
 			clone.setBare(false);
 			clone.setCloneAllBranches(true);
 			clone.setCredentialsProvider(new UsernamePasswordCredentialsProvider(user.username, user.password));
-			close(clone.call());
+			GitBlitSuite.close(clone.call());
 			cloned = true;
 		} catch (Exception e) {
 			// swallow the exception which we expect
@@ -165,7 +171,7 @@
 		clone.setBare(false);
 		clone.setCloneAllBranches(true);
 		clone.setCredentialsProvider(new UsernamePasswordCredentialsProvider(user.username, user.password));
-		close(clone.call());
+		GitBlitSuite.close(clone.call());
 		cloned = true;
 
 		assertTrue("Authenticated login could not clone!", cloned);
@@ -190,7 +196,7 @@
 		git.add().addFilepattern(file.getName()).call();
 		git.commit().setMessage("test commit").call();
 		git.push().setPushAll().call();
-		close(git);
+		GitBlitSuite.close(git);
 	}
 
 	@Test
@@ -201,7 +207,7 @@
 		clone.setBare(false);
 		clone.setCloneAllBranches(true);
 		clone.setCredentialsProvider(new UsernamePasswordCredentialsProvider(account, password));
-		close(clone.call());
+		GitBlitSuite.close(clone.call());
 		assertTrue(true);
 
 		Git git = Git.open(jgitFolder);
@@ -213,7 +219,7 @@
 		git.add().addFilepattern(file.getName()).call();
 		git.commit().setMessage("test commit").call();
 		git.push().setPushAll().call();
-		close(git);
+		GitBlitSuite.close(git);
 	}
 	
 	@Test
@@ -224,7 +230,7 @@
 		clone.setBare(false);
 		clone.setCloneAllBranches(true);
 		clone.setCredentialsProvider(new UsernamePasswordCredentialsProvider(account, password));
-		close(clone.call());
+		GitBlitSuite.close(clone.call());
 		assertTrue(true);
 
 		Git git = Git.open(jgit2Folder);
@@ -241,7 +247,113 @@
 		} catch (Exception e) {
 			assertTrue(e.getCause().getMessage().contains("git-receive-pack not permitted"));
 		}
-		close(git);
+		GitBlitSuite.close(git);
+	}
+
+	@Test
+	public void testCommitterVerification() throws Exception {
+		UserModel user = new UserModel("james");
+		user.password = "james";
+
+		// account only uses account name to verify
+		testCommitterVerification(user, user.username, null, true);
+		// committer email address is ignored because account does not specify email
+		testCommitterVerification(user, user.username, "something", true);
+		// completely different committer
+		testCommitterVerification(user, "joe", null, false);
+
+		// test display name verification
+		user.displayName = "James Moger";
+		testCommitterVerification(user, user.displayName, null, true);
+		testCommitterVerification(user, user.displayName, "something", true);
+		testCommitterVerification(user, "joe", null, false);
+		
+		// test email address verification
+		user.emailAddress = "something";
+		testCommitterVerification(user, user.displayName, null, false);
+		testCommitterVerification(user, user.displayName, "somethingelse", false);
+		testCommitterVerification(user, user.displayName, user.emailAddress, true);
+		
+		// use same email address but with different committer
+		testCommitterVerification(user, "joe", "somethingelse", false);
+	}
+	
+	private void testCommitterVerification(UserModel user, String displayName, String emailAddress, boolean expectedSuccess) throws Exception {
+		
+		if (GitBlit.self().getUserModel(user.username) != null) {
+			GitBlit.self().deleteUser(user.username);
+		}
+		
+		CredentialsProvider cp = new UsernamePasswordCredentialsProvider(user.username, user.password);
+		
+		// fork from original to a temporary bare repo
+		File verification = new File(GitBlitSuite.REPOSITORIES, "refchecks/verify-committer.git");
+		if (verification.exists()) {
+			FileUtils.delete(verification, FileUtils.RECURSIVE);
+		}
+		CloneCommand clone = Git.cloneRepository();
+		clone.setURI(MessageFormat.format("{0}/git/ticgit.git", url));
+		clone.setDirectory(verification);
+		clone.setBare(true);
+		clone.setCloneAllBranches(true);
+		clone.setCredentialsProvider(cp);
+		GitBlitSuite.close(clone.call());
+		
+		// require push permissions and committer verification
+		RepositoryModel model = GitBlit.self().getRepositoryModel("refchecks/verify-committer.git");
+		model.authorizationControl = AuthorizationControl.NAMED;
+		model.accessRestriction = AccessRestrictionType.PUSH;
+		model.verifyCommitter = true;
+		
+		// grant user push permission
+		user.setRepositoryPermission(model.name, AccessPermission.PUSH);
+		
+		GitBlit.self().updateUserModel(user.username, user, true);
+		GitBlit.self().updateRepositoryModel(model.name, model, false);
+
+		// clone temp bare repo to working copy
+		File local = new File(GitBlitSuite.REPOSITORIES, "refchecks/verify-wc");
+		if (local.exists()) {
+			FileUtils.delete(local, FileUtils.RECURSIVE);
+		}
+		clone = Git.cloneRepository();
+		clone.setURI(MessageFormat.format("{0}/git/{1}", url, model.name));
+		clone.setDirectory(local);
+		clone.setBare(false);
+		clone.setCloneAllBranches(true);
+		clone.setCredentialsProvider(cp);
+		GitBlitSuite.close(clone.call());
+		
+		Git git = Git.open(local);
+		
+		// force an identity which may or may not match the account's identity
+		git.getRepository().getConfig().setString("user", null, "name", displayName);
+		git.getRepository().getConfig().setString("user", null, "email", emailAddress);
+		git.getRepository().getConfig().save();
+		
+		// commit a file and push it
+		File file = new File(local, "PUSHCHK");
+		OutputStreamWriter os = new OutputStreamWriter(new FileOutputStream(file, true), Constants.CHARSET);
+		BufferedWriter w = new BufferedWriter(os);
+		w.write("// " + new Date().toString() + "\n");
+		w.close();
+		git.add().addFilepattern(file.getName()).call();
+		git.commit().setMessage("push test").call();
+		Iterable<PushResult> results = git.push().setCredentialsProvider(cp).setRemote("origin").call();
+		
+		for (PushResult result : results) {
+			RemoteRefUpdate ref = result.getRemoteUpdate("refs/heads/master");
+			Status status = ref.getStatus();
+			if (expectedSuccess) {
+				assertTrue("Verification failed! User was NOT able to push commit! " + status.name(), Status.OK.equals(status));
+			} else {
+				assertTrue("Verification failed! User was able to push commit! " + status.name(), Status.REJECTED_OTHER_REASON.equals(status));
+			}
+		}
+		
+		GitBlitSuite.close(git);
+		// close serving repository
+		GitBlitSuite.close(verification);
 	}
 
 	@Test
@@ -296,7 +408,7 @@
 		clone.setBare(true);
 		clone.setCloneAllBranches(true);
 		clone.setCredentialsProvider(cp);
-		close(clone.call());
+		GitBlitSuite.close(clone.call());
 
 		// elevate repository to clone permission
 		RepositoryModel model = GitBlit.self().getRepositoryModel("refchecks/ticgit.git");
@@ -331,13 +443,16 @@
 		clone.setCredentialsProvider(cp);
 		
 		try {
-			close(clone.call());
+			GitBlitSuite.close(clone.call());
 		} catch (GitAPIException e) {
 			if (permission.atLeast(AccessPermission.CLONE)) {
 				throw e;
 			} else {
+				// close serving repository
+				GitBlitSuite.close(refChecks);
+				
 				// user does not have clone permission
-				assertTrue(e.getMessage(), e.getMessage().contains("not permitted"));				
+				assertTrue(e.getMessage(), e.getMessage().contains("not permitted"));	
 				return;
 			}
 		}
@@ -359,9 +474,12 @@
 			if (permission.atLeast(AccessPermission.PUSH)) {
 				throw e;
 			} else {
+				// close serving repository
+				GitBlitSuite.close(refChecks);
+				
 				// user does not have push permission
 				assertTrue(e.getMessage(), e.getMessage().contains("not permitted"));
-				close(git);
+				GitBlitSuite.close(git);
 				return;
 			}
 		}
@@ -372,8 +490,11 @@
 			if (permission.atLeast(AccessPermission.PUSH)) {
 				assertTrue("User failed to push commit?! " + status.name(), Status.OK.equals(status));
 			} else {
+				// close serving repository
+				GitBlitSuite.close(refChecks);
+
 				assertTrue("User was able to push commit! " + status.name(), Status.REJECTED_OTHER_REASON.equals(status));
-				close(git);
+				GitBlitSuite.close(git);
 				// skip delete test
 				return;
 			}
@@ -389,8 +510,11 @@
 			if (Status.OK.equals(expectedCreate)) {
 				assertTrue("User failed to push creation?! " + status.name(), status.equals(expectedCreate));
 			} else {
+				// close serving repository
+				GitBlitSuite.close(refChecks);
+
 				assertTrue("User was able to push ref creation! " + status.name(), status.equals(expectedCreate));
-				close(git);
+				GitBlitSuite.close(git);
 				// skip delete test
 				return;
 			}
@@ -408,8 +532,11 @@
 			if (Status.OK.equals(expectedDelete)) {
 				assertTrue("User failed to push ref deletion?! " + status.name(), status.equals(Status.OK));
 			} else {
+				// close serving repository
+				GitBlitSuite.close(refChecks);
+
 				assertTrue("User was able to push ref deletion?! " + status.name(), status.equals(expectedDelete));
-				close(git);
+				GitBlitSuite.close(git);
 				// skip rewind test
 				return;
 			}
@@ -445,17 +572,119 @@
 				assertTrue("User was able to rewind master?! " + status.name(), status.equals(expectedRewind));
 			}
 		}
-		close(git);
+		GitBlitSuite.close(git);
 		
+		// close serving repository
+		GitBlitSuite.close(refChecks);
+
 		GitBlit.self().deleteUser(user.username);
 	}
-
 	
-	private void close(Git git) {
-		// really close the repository
-		// decrement the use counter to 0
-		for (int i = 0; i < 2; i++) {
-			git.getRepository().close();
+	@Test
+	public void testCreateOnPush() throws Exception {
+		testCreateOnPush(false, false);
+		testCreateOnPush(true, false);
+		testCreateOnPush(false, true);
+	}
+	
+	private void testCreateOnPush(boolean canCreate, boolean canAdmin) throws Exception {
+
+		UserModel user = new UserModel("sampleuser");
+		user.password = user.username;
+		
+		if (GitBlit.self().getUserModel(user.username) != null) {
+			GitBlit.self().deleteUser(user.username);
 		}
+		
+		user.canCreate = canCreate;
+		user.canAdmin = canAdmin;
+		
+		GitBlit.self().updateUserModel(user.username, user, true);
+
+		CredentialsProvider cp = new UsernamePasswordCredentialsProvider(user.username, user.password);
+		
+		// fork from original to a temporary bare repo
+		File tmpFolder = File.createTempFile("gitblit", "").getParentFile();
+		File createCheck = new File(tmpFolder, "ticgit.git");
+		if (createCheck.exists()) {
+			FileUtils.delete(createCheck, FileUtils.RECURSIVE);
+		}
+		
+		File personalRepo = new File(GitBlitSuite.REPOSITORIES, MessageFormat.format("~{0}/ticgit.git", user.username));
+		GitBlitSuite.close(personalRepo);
+		if (personalRepo.exists()) {
+			FileUtils.delete(personalRepo, FileUtils.RECURSIVE);
+		}
+
+		File projectRepo = new File(GitBlitSuite.REPOSITORIES, "project/ticgit.git");
+		GitBlitSuite.close(projectRepo);
+		if (projectRepo.exists()) {
+			FileUtils.delete(projectRepo, FileUtils.RECURSIVE);
+		}
+
+		CloneCommand clone = Git.cloneRepository();
+		clone.setURI(MessageFormat.format("{0}/git/ticgit.git", url));
+		clone.setDirectory(createCheck);
+		clone.setBare(true);
+		clone.setCloneAllBranches(true);
+		clone.setCredentialsProvider(cp);
+		Git git = clone.call();
+		
+		GitBlitSuite.close(personalRepo);
+		
+		// add a personal repository remote and a project remote
+		git.getRepository().getConfig().setString("remote", "user", "url", MessageFormat.format("{0}/git/~{1}/ticgit.git", url, user.username));
+		git.getRepository().getConfig().setString("remote", "project", "url", MessageFormat.format("{0}/git/project/ticgit.git", url));
+		git.getRepository().getConfig().save();
+
+		// push to non-existent user repository
+		try {
+			Iterable<PushResult> results = git.push().setRemote("user").setPushAll().setCredentialsProvider(cp).call();
+
+			for (PushResult result : results) {
+				RemoteRefUpdate ref = result.getRemoteUpdate("refs/heads/master");
+				Status status = ref.getStatus();
+				assertTrue("User failed to create repository?! " + status.name(), Status.OK.equals(status));
+			}
+
+			assertTrue("User canAdmin:" + user.canAdmin + " canCreate:" + user.canCreate, user.canAdmin || user.canCreate);
+			
+			// confirm default personal repository permissions
+			RepositoryModel model = GitBlit.self().getRepositoryModel(MessageFormat.format("~{0}/ticgit.git", user.username));
+			assertEquals("Unexpected owner", user.username, model.owner);
+			assertEquals("Unexpected authorization control", AuthorizationControl.NAMED, model.authorizationControl);
+			assertEquals("Unexpected access restriction", AccessRestrictionType.VIEW, model.accessRestriction);
+			
+		} catch (GitAPIException e) {
+			assertTrue(e.getMessage(), e.getMessage().contains("git-receive-pack not found"));
+			assertFalse("User canAdmin:" + user.canAdmin + " canCreate:" + user.canCreate, user.canAdmin || user.canCreate);
+		}
+		
+		// push to non-existent project repository
+		try {
+			Iterable<PushResult> results = git.push().setRemote("project").setPushAll().setCredentialsProvider(cp).call();
+			GitBlitSuite.close(git);
+
+			for (PushResult result : results) {
+				RemoteRefUpdate ref = result.getRemoteUpdate("refs/heads/master");
+				Status status = ref.getStatus();
+				assertTrue("User failed to create repository?! " + status.name(), Status.OK.equals(status));
+			}
+			
+			assertTrue("User canAdmin:" + user.canAdmin, user.canAdmin);
+			
+			// confirm default project repository permissions
+			RepositoryModel model = GitBlit.self().getRepositoryModel("project/ticgit.git");
+			assertEquals("Unexpected owner", user.username, model.owner);
+			assertEquals("Unexpected authorization control", AuthorizationControl.fromName(GitBlit.getString(Keys.git.defaultAuthorizationControl, "NAMED")), model.authorizationControl);
+			assertEquals("Unexpected access restriction", AccessRestrictionType.fromName(GitBlit.getString(Keys.git.defaultAccessRestriction, "NONE")), model.accessRestriction);
+
+		} catch (GitAPIException e) {
+			assertTrue(e.getMessage(), e.getMessage().contains("git-receive-pack not found"));
+			assertFalse("User canAdmin:" + user.canAdmin, user.canAdmin);
+		}
+
+		GitBlitSuite.close(git);
+		GitBlit.self().deleteUser(user.username);
 	}
 }

--
Gitblit v1.9.1