From 13a3f5bc3e2d25fc76850f86070dc34efe60d77a Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Fri, 07 Sep 2012 22:06:15 -0400
Subject: [PATCH] Draft project pages, project metadata, and RSS feeds

---
 src/com/gitblit/SyndicationFilter.java |  143 ++++++++++++++++++++++++++++++++---------------
 1 files changed, 96 insertions(+), 47 deletions(-)

diff --git a/src/com/gitblit/SyndicationFilter.java b/src/com/gitblit/SyndicationFilter.java
index 0826566..0dff1c8 100644
--- a/src/com/gitblit/SyndicationFilter.java
+++ b/src/com/gitblit/SyndicationFilter.java
@@ -15,19 +15,30 @@
  */
 package com.gitblit;
 
+import java.io.IOException;
+import java.text.MessageFormat;
+
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
 import com.gitblit.Constants.AccessRestrictionType;
+import com.gitblit.models.ProjectModel;
 import com.gitblit.models.RepositoryModel;
 import com.gitblit.models.UserModel;
 
 /**
- * The SyndicationFilter is an AccessRestrictionFilter which ensures that feed
- * requests for view-restricted repositories have proper authentication
+ * The SyndicationFilter is an AuthenticationFilter which ensures that feed
+ * requests for projects or view-restricted repositories have proper authentication
  * credentials and are authorized for the requested feed.
  * 
  * @author James Moger
  * 
  */
-public class SyndicationFilter extends AccessRestrictionFilter {
+public class SyndicationFilter extends AuthenticationFilter {
 
 	/**
 	 * Extract the repository name from the url.
@@ -35,8 +46,7 @@
 	 * @param url
 	 * @return repository name
 	 */
-	@Override
-	protected String extractRepositoryName(String url) {
+	protected String extractRequestedName(String url) {
 		if (url.indexOf('?') > -1) {
 			return url.substring(0, url.indexOf('?'));
 		}
@@ -44,52 +54,91 @@
 	}
 
 	/**
-	 * Analyze the url and returns the action of the request.
+	 * doFilter does the actual work of preprocessing the request to ensure that
+	 * the user may proceed.
 	 * 
-	 * @param url
-	 * @return action of the request
+	 * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest,
+	 *      javax.servlet.ServletResponse, javax.servlet.FilterChain)
 	 */
 	@Override
-	protected String getUrlRequestAction(String url) {
-		return "VIEW";
-	}
+	public void doFilter(final ServletRequest request, final ServletResponse response,
+			final FilterChain chain) throws IOException, ServletException {
 
-	/**
-	 * Determine if the action may be executed on the repository.
-	 * 
-	 * @param repository
-	 * @param action
-	 * @return true if the action may be performed
-	 */
-	@Override
-	protected boolean isActionAllowed(RepositoryModel repository, String action) {
-		return true;
-	}
-	
-	/**
-	 * Determine if the repository requires authentication.
-	 * 
-	 * @param repository
-	 * @param action
-	 * @return true if authentication required
-	 */
-	@Override
-	protected boolean requiresAuthentication(RepositoryModel repository, String action) {
-		return repository.accessRestriction.atLeast(AccessRestrictionType.VIEW);
-	}
+		HttpServletRequest httpRequest = (HttpServletRequest) request;
+		HttpServletResponse httpResponse = (HttpServletResponse) response;
 
-	/**
-	 * Determine if the user can access the repository and perform the specified
-	 * action.
-	 * 
-	 * @param repository
-	 * @param user
-	 * @param action
-	 * @return true if user may execute the action on the repository
-	 */
-	@Override
-	protected boolean canAccess(RepositoryModel repository, UserModel user, String action) {
-		return user.canAccessRepository(repository);
-	}
+		String fullUrl = getFullUrl(httpRequest);
+		String name = extractRequestedName(fullUrl);
 
+		ProjectModel project = GitBlit.self().getProjectModel(name);
+		RepositoryModel model = null;
+		
+		if (project == null) {
+			// try loading a repository model
+			model = GitBlit.self().getRepositoryModel(name);
+			if (model == null) {
+				// repository not found. send 404.
+				logger.info(MessageFormat.format("ARF: {0} ({1})", fullUrl,
+						HttpServletResponse.SC_NOT_FOUND));
+				httpResponse.sendError(HttpServletResponse.SC_NOT_FOUND);
+				return;
+			}
+		}
+		
+		// Wrap the HttpServletRequest with the AccessRestrictionRequest which
+		// overrides the servlet container user principal methods.
+		// JGit requires either:
+		//
+		// 1. servlet container authenticated user
+		// 2. http.receivepack = true in each repository's config
+		//
+		// Gitblit must conditionally authenticate users per-repository so just
+		// enabling http.receivepack is insufficient.
+		AuthenticatedRequest authenticatedRequest = new AuthenticatedRequest(httpRequest);
+		UserModel user = getUser(httpRequest);
+		if (user != null) {
+			authenticatedRequest.setUser(user);
+		}
+
+		// BASIC authentication challenge and response processing
+		if (model != null) {
+			if (model.accessRestriction.atLeast(AccessRestrictionType.VIEW)) {
+				if (user == null) {
+					// challenge client to provide credentials. send 401.
+					if (GitBlit.isDebugMode()) {
+						logger.info(MessageFormat.format("ARF: CHALLENGE {0}", fullUrl));
+					}
+					httpResponse.setHeader("WWW-Authenticate", CHALLENGE);
+					httpResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+					return;
+				} else {
+					// check user access for request
+					if (user.canAdmin || user.canAccessRepository(model)) {
+						// authenticated request permitted.
+						// pass processing to the restricted servlet.
+						newSession(authenticatedRequest, httpResponse);
+						logger.info(MessageFormat.format("ARF: {0} ({1}) authenticated", fullUrl,
+								HttpServletResponse.SC_CONTINUE));
+						chain.doFilter(authenticatedRequest, httpResponse);
+						return;
+					}
+					// valid user, but not for requested access. send 403.
+					if (GitBlit.isDebugMode()) {
+						logger.info(MessageFormat.format("ARF: {0} forbidden to access {1}",
+								user.username, fullUrl));
+					}
+					httpResponse.sendError(HttpServletResponse.SC_FORBIDDEN);
+					return;
+				}
+			}
+		}
+
+		if (GitBlit.isDebugMode()) {
+			logger.info(MessageFormat.format("ARF: {0} ({1}) unauthenticated", fullUrl,
+					HttpServletResponse.SC_CONTINUE));
+		}
+		// unauthenticated request permitted.
+		// pass processing to the restricted servlet.
+		chain.doFilter(authenticatedRequest, httpResponse);
+	}
 }

--
Gitblit v1.9.1