Implementation of OAuth2

This commit is contained in:
Winston Li 2015-10-25 13:44:38 +00:00
parent c3db415ce7
commit 1872eba223
18 changed files with 281 additions and 100 deletions

View file

@ -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()) {

View file

@ -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);
}
}

View file

@ -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();
}

View file

@ -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));

View file

@ -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());
}

View file

@ -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;
}

View file

@ -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();
}
}

View file

@ -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 {

View file

@ -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(

View file

@ -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");
}
}

View file

@ -0,0 +1,7 @@
package uk.ac.ic.wlgitbridge.snapshot.base;
/**
* Created by winston on 25/10/15.
*/
public class ForbiddenException extends Throwable {
}

View file

@ -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();
}
}

View file

@ -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) {

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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();
}