From 6adf56bb13227afac2c37871b3443fb5354d132c Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Thu, 02 Aug 2012 00:27:02 -0400
Subject: [PATCH] Per-repository authorization control: AUTHENTICATED and NAMED (issue 117)

---
 src/com/gitblit/wicket/pages/EditRepositoryPage.java |   13 +++
 src/com/gitblit/client/GitblitClient.java            |    9 ++
 src/com/gitblit/client/RepositoriesPanel.java        |    1 
 src/com/gitblit/AuthenticationFilter.java            |    1 
 distrib/gitblit.properties                           |    8 ++
 src/com/gitblit/GitServlet.java                      |    1 
 src/com/gitblit/models/UserModel.java                |    8 +
 tests/com/gitblit/tests/GitServletTest.java          |   60 +++++++++++++++
 src/com/gitblit/GitBlit.java                         |    4 +
 src/com/gitblit/wicket/GitBlitWebApp.properties      |    3 
 docs/04_releases.mkd                                 |   10 ++
 tests/com/gitblit/tests/RpcTests.java                |    3 
 src/com/gitblit/models/RepositoryModel.java          |    4 +
 src/com/gitblit/client/EditRepositoryDialog.java     |   43 +++++++++-
 src/com/gitblit/wicket/pages/EditRepositoryPage.html |   12 ++
 src/com/gitblit/Constants.java                       |   22 +++++
 16 files changed, 193 insertions(+), 9 deletions(-)

diff --git a/distrib/gitblit.properties b/distrib/gitblit.properties
index 0923c41..70718b6 100644
--- a/distrib/gitblit.properties
+++ b/distrib/gitblit.properties
@@ -63,6 +63,14 @@
 # SINCE 1.0.0
 git.defaultAccessRestriction = NONE
 
+# The default authorization control for new repositories.
+# Valid values are AUTHENTICATED and NAMED
+#  AUTHENTICATED = any authenticated user is granted restricted access
+#  NAMED = only named users/teams are granted restricted access
+#
+# SINCE 1.0.1
+git.defaultAuthorizationControl = NAMED
+
 # Number of bytes of a pack file to load into memory in a single read operation.
 # This is the "page size" of the JGit buffer cache, used for all pack access
 # operations. All disk IO occurs as single window reads. Setting this too large
diff --git a/docs/04_releases.mkd b/docs/04_releases.mkd
index e197210..4e4ee99 100644
--- a/docs/04_releases.mkd
+++ b/docs/04_releases.mkd
@@ -16,14 +16,22 @@
 - Fixed Lucene charset encoding bug when reindexing a repository (issue 112)
 - Fixed null pointer in LdapUserSerivce if account has a null email address (issue 110)
 
-#### changes
+#### additions
 
+- Added a repository setting to control authorization as AUTHENTICATED or NAMED.  
+NAMED is the original behavior for authorizing against a list of permitted users or permitted teams.
+AUTHENTICATED allows restricted access for any authenticated user.
+- Added default authorization control setting (AUTHENTICATED or NAMED)
+    **New:** *git.defaultAuthorizationControl=NAMED*  
 - Added setting to control how deep Gitblit will recurse into *git.repositoriesFolder* looking for repositories (issue 103)
     **New:** *git.searchRecursionDepth=-1*  
 - Added setting to specify regex exclusions for repositories (issue 103)
     **New:** *git.searchExclusions=*  
 - Blob page now supports displaying images (issue 6)
 - Non-image binary files can now be downloaded using the RAW link
+
+#### changes
+
 - Updated Polish translation
 
 **1.0.0** *released 2012-07-14*
diff --git a/src/com/gitblit/AuthenticationFilter.java b/src/com/gitblit/AuthenticationFilter.java
index 50a67a0..259991c 100644
--- a/src/com/gitblit/AuthenticationFilter.java
+++ b/src/com/gitblit/AuthenticationFilter.java
@@ -170,6 +170,7 @@
 		public AuthenticatedRequest(HttpServletRequest req) {
 			super(req);
 			user = new UserModel("anonymous");
+			user.isAuthenticated = false;
 		}
 
 		UserModel getUser() {
diff --git a/src/com/gitblit/Constants.java b/src/com/gitblit/Constants.java
index b80c968..181fb8f 100644
--- a/src/com/gitblit/Constants.java
+++ b/src/com/gitblit/Constants.java
@@ -109,6 +109,28 @@
 			return name();
 		}
 	}
+	
+	/**
+	 * Enumeration representing the types of authorization control for an
+	 * access restricted resource.
+	 */
+	public static enum AuthorizationControl {
+		AUTHENTICATED, NAMED;
+		
+		public static AuthorizationControl fromName(String name) {
+			for (AuthorizationControl type : values()) {
+				if (type.name().equalsIgnoreCase(name)) {
+					return type;
+				}
+			}
+			return NAMED;
+		}
+		
+		public String toString() {
+			return name();
+		}
+	}
+
 
 	/**
 	 * Enumeration representing the types of federation tokens.
diff --git a/src/com/gitblit/GitBlit.java b/src/com/gitblit/GitBlit.java
index 8f51069..26f30f9 100644
--- a/src/com/gitblit/GitBlit.java
+++ b/src/com/gitblit/GitBlit.java
@@ -69,6 +69,7 @@
 import org.slf4j.LoggerFactory;
 
 import com.gitblit.Constants.AccessRestrictionType;
+import com.gitblit.Constants.AuthorizationControl;
 import com.gitblit.Constants.FederationRequest;
 import com.gitblit.Constants.FederationStrategy;
 import com.gitblit.Constants.FederationToken;
@@ -876,6 +877,8 @@
 			model.useDocs = getConfig(config, "useDocs", false);
 			model.accessRestriction = AccessRestrictionType.fromName(getConfig(config,
 					"accessRestriction", settings.getString(Keys.git.defaultAccessRestriction, null)));
+			model.authorizationControl = AuthorizationControl.fromName(getConfig(config,
+					"authorizationControl", settings.getString(Keys.git.defaultAuthorizationControl, null)));
 			model.showRemoteBranches = getConfig(config, "showRemoteBranches", false);
 			model.isFrozen = getConfig(config, "isFrozen", false);
 			model.showReadme = getConfig(config, "showReadme", false);
@@ -1135,6 +1138,7 @@
 		config.setBoolean(Constants.CONFIG_GITBLIT, null, "useTickets", repository.useTickets);
 		config.setBoolean(Constants.CONFIG_GITBLIT, null, "useDocs", repository.useDocs);
 		config.setString(Constants.CONFIG_GITBLIT, null, "accessRestriction", repository.accessRestriction.name());
+		config.setString(Constants.CONFIG_GITBLIT, null, "authorizationControl", repository.authorizationControl.name());
 		config.setBoolean(Constants.CONFIG_GITBLIT, null, "showRemoteBranches", repository.showRemoteBranches);
 		config.setBoolean(Constants.CONFIG_GITBLIT, null, "isFrozen", repository.isFrozen);
 		config.setBoolean(Constants.CONFIG_GITBLIT, null, "showReadme", repository.showReadme);
diff --git a/src/com/gitblit/GitServlet.java b/src/com/gitblit/GitServlet.java
index 68097cb..0b5575b 100644
--- a/src/com/gitblit/GitServlet.java
+++ b/src/com/gitblit/GitServlet.java
@@ -231,6 +231,7 @@
 			if (user == null) {
 				// anonymous push, create a temporary usermodel
 				user = new UserModel(person.getName());
+				user.isAuthenticated = false;
 			}
 			return user;
 		}
diff --git a/src/com/gitblit/client/EditRepositoryDialog.java b/src/com/gitblit/client/EditRepositoryDialog.java
index 77878cb..8ce076e 100644
--- a/src/com/gitblit/client/EditRepositoryDialog.java
+++ b/src/com/gitblit/client/EditRepositoryDialog.java
@@ -35,6 +35,7 @@
 import java.util.Set;
 
 import javax.swing.BoxLayout;
+import javax.swing.ButtonGroup;
 import javax.swing.DefaultComboBoxModel;
 import javax.swing.ImageIcon;
 import javax.swing.JButton;
@@ -46,6 +47,7 @@
 import javax.swing.JList;
 import javax.swing.JOptionPane;
 import javax.swing.JPanel;
+import javax.swing.JRadioButton;
 import javax.swing.JRootPane;
 import javax.swing.JScrollPane;
 import javax.swing.JTabbedPane;
@@ -55,6 +57,7 @@
 import javax.swing.ScrollPaneConstants;
 
 import com.gitblit.Constants.AccessRestrictionType;
+import com.gitblit.Constants.AuthorizationControl;
 import com.gitblit.Constants.FederationStrategy;
 import com.gitblit.models.RepositoryModel;
 import com.gitblit.utils.ArrayUtils;
@@ -98,6 +101,10 @@
 	private JTextField mailingListsField;
 
 	private JComboBox accessRestriction;
+	
+	private JRadioButton allowAuthenticated;
+	
+	private JRadioButton allowNamed;
 
 	private JComboBox federationStrategy;
 
@@ -206,6 +213,21 @@
 		accessRestriction = new JComboBox(AccessRestrictionType.values());
 		accessRestriction.setRenderer(new AccessRestrictionRenderer());
 		accessRestriction.setSelectedItem(anRepository.accessRestriction);
+		
+		boolean authenticated = anRepository.authorizationControl != null 
+				&& AuthorizationControl.AUTHENTICATED.equals(anRepository.authorizationControl);
+		allowAuthenticated = new JRadioButton(Translation.get("gb.allowAuthenticatedDescription"));
+		allowAuthenticated.setSelected(authenticated);
+		allowNamed = new JRadioButton(Translation.get("gb.allowNamedDescription"));
+		allowNamed.setSelected(!authenticated);
+		
+		ButtonGroup group = new ButtonGroup();
+		group.add(allowAuthenticated);
+		group.add(allowNamed);
+		
+		JPanel authorizationPanel = new JPanel(new GridLayout(0, 1));
+		authorizationPanel.add(allowAuthenticated);
+		authorizationPanel.add(allowNamed);
 
 		// federation strategies - remove ORIGIN choice if this repository has
 		// no origin.
@@ -246,12 +268,15 @@
 				mailingListsField));
 
 		usersPalette = new JPalette<String>();
+		JPanel northAccessPanel = new JPanel(new BorderLayout(5, 5));
+		northAccessPanel.add(newFieldPanel(Translation.get("gb.accessRestriction"),
+				accessRestriction), BorderLayout.NORTH);
+		northAccessPanel.add(newFieldPanel(Translation.get("gb.authorizationControl"),
+				authorizationPanel), BorderLayout.CENTER);
+
 		JPanel accessPanel = new JPanel(new BorderLayout(5, 5));
-		accessPanel.add(
-				newFieldPanel(Translation.get("gb.accessRestriction"),
-						accessRestriction), BorderLayout.NORTH);
-		accessPanel.add(
-				newFieldPanel(Translation.get("gb.permittedUsers"),
+		accessPanel.add(northAccessPanel, BorderLayout.NORTH);
+		accessPanel.add(newFieldPanel(Translation.get("gb.permittedUsers"),
 						usersPalette), BorderLayout.CENTER);
 
 		teamsPalette = new JPalette<String>();
@@ -463,6 +488,8 @@
 
 		repository.accessRestriction = (AccessRestrictionType) accessRestriction
 				.getSelectedItem();
+		repository.authorizationControl = allowAuthenticated.isSelected() ? 
+				AuthorizationControl.AUTHENTICATED : AuthorizationControl.NAMED;
 		repository.federationStrategy = (FederationStrategy) federationStrategy
 				.getSelectedItem();
 
@@ -495,6 +522,12 @@
 		this.accessRestriction.setSelectedItem(restriction);
 	}
 
+	public void setAuthorizationControl(AuthorizationControl authorization) {
+		boolean authenticated = authorization != null && AuthorizationControl.AUTHENTICATED.equals(authorization);
+		this.allowAuthenticated.setSelected(authenticated);
+		this.allowNamed.setSelected(!authenticated);
+	}
+
 	public void setUsers(String owner, List<String> all, List<String> selected) {
 		ownerField.setModel(new DefaultComboBoxModel(all.toArray()));
 		if (!StringUtils.isEmpty(owner)) {
diff --git a/src/com/gitblit/client/GitblitClient.java b/src/com/gitblit/client/GitblitClient.java
index ed5a133..5e05fa4 100644
--- a/src/com/gitblit/client/GitblitClient.java
+++ b/src/com/gitblit/client/GitblitClient.java
@@ -29,6 +29,7 @@
 
 import com.gitblit.Constants;
 import com.gitblit.Constants.AccessRestrictionType;
+import com.gitblit.Constants.AuthorizationControl;
 import com.gitblit.GitBlitException.ForbiddenException;
 import com.gitblit.GitBlitException.NotAllowedException;
 import com.gitblit.GitBlitException.UnauthorizedException;
@@ -195,6 +196,14 @@
 		return AccessRestrictionType.fromName(restriction);
 	}
 
+	public AuthorizationControl getDefaultAuthorizationControl() {
+		String authorization = null;
+		if (settings.hasKey(Keys.git.defaultAuthorizationControl)) {
+			authorization = settings.get(Keys.git.defaultAuthorizationControl).currentValue;
+		}
+		return AuthorizationControl.fromName(authorization);
+	}
+
 	/**
 	 * Returns the list of pre-receive scripts the repository inherited from the
 	 * global settings and team affiliations.
diff --git a/src/com/gitblit/client/RepositoriesPanel.java b/src/com/gitblit/client/RepositoriesPanel.java
index 70b87c6..cbe1874 100644
--- a/src/com/gitblit/client/RepositoriesPanel.java
+++ b/src/com/gitblit/client/RepositoriesPanel.java
@@ -358,6 +358,7 @@
 		EditRepositoryDialog dialog = new EditRepositoryDialog(gitblit.getProtocolVersion());
 		dialog.setLocationRelativeTo(RepositoriesPanel.this);
 		dialog.setAccessRestriction(gitblit.getDefaultAccessRestriction());
+		dialog.setAuthorizationControl(gitblit.getDefaultAuthorizationControl());
 		dialog.setUsers(null, gitblit.getUsernames(), null);
 		dialog.setTeams(gitblit.getTeamnames(), null);
 		dialog.setRepositories(gitblit.getRepositories());
diff --git a/src/com/gitblit/models/RepositoryModel.java b/src/com/gitblit/models/RepositoryModel.java
index 0e0c2df..2719663 100644
--- a/src/com/gitblit/models/RepositoryModel.java
+++ b/src/com/gitblit/models/RepositoryModel.java
@@ -22,6 +22,7 @@
 import java.util.Map;
 
 import com.gitblit.Constants.AccessRestrictionType;
+import com.gitblit.Constants.AuthorizationControl;
 import com.gitblit.Constants.FederationStrategy;
 import com.gitblit.utils.ArrayUtils;
 import com.gitblit.utils.StringUtils;
@@ -47,6 +48,8 @@
 	public boolean useTickets;
 	public boolean useDocs;
 	public AccessRestrictionType accessRestriction;
+	public AuthorizationControl authorizationControl;
+	public boolean allowAuthenticated;
 	public boolean isFrozen;
 	public boolean showReadme;
 	public FederationStrategy federationStrategy;
@@ -77,6 +80,7 @@
 		this.owner = owner;
 		this.lastChange = lastchange;
 		this.accessRestriction = AccessRestrictionType.NONE;
+		this.authorizationControl = AuthorizationControl.NAMED;
 		this.federationSets = new ArrayList<String>();
 		this.federationStrategy = FederationStrategy.FEDERATE_THIS;		
 	}
diff --git a/src/com/gitblit/models/UserModel.java b/src/com/gitblit/models/UserModel.java
index 6632c61..8349bab 100644
--- a/src/com/gitblit/models/UserModel.java
+++ b/src/com/gitblit/models/UserModel.java
@@ -20,6 +20,7 @@
 import java.util.HashSet;
 import java.util.Set;
 
+import com.gitblit.Constants.AuthorizationControl;
 import com.gitblit.utils.StringUtils;
 
 /**
@@ -45,8 +46,12 @@
 	public final Set<String> repositories = new HashSet<String>();
 	public final Set<TeamModel> teams = new HashSet<TeamModel>();
 
+	// non-persisted fields
+	public boolean isAuthenticated;
+	
 	public UserModel(String username) {
 		this.username = username;
+		this.isAuthenticated = true;
 	}
 
 	/**
@@ -65,8 +70,9 @@
 	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);
+				|| hasTeamAccess(repository.name) || allowAuthenticated;
 	}
 
 	public boolean hasTeamAccess(String repositoryName) {
diff --git a/src/com/gitblit/wicket/GitBlitWebApp.properties b/src/com/gitblit/wicket/GitBlitWebApp.properties
index f8a936d..bcd6337 100644
--- a/src/com/gitblit/wicket/GitBlitWebApp.properties
+++ b/src/com/gitblit/wicket/GitBlitWebApp.properties
@@ -310,3 +310,6 @@
 gb.duration.months = {0} months
 gb.duration.oneYear = 1 year
 gb.duration.years = {0} years
+gb.authorizationControl = authorization control
+gb.allowAuthenticatedDescription = grant restricted access to all authenticated users
+gb.allowNamedDescription = grant restricted access to named users or teams
\ No newline at end of file
diff --git a/src/com/gitblit/wicket/pages/EditRepositoryPage.html b/src/com/gitblit/wicket/pages/EditRepositoryPage.html
index a419698..2bb5776 100644
--- a/src/com/gitblit/wicket/pages/EditRepositoryPage.html
+++ b/src/com/gitblit/wicket/pages/EditRepositoryPage.html
@@ -25,11 +25,19 @@
 				<tr><th><wicket:message key="gb.isFrozen"></wicket:message></th><td class="edit"><label class="checkbox"><input type="checkbox" wicket:id="isFrozen" tabindex="12" /> &nbsp;<span class="help-inline"><wicket:message key="gb.isFrozenDescription"></wicket:message></span></label></td></tr>
 				<tr><th><wicket:message key="gb.mailingLists"></wicket:message></th><td class="edit"><input class="span8" type="text" wicket:id="mailingLists" size="40" tabindex="13" /></td></tr>
 				<tr><td colspan="2" style="padding-top:15px"><h3><wicket:message key="gb.accessPermissions"></wicket:message> &nbsp;<small><wicket:message key="gb.accessPermissionsDescription"></wicket:message></small></h3></td></tr>	
-				<tr><th><wicket:message key="gb.accessRestriction"></wicket:message></th><td class="edit"><select class="span4" wicket:id="accessRestriction" tabindex="14" /></td></tr>				
+				<tr><th><wicket:message key="gb.accessRestriction"></wicket:message></th><td class="edit"><select class="span4" wicket:id="accessRestriction" tabindex="14" /></td></tr>
+				<tr><th colspan="2"><hr/></th></tr>
+				<tr><th style="vertical-align: top;"><wicket:message key="gb.authorizationControl"></wicket:message></th><td style="padding:2px;">
+					<wicket:container wicket:id="authorizationControl">
+						<label class="radio"><input type="radio" wicket:id="allowAuthenticated" tabindex="15" /> &nbsp;<span class="help-inline"><wicket:message key="gb.allowAuthenticatedDescription"></wicket:message></span></label>
+						<label class="radio"><input type="radio" wicket:id="allowNamed" tabindex="16" /> &nbsp;<span class="help-inline"><wicket:message key="gb.allowNamedDescription"></wicket:message></span></label>
+					</wicket:container>
+				</td></tr>
+				<tr><th colspan="2"><hr/></th></tr>
 				<tr><th style="vertical-align: top;"><wicket:message key="gb.permittedUsers"></wicket:message></th><td style="padding:2px;"><span wicket:id="users"></span></td></tr>
 				<tr><th style="vertical-align: top;"><wicket:message key="gb.permittedTeams"></wicket:message></th><td style="padding:2px;"><span wicket:id="teams"></span></td></tr>
 				<tr><td colspan="2"><h3><wicket:message key="gb.federation"></wicket:message> &nbsp;<small><wicket:message key="gb.federationRepositoryDescription"></wicket:message></small></h3></td></tr>	
-				<tr><th><wicket:message key="gb.federationStrategy"></wicket:message></th><td class="edit"><select class="span4" wicket:id="federationStrategy" tabindex="15" /></td></tr>
+				<tr><th><wicket:message key="gb.federationStrategy"></wicket:message></th><td class="edit"><select class="span4" wicket:id="federationStrategy" tabindex="17" /></td></tr>
 				<tr><th style="vertical-align: top;"><wicket:message key="gb.federationSets"></wicket:message></th><td style="padding:2px;"><span wicket:id="federationSets"></span></td></tr>
 				<tr><td colspan="2"><h3><wicket:message key="gb.search"></wicket:message> &nbsp;<small><wicket:message key="gb.indexedBranchesDescription"></wicket:message></small></h3></td></tr>	
 				<tr><th style="vertical-align: top;"><wicket:message key="gb.indexedBranches"></wicket:message></th><td style="padding:2px;"><span wicket:id="indexedBranches"></span></td></tr>
diff --git a/src/com/gitblit/wicket/pages/EditRepositoryPage.java b/src/com/gitblit/wicket/pages/EditRepositoryPage.java
index 0176249..505cb54 100644
--- a/src/com/gitblit/wicket/pages/EditRepositoryPage.java
+++ b/src/com/gitblit/wicket/pages/EditRepositoryPage.java
@@ -36,6 +36,8 @@
 import org.apache.wicket.markup.html.form.DropDownChoice;
 import org.apache.wicket.markup.html.form.Form;
 import org.apache.wicket.markup.html.form.IChoiceRenderer;
+import org.apache.wicket.markup.html.form.Radio;
+import org.apache.wicket.markup.html.form.RadioGroup;
 import org.apache.wicket.markup.html.form.TextField;
 import org.apache.wicket.markup.html.list.ListItem;
 import org.apache.wicket.markup.html.list.ListView;
@@ -47,6 +49,7 @@
 
 import com.gitblit.Constants;
 import com.gitblit.Constants.AccessRestrictionType;
+import com.gitblit.Constants.AuthorizationControl;
 import com.gitblit.Constants.FederationStrategy;
 import com.gitblit.GitBlit;
 import com.gitblit.GitBlitException;
@@ -75,6 +78,8 @@
 		RepositoryModel model = new RepositoryModel();
 		String restriction = GitBlit.getString(Keys.git.defaultAccessRestriction, null);
 		model.accessRestriction = AccessRestrictionType.fromName(restriction);
+		String authorization = GitBlit.getString(Keys.git.defaultAuthorizationControl, null);
+		model.authorizationControl = AuthorizationControl.fromName(authorization);
 		setupPage(model);
 	}
 
@@ -370,6 +375,14 @@
 				: StringUtils.flattenStrings(repositoryModel.mailingLists, " "));
 		form.add(new TextField<String>("mailingLists", mailingLists));
 		form.add(indexedBranchesPalette);
+		
+		RadioGroup<AuthorizationControl> group = new RadioGroup<AuthorizationControl>("authorizationControl");
+		Radio<AuthorizationControl> allowAuthenticated = new Radio<AuthorizationControl>("allowAuthenticated", new Model<AuthorizationControl>(AuthorizationControl.AUTHENTICATED));		
+		Radio<AuthorizationControl> allowNamed = new Radio<AuthorizationControl>("allowNamed", new Model<AuthorizationControl>(AuthorizationControl.NAMED));
+		group.add(allowAuthenticated);
+		group.add(allowNamed);
+		form.add(group);
+				
 		form.add(usersPalette);
 		form.add(teamsPalette);
 		form.add(federationSetsPalette);
diff --git a/tests/com/gitblit/tests/GitServletTest.java b/tests/com/gitblit/tests/GitServletTest.java
index 848a1d0..bdbb2a5 100644
--- a/tests/com/gitblit/tests/GitServletTest.java
+++ b/tests/com/gitblit/tests/GitServletTest.java
@@ -21,8 +21,10 @@
 import org.junit.Test;
 
 import com.gitblit.Constants.AccessRestrictionType;
+import com.gitblit.Constants.AuthorizationControl;
 import com.gitblit.GitBlit;
 import com.gitblit.models.RepositoryModel;
+import com.gitblit.models.UserModel;
 
 public class GitServletTest {
 
@@ -108,6 +110,64 @@
 
 		assertFalse("Bogus login cloned a repository?!", cloned);
 	}
+	
+	@Test
+	public void testUnauthorizedLoginClone() throws Exception {
+		// restrict repository access
+		RepositoryModel model = GitBlit.self().getRepositoryModel("ticgit.git");
+		model.accessRestriction = AccessRestrictionType.CLONE;
+		model.authorizationControl = AuthorizationControl.NAMED;
+		UserModel user = new UserModel("james");
+		user.password = "james";
+		GitBlit.self().updateUserModel(user.username, user, true);
+		GitBlit.self().updateRepositoryModel(model.name, model, false);
+
+		FileUtils.delete(ticgit2Folder, FileUtils.RECURSIVE);
+		
+		// delete any existing working folder		
+		boolean cloned = false;
+		try {
+			CloneCommand clone = Git.cloneRepository();
+			clone.setURI(MessageFormat.format("{0}/git/ticgit.git", url));
+			clone.setDirectory(ticgit2Folder);
+			clone.setBare(false);
+			clone.setCloneAllBranches(true);
+			clone.setCredentialsProvider(new UsernamePasswordCredentialsProvider(user.username, user.password));
+			close(clone.call());
+			cloned = true;
+		} catch (Exception e) {
+			// swallow the exception which we expect
+		}
+
+		assertFalse("Unauthorized login cloned a repository?!", cloned);
+
+		FileUtils.delete(ticgit2Folder, FileUtils.RECURSIVE);
+		
+		// switch to authenticated
+		model.authorizationControl = AuthorizationControl.AUTHENTICATED;
+		GitBlit.self().updateRepositoryModel(model.name, model, false);
+		
+		// try clone again
+		cloned = false;
+		CloneCommand clone = Git.cloneRepository();
+		clone.setURI(MessageFormat.format("{0}/git/ticgit.git", url));
+		clone.setDirectory(ticgit2Folder);
+		clone.setBare(false);
+		clone.setCloneAllBranches(true);
+		clone.setCredentialsProvider(new UsernamePasswordCredentialsProvider(user.username, user.password));
+		close(clone.call());
+		cloned = true;
+
+		assertTrue("Authenticated login could not clone!", cloned);
+		
+		FileUtils.delete(ticgit2Folder, FileUtils.RECURSIVE);
+		
+		// restore anonymous repository access
+		model.accessRestriction = AccessRestrictionType.NONE;
+		model.authorizationControl = AuthorizationControl.NAMED;
+		GitBlit.self().updateRepositoryModel(model.name, model, false);
+		GitBlit.self().deleteUser(user.username);
+	}
 
 	@Test
 	public void testAnonymousPush() throws Exception {
diff --git a/tests/com/gitblit/tests/RpcTests.java b/tests/com/gitblit/tests/RpcTests.java
index f85dd79..1080849 100644
--- a/tests/com/gitblit/tests/RpcTests.java
+++ b/tests/com/gitblit/tests/RpcTests.java
@@ -33,6 +33,7 @@
 import org.junit.Test;
 
 import com.gitblit.Constants.AccessRestrictionType;
+import com.gitblit.Constants.AuthorizationControl;
 import com.gitblit.GitBlitException.UnauthorizedException;
 import com.gitblit.Keys;
 import com.gitblit.RpcServlet;
@@ -164,6 +165,7 @@
 		model.description = "created by RpcUtils";
 		model.owner = "garbage";
 		model.accessRestriction = AccessRestrictionType.VIEW;
+		model.authorizationControl = AuthorizationControl.AUTHENTICATED;
 
 		// create
 		assertTrue("Failed to create repository!",
@@ -172,6 +174,7 @@
 		RepositoryModel retrievedRepository = findRepository(model.name);
 		assertNotNull("Failed to find " + model.name, retrievedRepository);
 		assertEquals(AccessRestrictionType.VIEW, retrievedRepository.accessRestriction);
+		assertEquals(AuthorizationControl.AUTHENTICATED, retrievedRepository.authorizationControl);
 
 		// rename and change access restriciton
 		String originalName = model.name;

--
Gitblit v1.9.1