mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-07 20:31:06 -05:00
Implementation of OAuth2
This commit is contained in:
parent
c3db415ce7
commit
1872eba223
18 changed files with 281 additions and 100 deletions
|
@ -1,5 +1,6 @@
|
|||
package uk.ac.ic.wlgitbridge.bridge;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.transport.ServiceMayNotContinueException;
|
||||
|
@ -8,6 +9,7 @@ import uk.ac.ic.wlgitbridge.data.ProjectLock;
|
|||
import uk.ac.ic.wlgitbridge.data.ShutdownHook;
|
||||
import uk.ac.ic.wlgitbridge.data.model.DataStore;
|
||||
import uk.ac.ic.wlgitbridge.data.filestore.RawDirectory;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.base.ForbiddenException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.exception.FailedConnectionException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getdoc.GetDocRequest;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getdoc.exception.InvalidProjectException;
|
||||
|
@ -43,9 +45,9 @@ public class BridgeAPI {
|
|||
mainProjectLock.unlockForProject(projectName);
|
||||
}
|
||||
|
||||
public boolean repositoryExists(String projectName) throws ServiceMayNotContinueException {
|
||||
public boolean repositoryExists(Credential oauth2, String projectName) throws ServiceMayNotContinueException, ForbiddenException {
|
||||
lockForProject(projectName);
|
||||
GetDocRequest getDocRequest = new GetDocRequest(projectName);
|
||||
GetDocRequest getDocRequest = new GetDocRequest(oauth2, projectName);
|
||||
getDocRequest.request();
|
||||
try {
|
||||
getDocRequest.getResult().getVersionID();
|
||||
|
@ -61,19 +63,19 @@ public class BridgeAPI {
|
|||
return true;
|
||||
}
|
||||
|
||||
public void getWritableRepositories(String projectName, Repository repository) throws IOException, SnapshotPostException, GitAPIException {
|
||||
public void getWritableRepositories(Credential oauth2, String projectName, Repository repository) throws IOException, SnapshotPostException, GitAPIException, ForbiddenException {
|
||||
Util.sout("Fetching project: " + projectName);
|
||||
dataStore.updateProjectWithName(projectName, repository);
|
||||
dataStore.updateProjectWithName(oauth2, projectName, repository);
|
||||
}
|
||||
|
||||
public void putDirectoryContentsToProjectWithName(String projectName, RawDirectory directoryContents, RawDirectory oldDirectoryContents, String hostname) throws SnapshotPostException, IOException {
|
||||
public void putDirectoryContentsToProjectWithName(Credential oauth2, String projectName, RawDirectory directoryContents, RawDirectory oldDirectoryContents, String hostname) throws SnapshotPostException, IOException, ForbiddenException {
|
||||
mainProjectLock.lockForProject(projectName);
|
||||
CandidateSnapshot candidate = null;
|
||||
try {
|
||||
Util.sout("Pushing project: " + projectName);
|
||||
String postbackKey = postbackManager.makeKeyForProject(projectName);
|
||||
candidate = dataStore.createCandidateSnapshotFromProjectWithContents(projectName, directoryContents, oldDirectoryContents);
|
||||
PushRequest pushRequest = new PushRequest(candidate, postbackKey);
|
||||
PushRequest pushRequest = new PushRequest(oauth2, candidate, postbackKey);
|
||||
pushRequest.request();
|
||||
PushResult result = pushRequest.getResult();
|
||||
if (result.wasSuccessful()) {
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package uk.ac.ic.wlgitbridge.bridge;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.transport.ServiceMayNotContinueException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.base.ForbiddenException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getdoc.exception.InvalidProjectException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.push.exception.SnapshotPostException;
|
||||
|
||||
|
@ -24,13 +26,13 @@ public class WLBridgedProject {
|
|||
this.bridgeAPI = bridgeAPI;
|
||||
}
|
||||
|
||||
public void buildRepository() throws RepositoryNotFoundException, ServiceMayNotContinueException {
|
||||
public void buildRepository(Credential oauth2) throws RepositoryNotFoundException, ServiceMayNotContinueException, ForbiddenException {
|
||||
bridgeAPI.lockForProject(name);
|
||||
try {
|
||||
if (repository.getObjectDatabase().exists()) {
|
||||
updateRepositoryFromSnapshots(repository);
|
||||
updateRepositoryFromSnapshots(oauth2, repository);
|
||||
} else {
|
||||
buildRepositoryFromScratch(repository);
|
||||
buildRepositoryFromScratch(oauth2, repository);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
e.printStackTrace();
|
||||
|
@ -40,9 +42,9 @@ public class WLBridgedProject {
|
|||
}
|
||||
}
|
||||
|
||||
private void updateRepositoryFromSnapshots(Repository repository) throws RepositoryNotFoundException, ServiceMayNotContinueException {
|
||||
private void updateRepositoryFromSnapshots(Credential oauth2, Repository repository) throws RepositoryNotFoundException, ServiceMayNotContinueException, ForbiddenException {
|
||||
try {
|
||||
bridgeAPI.getWritableRepositories(name, repository);
|
||||
bridgeAPI.getWritableRepositories(oauth2, name, repository);
|
||||
} catch (InvalidProjectException e) {
|
||||
throw new RepositoryNotFoundException(name);
|
||||
} catch (SnapshotPostException e) {
|
||||
|
@ -54,8 +56,8 @@ public class WLBridgedProject {
|
|||
}
|
||||
}
|
||||
|
||||
private void buildRepositoryFromScratch(Repository repository) throws RepositoryNotFoundException, ServiceMayNotContinueException {
|
||||
if (!bridgeAPI.repositoryExists(name)) {
|
||||
private void buildRepositoryFromScratch(Credential oauth2, Repository repository) throws RepositoryNotFoundException, ServiceMayNotContinueException, ForbiddenException {
|
||||
if (!bridgeAPI.repositoryExists(oauth2, name)) {
|
||||
throw new RepositoryNotFoundException(name);
|
||||
}
|
||||
try {
|
||||
|
@ -63,7 +65,7 @@ public class WLBridgedProject {
|
|||
} catch (IOException e) {
|
||||
throw new ServiceMayNotContinueException(e);
|
||||
}
|
||||
updateRepositoryFromSnapshots(repository);
|
||||
updateRepositoryFromSnapshots(oauth2, repository);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package uk.ac.ic.wlgitbridge.data;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.base.ForbiddenException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.exception.FailedConnectionException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getdoc.GetDocRequest;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getdoc.GetDocResult;
|
||||
|
@ -17,17 +19,17 @@ import java.util.*;
|
|||
*/
|
||||
public class SnapshotFetcher {
|
||||
|
||||
public LinkedList<Snapshot> getSnapshotsForProjectAfterVersion(String projectName, int version) throws FailedConnectionException, SnapshotPostException {
|
||||
List<SnapshotInfo> snapshotInfos = getSnapshotInfosAfterVersion(projectName, version);
|
||||
List<SnapshotData> snapshotDatas = getMatchingSnapshotData(projectName, snapshotInfos);
|
||||
public LinkedList<Snapshot> getSnapshotsForProjectAfterVersion(Credential oauth2, String projectName, int version) throws FailedConnectionException, SnapshotPostException, ForbiddenException {
|
||||
List<SnapshotInfo> snapshotInfos = getSnapshotInfosAfterVersion(oauth2, projectName, version);
|
||||
List<SnapshotData> snapshotDatas = getMatchingSnapshotData(oauth2, projectName, snapshotInfos);
|
||||
LinkedList<Snapshot> snapshots = combine(snapshotInfos, snapshotDatas);
|
||||
return snapshots;
|
||||
}
|
||||
|
||||
private List<SnapshotInfo> getSnapshotInfosAfterVersion(String projectName, int version) throws FailedConnectionException, SnapshotPostException {
|
||||
private List<SnapshotInfo> getSnapshotInfosAfterVersion(Credential oauth2, String projectName, int version) throws FailedConnectionException, SnapshotPostException, ForbiddenException {
|
||||
SortedSet<SnapshotInfo> versions = new TreeSet<SnapshotInfo>();
|
||||
GetDocRequest getDoc = new GetDocRequest(projectName);
|
||||
GetSavedVersRequest getSavedVers = new GetSavedVersRequest(projectName);
|
||||
GetDocRequest getDoc = new GetDocRequest(oauth2, projectName);
|
||||
GetSavedVersRequest getSavedVers = new GetSavedVersRequest(oauth2, projectName);
|
||||
getDoc.request();
|
||||
getSavedVers.request();
|
||||
GetDocResult latestDoc = getDoc.getResult();
|
||||
|
@ -44,8 +46,8 @@ public class SnapshotFetcher {
|
|||
return new LinkedList<SnapshotInfo>(versions);
|
||||
}
|
||||
|
||||
private List<SnapshotData> getMatchingSnapshotData(String projectName, List<SnapshotInfo> snapshotInfos) throws FailedConnectionException {
|
||||
List<GetForVersionRequest> firedRequests = fireDataRequests(projectName, snapshotInfos);
|
||||
private List<SnapshotData> getMatchingSnapshotData(Credential oauth2, String projectName, List<SnapshotInfo> snapshotInfos) throws FailedConnectionException, ForbiddenException {
|
||||
List<GetForVersionRequest> firedRequests = fireDataRequests(oauth2, projectName, snapshotInfos);
|
||||
List<SnapshotData> snapshotDataList = new LinkedList<SnapshotData>();
|
||||
for (GetForVersionRequest fired : firedRequests) {
|
||||
snapshotDataList.add(fired.getResult().getSnapshotData());
|
||||
|
@ -53,10 +55,10 @@ public class SnapshotFetcher {
|
|||
return snapshotDataList;
|
||||
}
|
||||
|
||||
private List<GetForVersionRequest> fireDataRequests(String projectName, List<SnapshotInfo> snapshotInfos) {
|
||||
private List<GetForVersionRequest> fireDataRequests(Credential oauth2, String projectName, List<SnapshotInfo> snapshotInfos) {
|
||||
List<GetForVersionRequest> requests = new LinkedList<GetForVersionRequest>();
|
||||
for (SnapshotInfo snapshotInfo : snapshotInfos) {
|
||||
GetForVersionRequest request = new GetForVersionRequest(projectName, snapshotInfo.getVersionId());
|
||||
GetForVersionRequest request = new GetForVersionRequest(oauth2, projectName, snapshotInfo.getVersionId());
|
||||
requests.add(request);
|
||||
request.request();
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
package uk.ac.ic.wlgitbridge.data;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
|
||||
import org.eclipse.jgit.transport.ServiceMayNotContinueException;
|
||||
import uk.ac.ic.wlgitbridge.bridge.WLBridgedProject;
|
||||
import uk.ac.ic.wlgitbridge.bridge.BridgeAPI;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.base.ForbiddenException;
|
||||
import uk.ac.ic.wlgitbridge.util.Util;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.push.exception.InternalErrorException;
|
||||
|
||||
|
@ -23,8 +25,8 @@ public class SnapshotRepositoryBuilder {
|
|||
this.bridgeAPI = bridgeAPI;
|
||||
}
|
||||
|
||||
public Repository getRepositoryWithNameAtRootDirectory(String name, File rootDirectory) throws RepositoryNotFoundException, ServiceMayNotContinueException {
|
||||
if (!bridgeAPI.repositoryExists(name)) {
|
||||
public Repository getRepositoryWithNameAtRootDirectory(String name, File rootDirectory, Credential oauth2) throws RepositoryNotFoundException, ServiceMayNotContinueException, ForbiddenException {
|
||||
if (!bridgeAPI.repositoryExists(oauth2, name)) {
|
||||
throw new RepositoryNotFoundException(name);
|
||||
}
|
||||
File repositoryDirectory = new File(rootDirectory, name);
|
||||
|
@ -32,7 +34,7 @@ public class SnapshotRepositoryBuilder {
|
|||
Repository repository = null;
|
||||
try {
|
||||
repository = new FileRepositoryBuilder().setWorkTree(repositoryDirectory).build();
|
||||
new WLBridgedProject(repository, name, bridgeAPI).buildRepository();
|
||||
new WLBridgedProject(repository, name, bridgeAPI).buildRepository(oauth2);
|
||||
} catch (IOException e) {
|
||||
Util.printStackTrace(e);
|
||||
throw new ServiceMayNotContinueException(new InternalErrorException().getDescriptionLines().get(0));
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package uk.ac.ic.wlgitbridge.data.model;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.lib.PersonIdent;
|
||||
|
@ -10,6 +11,7 @@ import uk.ac.ic.wlgitbridge.data.filestore.GitDirectoryContents;
|
|||
import uk.ac.ic.wlgitbridge.data.filestore.RawDirectory;
|
||||
import uk.ac.ic.wlgitbridge.data.filestore.RawFile;
|
||||
import uk.ac.ic.wlgitbridge.data.model.db.PersistentStore;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.base.ForbiddenException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.exception.FailedConnectionException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.getforversion.SnapshotAttachment;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.push.exception.SnapshotPostException;
|
||||
|
@ -40,8 +42,8 @@ public class DataStore {
|
|||
resourceFetcher = new ResourceFetcher(persistentStore);
|
||||
}
|
||||
|
||||
public void updateProjectWithName(String name, Repository repository) throws IOException, SnapshotPostException, GitAPIException {
|
||||
LinkedList<Snapshot> snapshots = snapshotFetcher.getSnapshotsForProjectAfterVersion(name, persistentStore.getLatestVersionForProject(name));
|
||||
public void updateProjectWithName(Credential oauth2, String name, Repository repository) throws IOException, SnapshotPostException, GitAPIException, ForbiddenException {
|
||||
LinkedList<Snapshot> snapshots = snapshotFetcher.getSnapshotsForProjectAfterVersion(oauth2, name, persistentStore.getLatestVersionForProject(name));
|
||||
if (!snapshots.isEmpty()) {
|
||||
persistentStore.setLatestVersionForProject(name, snapshots.getLast().getVersionID());
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package uk.ac.ic.wlgitbridge.git.handler;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.transport.ReceivePack;
|
||||
import org.eclipse.jgit.transport.resolver.ReceivePackFactory;
|
||||
|
@ -7,6 +8,7 @@ import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
|
|||
import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
|
||||
import uk.ac.ic.wlgitbridge.bridge.BridgeAPI;
|
||||
import uk.ac.ic.wlgitbridge.git.handler.hook.WriteLatexPutHook;
|
||||
import uk.ac.ic.wlgitbridge.server.Oauth2Filter;
|
||||
import uk.ac.ic.wlgitbridge.util.Util;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -25,12 +27,13 @@ public class WLReceivePackFactory implements ReceivePackFactory<HttpServletReque
|
|||
|
||||
@Override
|
||||
public ReceivePack create(HttpServletRequest httpServletRequest, Repository repository) throws ServiceNotEnabledException, ServiceNotAuthorizedException {
|
||||
Credential oauth2 = (Credential) httpServletRequest.getAttribute(Oauth2Filter.ATTRIBUTE_KEY);
|
||||
ReceivePack receivePack = new ReceivePack(repository);
|
||||
String hostname = Util.getPostbackURL();
|
||||
if (hostname == null) {
|
||||
hostname = httpServletRequest.getLocalName();
|
||||
}
|
||||
receivePack.setPreReceiveHook(new WriteLatexPutHook(bridgeAPI, hostname));
|
||||
receivePack.setPreReceiveHook(new WriteLatexPutHook(bridgeAPI, hostname, oauth2));
|
||||
return receivePack;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
package uk.ac.ic.wlgitbridge.git.handler;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.transport.ServiceMayNotContinueException;
|
||||
import org.eclipse.jgit.transport.resolver.RepositoryResolver;
|
||||
import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException;
|
||||
import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException;
|
||||
import uk.ac.ic.wlgitbridge.application.config.Oauth2;
|
||||
import uk.ac.ic.wlgitbridge.data.SnapshotRepositoryBuilder;
|
||||
import uk.ac.ic.wlgitbridge.git.exception.InvalidRootDirectoryPathException;
|
||||
import uk.ac.ic.wlgitbridge.server.Oauth2Filter;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.base.ForbiddenException;
|
||||
import uk.ac.ic.wlgitbridge.util.Util;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
@ -28,8 +32,9 @@ public class WLRepositoryResolver implements RepositoryResolver<HttpServletReque
|
|||
|
||||
@Override
|
||||
public Repository open(HttpServletRequest httpServletRequest, String name) throws RepositoryNotFoundException, ServiceNotAuthorizedException, ServiceNotEnabledException, ServiceMayNotContinueException {
|
||||
Credential oauth2 = (Credential) httpServletRequest.getAttribute(Oauth2Filter.ATTRIBUTE_KEY);
|
||||
try {
|
||||
return snapshotRepositoryBuilder.getRepositoryWithNameAtRootDirectory(Util.removeAllSuffixes(name, "/", ".git"), rootGitDirectory);
|
||||
return snapshotRepositoryBuilder.getRepositoryWithNameAtRootDirectory(Util.removeAllSuffixes(name, "/", ".git"), rootGitDirectory, oauth2);
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
Util.printStackTrace(e);
|
||||
throw e;
|
||||
|
@ -44,6 +49,8 @@ public class WLRepositoryResolver implements RepositoryResolver<HttpServletReque
|
|||
} catch (RuntimeException e) {
|
||||
Util.printStackTrace(e);
|
||||
throw new ServiceMayNotContinueException(e);
|
||||
} catch (ForbiddenException e) {
|
||||
throw new ServiceNotAuthorizedException();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package uk.ac.ic.wlgitbridge.git.handler.hook;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.transport.PreReceiveHook;
|
||||
import org.eclipse.jgit.transport.ReceiveCommand;
|
||||
|
@ -10,6 +11,7 @@ import uk.ac.ic.wlgitbridge.git.handler.hook.exception.ForcedPushException;
|
|||
import uk.ac.ic.wlgitbridge.git.handler.hook.exception.WrongBranchException;
|
||||
import uk.ac.ic.wlgitbridge.data.filestore.RawDirectory;
|
||||
import uk.ac.ic.wlgitbridge.git.util.RepositoryObjectTreeWalker;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.base.ForbiddenException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.exception.FailedConnectionException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.push.exception.InternalErrorException;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.push.exception.OutOfDateException;
|
||||
|
@ -26,17 +28,19 @@ public class WriteLatexPutHook implements PreReceiveHook {
|
|||
|
||||
private final BridgeAPI bridgeAPI;
|
||||
private final String hostname;
|
||||
private final Credential oauth2;
|
||||
|
||||
public WriteLatexPutHook(BridgeAPI bridgeAPI, String hostname) {
|
||||
public WriteLatexPutHook(BridgeAPI bridgeAPI, String hostname, Credential oauth2) {
|
||||
this.bridgeAPI = bridgeAPI;
|
||||
this.hostname = hostname;
|
||||
this.oauth2 = oauth2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPreReceive(ReceivePack receivePack, Collection<ReceiveCommand> receiveCommands) {
|
||||
for (ReceiveCommand receiveCommand : receiveCommands) {
|
||||
try {
|
||||
handleReceiveCommand(receivePack.getRepository(), receiveCommand);
|
||||
handleReceiveCommand(oauth2, receivePack.getRepository(), receiveCommand);
|
||||
} catch (IOException e) {
|
||||
receivePack.sendError(e.getMessage());
|
||||
receiveCommand.setResult(Result.REJECTED_OTHER_REASON, e.getMessage());
|
||||
|
@ -60,14 +64,17 @@ public class WriteLatexPutHook implements PreReceiveHook {
|
|||
receiveCommand.setResult(Result.REJECTED_OTHER_REASON, message);
|
||||
}
|
||||
|
||||
private void handleReceiveCommand(Repository repository, ReceiveCommand receiveCommand) throws IOException, SnapshotPostException, FailedConnectionException {
|
||||
private void handleReceiveCommand(Credential oauth2, Repository repository, ReceiveCommand receiveCommand) throws IOException, SnapshotPostException, ForbiddenException {
|
||||
checkBranch(receiveCommand);
|
||||
checkForcedPush(receiveCommand);
|
||||
bridgeAPI.putDirectoryContentsToProjectWithName(repository.getWorkTree().getName(),
|
||||
bridgeAPI.putDirectoryContentsToProjectWithName(
|
||||
oauth2,
|
||||
repository.getWorkTree().getName(),
|
||||
getPushedDirectoryContents(repository,
|
||||
receiveCommand),
|
||||
getOldDirectoryContents(repository),
|
||||
hostname);
|
||||
hostname
|
||||
);
|
||||
}
|
||||
|
||||
private void checkBranch(ReceiveCommand receiveCommand) throws WrongBranchException {
|
||||
|
|
|
@ -4,6 +4,7 @@ import org.eclipse.jetty.server.Handler;
|
|||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.handler.HandlerCollection;
|
||||
import org.eclipse.jetty.server.handler.ResourceHandler;
|
||||
import org.eclipse.jetty.servlet.FilterHolder;
|
||||
import org.eclipse.jetty.servlet.ServletContextHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.util.log.Log;
|
||||
|
@ -15,9 +16,12 @@ import uk.ac.ic.wlgitbridge.git.servlet.WLGitServlet;
|
|||
import uk.ac.ic.wlgitbridge.snapshot.base.SnapshotAPIRequest;
|
||||
import uk.ac.ic.wlgitbridge.util.Util;
|
||||
|
||||
import javax.servlet.DispatcherType;
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.ServletException;
|
||||
import java.io.File;
|
||||
import java.net.BindException;
|
||||
import java.util.EnumSet;
|
||||
|
||||
/**
|
||||
* Created by Winston on 02/11/14.
|
||||
|
@ -36,23 +40,13 @@ public class GitBridgeServer {
|
|||
private String rootGitDirectoryPath;
|
||||
private String apiBaseURL;
|
||||
|
||||
/**
|
||||
* Constructs an instance of the server.
|
||||
* @param port the port number to listen on
|
||||
* @param rootGitDirectoryPath the root directory path containing the git repositories
|
||||
* @throws ServletException if the servlet throws an exception
|
||||
*/
|
||||
private GitBridgeServer(final int port, String rootGitDirectoryPath) throws ServletException, InvalidRootDirectoryPathException {
|
||||
public GitBridgeServer(Config config) throws ServletException, InvalidRootDirectoryPathException {
|
||||
Log.setLog(new NullLogger());
|
||||
this.port = port;
|
||||
this.rootGitDirectoryPath = rootGitDirectoryPath;
|
||||
this.port = config.getPort();
|
||||
this.rootGitDirectoryPath = config.getRootGitDirectory();
|
||||
bridgeAPI = new BridgeAPI(rootGitDirectoryPath);
|
||||
jettyServer = new Server(port);
|
||||
configureJettyServer();
|
||||
}
|
||||
|
||||
public GitBridgeServer(Config config) throws ServletException, InvalidRootDirectoryPathException {
|
||||
this(config.getPort(), config.getRootGitDirectory());
|
||||
configureJettyServer(config);
|
||||
SnapshotAPIRequest.setBasicAuth(config.getUsername(), config.getPassword());
|
||||
apiBaseURL = config.getAPIBaseURL();
|
||||
SnapshotAPIRequest.setBaseURL(apiBaseURL);
|
||||
|
@ -87,18 +81,22 @@ public class GitBridgeServer {
|
|||
}
|
||||
}
|
||||
|
||||
private void configureJettyServer() throws ServletException, InvalidRootDirectoryPathException {
|
||||
private void configureJettyServer(Config config) throws ServletException, InvalidRootDirectoryPathException {
|
||||
HandlerCollection handlers = new HandlerCollection();
|
||||
handlers.setHandlers(new Handler[] {
|
||||
initResourceHandler(),
|
||||
new PostbackHandler(bridgeAPI),
|
||||
initGitHandler()
|
||||
initGitHandler(config)
|
||||
});
|
||||
jettyServer.setHandler(handlers);
|
||||
}
|
||||
|
||||
private Handler initGitHandler() throws ServletException, InvalidRootDirectoryPathException {
|
||||
private Handler initGitHandler(Config config) throws ServletException, InvalidRootDirectoryPathException {
|
||||
final ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
|
||||
if (config.isUsingOauth2()) {
|
||||
Filter filter = new Oauth2Filter(config.getOauth2());
|
||||
servletContextHandler.addFilter(new FilterHolder(filter), "/*", EnumSet.of(DispatcherType.REQUEST));
|
||||
}
|
||||
servletContextHandler.setContextPath("/");
|
||||
servletContextHandler.addServlet(
|
||||
new ServletHolder(
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
package uk.ac.ic.wlgitbridge.server;
|
||||
|
||||
import com.google.api.client.auth.oauth2.*;
|
||||
import com.google.api.client.http.GenericUrl;
|
||||
import com.google.api.client.http.javanet.NetHttpTransport;
|
||||
import com.google.api.client.json.gson.GsonFactory;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.lang.StringUtils;
|
||||
import org.eclipse.jetty.server.Request;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import uk.ac.ic.wlgitbridge.application.config.Oauth2;
|
||||
import uk.ac.ic.wlgitbridge.util.Instance;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
/**
|
||||
* Created by winston on 25/10/15.
|
||||
*/
|
||||
public class Oauth2Filter implements Filter {
|
||||
|
||||
public static final String ATTRIBUTE_KEY = "oauth2";
|
||||
|
||||
private final Oauth2 oauth2;
|
||||
|
||||
public Oauth2Filter(Oauth2 oauth2) {
|
||||
this.oauth2 = oauth2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain)
|
||||
throws IOException, ServletException {
|
||||
|
||||
HttpServletRequest request = (HttpServletRequest) servletRequest;
|
||||
HttpServletResponse response = (HttpServletResponse) servletResponse;
|
||||
|
||||
String authHeader = request.getHeader("Authorization");
|
||||
if (authHeader != null) {
|
||||
StringTokenizer st = new StringTokenizer(authHeader);
|
||||
if (st.hasMoreTokens()) {
|
||||
String basic = st.nextToken();
|
||||
if (basic.equalsIgnoreCase("Basic")) {
|
||||
try {
|
||||
String credentials = new String(Base64.decodeBase64(st.nextToken()), "UTF-8");
|
||||
String[] split = credentials.split(":");
|
||||
if (split.length == 2) {
|
||||
String username = split[0];
|
||||
String password = split[1];
|
||||
String accessToken = null;
|
||||
try {
|
||||
accessToken = new PasswordTokenRequest(Instance.httpTransport, Instance.jsonFactory, new GenericUrl(oauth2.getOauth2Server() + "/oauth/token"), username, password)
|
||||
.setClientAuthentication(new ClientParametersAuthentication(oauth2.getOauth2ClientID(), oauth2.getOauth2ClientSecret()))
|
||||
.execute().getAccessToken();
|
||||
} catch (TokenResponseException e) {
|
||||
unauthorized(response, "bad credentials");
|
||||
return;
|
||||
}
|
||||
final Credential cred = new Credential.Builder(BearerToken.authorizationHeaderAccessMethod())
|
||||
.build();
|
||||
cred.setAccessToken(accessToken);
|
||||
servletRequest.setAttribute(ATTRIBUTE_KEY, cred);
|
||||
|
||||
filterChain.doFilter(servletRequest, servletResponse);
|
||||
} else {
|
||||
unauthorized(response, "Invalid authentication token");
|
||||
}
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
throw new Error("Couldn't retrieve authentication", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unauthorized(response);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
private void unauthorized(HttpServletResponse response, String message) throws IOException {
|
||||
response.setHeader("WWW-Authenticate", "Basic realm=\"Git Bridge\"");
|
||||
response.sendError(401, message);
|
||||
}
|
||||
|
||||
private void unauthorized(HttpServletResponse response) throws IOException {
|
||||
unauthorized(response, "Unauthorized");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package uk.ac.ic.wlgitbridge.snapshot.base;
|
||||
|
||||
/**
|
||||
* Created by winston on 25/10/15.
|
||||
*/
|
||||
public class ForbiddenException extends Throwable {
|
||||
}
|
|
@ -1,15 +1,18 @@
|
|||
package uk.ac.ic.wlgitbridge.snapshot.base;
|
||||
|
||||
import com.google.api.client.http.*;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.ning.http.client.AsyncCompletionHandler;
|
||||
import com.ning.http.client.AsyncHttpClient;
|
||||
import com.ning.http.client.AsyncHttpClient.BoundRequestBuilder;
|
||||
import com.ning.http.client.Realm;
|
||||
import com.ning.http.client.Response;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.exception.FailedConnectionException;
|
||||
import uk.ac.ic.wlgitbridge.util.Instance;
|
||||
import uk.ac.ic.wlgitbridge.util.Util;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
|
@ -22,12 +25,10 @@ public abstract class Request<T extends Result> {
|
|||
|
||||
private final String url;
|
||||
|
||||
private Future<T> future;
|
||||
private boolean error;
|
||||
private Future<HttpResponse> future;
|
||||
|
||||
public Request(String url) {
|
||||
this.url = url;
|
||||
error = false;
|
||||
}
|
||||
|
||||
public void request() {
|
||||
|
@ -43,54 +44,65 @@ public abstract class Request<T extends Result> {
|
|||
}
|
||||
}
|
||||
|
||||
public T getResult() throws FailedConnectionException {
|
||||
if (error) {
|
||||
throw new FailedConnectionException();
|
||||
}
|
||||
public T getResult() throws FailedConnectionException, ForbiddenException {
|
||||
try {
|
||||
return future.get();
|
||||
HttpResponse response = future.get();
|
||||
Util.sout(response.getStatusCode() + " " + response.getStatusMessage() + " (" + response.getHeaders().getContentLength() + "B) -> " + url);
|
||||
JsonElement json = new Gson().fromJson(response.parseAsString(), JsonElement.class);
|
||||
return parseResponse(json);
|
||||
} catch (InterruptedException e) {
|
||||
throw new FailedConnectionException();
|
||||
} catch (ExecutionException e) {
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof HttpResponseException && ((HttpResponseException) cause).getStatusCode() == HttpServletResponse.SC_FORBIDDEN) {
|
||||
throw new ForbiddenException();
|
||||
} else {
|
||||
throw new FailedConnectionException();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
Util.serr("Failed to parse JSON");
|
||||
e.printStackTrace();
|
||||
throw new FailedConnectionException();
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract HTTPMethod httpMethod();
|
||||
protected abstract Realm buildRequestRealm();
|
||||
|
||||
protected void onBeforeRequest(HttpRequest request) throws IOException {
|
||||
|
||||
}
|
||||
|
||||
protected abstract T parseResponse(JsonElement json) throws FailedConnectionException;
|
||||
|
||||
protected String getPostBody() {
|
||||
return "";
|
||||
return null;
|
||||
}
|
||||
|
||||
private void performGetRequest() {
|
||||
Util.sout("GET -> " + url);
|
||||
request(httpClient.prepareGet(url));
|
||||
try {
|
||||
HttpRequest request = Instance.httpRequestFactory.buildGetRequest(new GenericUrl(url));
|
||||
request(request);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void performPostRequest() {
|
||||
Util.sout("POST -> " + url);
|
||||
request(httpClient.preparePost(url).setBody(getPostBody()).setHeader("Content-Type", "application/json"));
|
||||
try {
|
||||
HttpRequest request = Instance.httpRequestFactory.buildPostRequest(new GenericUrl(url), new ByteArrayContent("application/json", getPostBody().getBytes()));
|
||||
request(request);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void request(BoundRequestBuilder boundRequestBuilder) {
|
||||
future = boundRequestBuilder.setRealm(buildRequestRealm()).execute(new AsyncCompletionHandler<T>() {
|
||||
|
||||
@Override
|
||||
public T onCompleted(Response response) throws Exception {
|
||||
String body = response.getResponseBody();
|
||||
Util.sout(response.getStatusCode() + " " + response.getStatusText() + " (" + body.length() + "B) -> " + url);
|
||||
return parseResponse(new Gson().fromJson(body, JsonElement.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onThrowable(Throwable t) {
|
||||
Util.printStackTrace(t);
|
||||
error = true;
|
||||
}
|
||||
|
||||
});
|
||||
private void request(HttpRequest request) throws IOException {
|
||||
onBeforeRequest(request);
|
||||
future = request.executeAsync();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,13 @@
|
|||
package uk.ac.ic.wlgitbridge.snapshot.base;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import com.google.api.client.http.BasicAuthentication;
|
||||
import com.google.api.client.http.HttpExecuteInterceptor;
|
||||
import com.google.api.client.http.HttpRequest;
|
||||
import com.ning.http.client.Realm;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Created by Winston on 06/11/14.
|
||||
*/
|
||||
|
@ -12,17 +18,26 @@ public abstract class SnapshotAPIRequest<T extends Result> extends Request<T> {
|
|||
|
||||
private static String BASE_URL;
|
||||
|
||||
public SnapshotAPIRequest(String projectName, String apiCall) {
|
||||
private final Credential oauth2;
|
||||
|
||||
public SnapshotAPIRequest(String projectName, String apiCall, Credential oauth2) {
|
||||
super(BASE_URL + projectName + apiCall);
|
||||
this.oauth2 = oauth2;
|
||||
}
|
||||
|
||||
protected Realm buildRequestRealm() {
|
||||
return new Realm.RealmBuilder()
|
||||
.setPrincipal(USERNAME)
|
||||
.setPassword(PASSWORD)
|
||||
.setUsePreemptiveAuth(true)
|
||||
.setScheme(Realm.AuthScheme.BASIC)
|
||||
.build();
|
||||
@Override
|
||||
protected void onBeforeRequest(HttpRequest request) throws IOException {
|
||||
request.setInterceptor(new HttpExecuteInterceptor() {
|
||||
|
||||
@Override
|
||||
public void intercept(HttpRequest request) throws IOException {
|
||||
new BasicAuthentication(USERNAME, PASSWORD).intercept(request);
|
||||
if (oauth2 != null) {
|
||||
oauth2.intercept(request);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
public static void setBasicAuth(String username, String password) {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package uk.ac.ic.wlgitbridge.snapshot.getdoc;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import com.google.gson.JsonElement;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.base.HTTPMethod;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.base.SnapshotAPIRequest;
|
||||
|
@ -12,8 +13,8 @@ public class GetDocRequest extends SnapshotAPIRequest<GetDocResult> {
|
|||
|
||||
public static final String API_CALL = "";
|
||||
|
||||
public GetDocRequest(String projectName) {
|
||||
super(projectName, API_CALL);
|
||||
public GetDocRequest(Credential oauth2, String projectName) {
|
||||
super(projectName, API_CALL, oauth2);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package uk.ac.ic.wlgitbridge.snapshot.getforversion;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import com.google.gson.JsonElement;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.base.HTTPMethod;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.base.SnapshotAPIRequest;
|
||||
|
@ -14,8 +15,8 @@ public class GetForVersionRequest extends SnapshotAPIRequest<GetForVersionResult
|
|||
|
||||
private int versionID;
|
||||
|
||||
public GetForVersionRequest(String projectName, int versionID) {
|
||||
super(projectName, API_CALL + "/" + versionID);
|
||||
public GetForVersionRequest(Credential oauth2, String projectName, int versionID) {
|
||||
super(projectName, API_CALL + "/" + versionID, oauth2);
|
||||
this.versionID = versionID;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package uk.ac.ic.wlgitbridge.snapshot.getsavedvers;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import com.google.gson.JsonElement;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.base.SnapshotAPIRequest;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.exception.FailedConnectionException;
|
||||
|
@ -12,8 +13,8 @@ public class GetSavedVersRequest extends SnapshotAPIRequest<GetSavedVersResult>
|
|||
|
||||
public static final String API_CALL = "/saved_vers";
|
||||
|
||||
public GetSavedVersRequest(String projectName) {
|
||||
super(projectName, API_CALL);
|
||||
public GetSavedVersRequest(Credential oauth2, String projectName) {
|
||||
super(projectName, API_CALL, oauth2);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package uk.ac.ic.wlgitbridge.snapshot.push;
|
||||
|
||||
import com.google.api.client.auth.oauth2.Credential;
|
||||
import com.google.gson.JsonElement;
|
||||
import uk.ac.ic.wlgitbridge.data.CandidateSnapshot;
|
||||
import uk.ac.ic.wlgitbridge.snapshot.base.HTTPMethod;
|
||||
|
@ -16,8 +17,8 @@ public class PushRequest extends SnapshotAPIRequest<PushResult> {
|
|||
private final CandidateSnapshot candidateSnapshot;
|
||||
private final String postbackKey;
|
||||
|
||||
public PushRequest(CandidateSnapshot candidateSnapshot, String postbackKey) {
|
||||
super(candidateSnapshot.getProjectName(), API_CALL);
|
||||
public PushRequest(Credential oauth2, CandidateSnapshot candidateSnapshot, String postbackKey) {
|
||||
super(candidateSnapshot.getProjectName(), API_CALL, oauth2);
|
||||
this.candidateSnapshot = candidateSnapshot;
|
||||
this.postbackKey = postbackKey;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
package uk.ac.ic.wlgitbridge.util;
|
||||
|
||||
import com.google.api.client.http.HttpRequestFactory;
|
||||
import com.google.api.client.http.HttpTransport;
|
||||
import com.google.api.client.http.javanet.NetHttpTransport;
|
||||
import com.google.api.client.json.JsonFactory;
|
||||
import com.google.api.client.json.gson.GsonFactory;
|
||||
|
||||
/**
|
||||
* Created by winston on 25/10/15.
|
||||
*/
|
||||
public class Instance {
|
||||
|
||||
public static final HttpTransport httpTransport = new NetHttpTransport();
|
||||
public static final HttpRequestFactory httpRequestFactory = httpTransport.createRequestFactory();
|
||||
public static final JsonFactory jsonFactory = new GsonFactory();
|
||||
|
||||
}
|
Loading…
Reference in a new issue