James Moger
2015-11-22 ed552ba47c02779c270ffd62841d6d1048dade70
src/main/java/com/gitblit/servlet/GitFilter.java
@@ -17,7 +17,9 @@
import java.text.MessageFormat;
import javax.servlet.FilterConfig;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import javax.servlet.http.HttpServletRequest;
import com.gitblit.Constants.AccessRestrictionType;
@@ -25,12 +27,13 @@
import com.gitblit.GitBlitException;
import com.gitblit.IStoredSettings;
import com.gitblit.Keys;
import com.gitblit.manager.IAuthenticationManager;
import com.gitblit.manager.IFederationManager;
import com.gitblit.manager.IRepositoryManager;
import com.gitblit.manager.IRuntimeManager;
import com.gitblit.models.RepositoryModel;
import com.gitblit.models.UserModel;
import com.gitblit.utils.StringUtils;
import dagger.ObjectGraph;
/**
 * The GitFilter is an AccessRestrictionFilter which ensures that Git client
@@ -40,24 +43,34 @@
 * @author James Moger
 *
 */
@Singleton
public class GitFilter extends AccessRestrictionFilter {
   protected static final String gitReceivePack = "/git-receive-pack";
   protected static final String gitUploadPack = "/git-upload-pack";
   protected static final String gitLfs = "/info/lfs";
   protected static final String[] suffixes = { gitReceivePack, gitUploadPack, "/info/refs", "/HEAD",
         "/objects" };
         "/objects", gitLfs };
   private IStoredSettings settings;
   private IFederationManager federationManager;
   @Override
   protected void inject(ObjectGraph dagger, FilterConfig filterConfig) {
      super.inject(dagger, filterConfig);
      this.settings = dagger.get(IStoredSettings.class);
      this.federationManager = dagger.get(IFederationManager.class);
   @Inject
   public GitFilter(
         IStoredSettings settings,
         IRuntimeManager runtimeManager,
         IAuthenticationManager authenticationManager,
         IRepositoryManager repositoryManager,
         IFederationManager federationManager) {
      super(runtimeManager, authenticationManager, repositoryManager);
      this.settings = settings;
      this.federationManager = federationManager;
   }
   /**
@@ -106,6 +119,8 @@
            return gitReceivePack;
         } else if (suffix.contains("?service=git-upload-pack")) {
            return gitUploadPack;
         } else if (suffix.startsWith(gitLfs)) {
            return gitLfs;
         } else {
            return gitUploadPack;
         }
@@ -134,7 +149,13 @@
    * @return true if the server allows repository creation on-push
    */
   @Override
   protected boolean isCreationAllowed() {
   protected boolean isCreationAllowed(String action) {
      //Repository must already exist before large files can be deposited
      if (action.equals(gitLfs)) {
         return false;
      }
      return settings.getBoolean(Keys.git.allowCreateOnPush, true);
   }
@@ -146,9 +167,15 @@
    * @return true if the action may be performed
    */
   @Override
   protected boolean isActionAllowed(RepositoryModel repository, String action) {
   protected boolean isActionAllowed(RepositoryModel repository, String action, String method) {
      // the log here has been moved into ReceiveHook to provide clients with
      // error messages
      if (gitLfs.equals(action)) {
         if (!method.matches("GET|POST|PUT|HEAD")) {
            return false;
         }
      }
      return true;
   }
@@ -162,16 +189,25 @@
    *
    * @param repository
    * @param action
    * @param method
    * @return true if authentication required
    */
   @Override
   protected boolean requiresAuthentication(RepositoryModel repository, String action) {
   protected boolean requiresAuthentication(RepositoryModel repository, String action, String method) {
      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);
      } else if (gitLfs.equals(action)) {
         if (method.matches("GET|HEAD")) {
            return repository.accessRestriction.atLeast(AccessRestrictionType.CLONE);
         } else {
            //NOTE: Treat POST as PUT as as without reading message type cannot determine
            return repository.accessRestriction.atLeast(AccessRestrictionType.PUSH);
         }
      }
      return false;
   }
@@ -220,6 +256,12 @@
   @Override
   protected RepositoryModel createRepository(UserModel user, String repository, String action) {
      boolean isPush = !StringUtils.isEmpty(action) && gitReceivePack.equals(action);
      if (action.equals(gitLfs)) {
         //Repository must already exist for any filestore actions
         return null;
      }
      if (isPush) {
         if (user.canCreate(repository)) {
            // user is pushing to a new repository
@@ -271,4 +313,40 @@
      // repository could not be created or action was not a push
      return null;
   }
   /**
    * Git lfs action uses an alternative authentication header,
    *
    * @param action
    * @return
    */
   @Override
   protected String getAuthenticationHeader(String action) {
      if (action.equals(gitLfs)) {
         return "LFS-Authenticate";
      }
      return super.getAuthenticationHeader(action);
   }
   /**
    * Interrogates the request headers based on the action
    * @param action
    * @param request
    * @return
    */
   @Override
   protected boolean hasValidRequestHeader(String action,
         HttpServletRequest request) {
      if (action.equals(gitLfs) && request.getMethod().equals("POST")) {
         if (    !hasContentInRequestHeader(request, "Accept", FilestoreServlet.GIT_LFS_META_MIME)
             || !hasContentInRequestHeader(request, "Content-Type", FilestoreServlet.GIT_LFS_META_MIME)) {
            return false;
         }
      }
      return super.hasValidRequestHeader(action, request);
   }
}