Merge pull request #12997 from overleaf/em-git-bridge-pat-messaging

Adapt git bridge messaging to personal access tokens

GitOrigin-RevId: 0b5d5ecbd97814c8b18827fe11e77513c11bab3a
This commit is contained in:
Eric Mc Sween 2023-05-15 08:01:27 -04:00 committed by Copybot
parent e306369b9a
commit effccf2d3a
148 changed files with 582 additions and 406 deletions

View file

@ -0,0 +1,21 @@
package uk.ac.ic.wlgitbridge.server;
public class BasicAuthCredentials {
private String username;
private String password;
public BasicAuthCredentials(String username, String password) {
this.username = username;
this.password = password;
}
public String getUsername() {
return username;
}
public String getPassword() {
return password;
}
}

View file

@ -2,6 +2,9 @@ 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.HttpHeaders;
import com.google.api.client.http.HttpRequest;
import com.google.api.client.http.HttpResponse;
import org.apache.commons.codec.binary.Base64;
import org.eclipse.jetty.server.Request;
import uk.ac.ic.wlgitbridge.application.config.Oauth2;
@ -43,18 +46,6 @@ public class Oauth2Filter implements Filter {
@Override
public void init(FilterConfig filterConfig) {}
private void sendResponse(ServletResponse servletResponse, int code, List<String> lines) throws IOException {
HttpServletResponse response = ((HttpServletResponse) servletResponse);
response.setContentType("text/plain");
response.setStatus(code);
PrintWriter w = response.getWriter();
for (String line : lines) {
w.println(line);
}
w.close();
return;
}
/**
* The original request from git will not contain the Authorization header.
*
@ -68,216 +59,343 @@ public class Oauth2Filter implements Filter {
*/
@Override
public void doFilter(
ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain
) throws IOException, ServletException {
String requestUri = ((Request) servletRequest).getRequestURI();
if (requestUri.startsWith("/project")) {
Log.info("[{}] Invalid request URI", requestUri);
sendResponse(servletResponse,404, Arrays.asList(
"Invalid Project ID (must not have a '/project' prefix)"
));
return;
}
String project = Util.removeAllSuffixes(
requestUri.split("/")[1],
".git"
);
// Reject v1 ids, the request will be rejected by v1 anyway
if (project.matches("^[0-9]+[bcdfghjklmnpqrstvwxyz]{6,12}$") && !project.matches("^[0-9a-f]{24}$")) {
Log.info("[{}] Request for v1 project, refusing", project);
sendResponse(servletResponse, 404, Arrays.asList(
"This project has not yet been moved into the new version",
"of Overleaf. You will need to move it in order to continue working on it.",
"Please visit this project online on www.overleaf.com to do this.",
"",
"You can find the new git remote url by selecting \"Git\" from",
"the left sidebar in the project view.",
"",
"If this is unexpected, please contact us at support@overleaf.com, or",
"see https://www.overleaf.com/help/342 for more information."
));
return;
}
Log.debug("[{}] Checking if auth needed", project);
GetDocRequest doc = new GetDocRequest(project);
doc.request();
try {
SnapshotApi.getResult(
snapshotApi.getDoc(Optional.empty(), project));
} catch (ForbiddenException e) {
Log.debug("[{}] Auth needed", project);
getAndInjectCredentials(
project,
servletRequest,
servletResponse,
filterChain
);
return;
} catch (MissingRepositoryException e) {
handleMissingRepository(project, e, (HttpServletResponse) servletResponse);
}
Log.debug("[{}] Auth not needed", project);
filterChain.doFilter(servletRequest, servletResponse);
}
// TODO: this is ridiculous. Check for error cases first, then return/throw
// TODO: also, use an Optional credential, since we treat it as optional
private void getAndInjectCredentials(
String projectName,
ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain
ServletRequest servletRequest,
ServletResponse servletResponse,
FilterChain filterChain
) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
HttpServletResponse response = (HttpServletResponse) servletResponse;
String capturedUsername = "(unknown)";
String requestUri = request.getRequestURI();
String authHeader = request.getHeader("Authorization");
if (authHeader != null) {
String clientIp = request.getHeader("X-Forwarded-For");
if (clientIp == null) {
clientIp = request.getRemoteAddr();
}
Log.debug("[{}] Authorization header present", clientIp);
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(":",2);
if (split.length == 2) {
String username = split[0];
String password = split[1];
final Credential cred = new Credential.Builder(
BearerToken.authorizationHeaderAccessMethod()
).build();
if(username.equals("git")) {
Log.debug("[{}] username is 'git', skipping password grant flow", projectName);
cred.setAccessToken(password);
} else if (this.isUserPasswordEnabled) {
String accessToken = null;
if (username.length() > 0) {
capturedUsername = username;
}
try {
accessToken = new PasswordTokenRequest(
Instance.httpTransport,
Instance.jsonFactory,
new GenericUrl(
oauth2.getOauth2Server()
+ "/oauth/token?client_ip="
+ clientIp
),
username,
password
).setClientAuthentication(
new ClientParametersAuthentication(
oauth2.getOauth2ClientID(),
oauth2.getOauth2ClientSecret()
)
).execute().getAccessToken();
} catch (TokenResponseException e) {
handleNeedAuthorization(projectName, capturedUsername, e.getStatusCode(), request, response);
return;
}
cred.setAccessToken(accessToken);
}
servletRequest.setAttribute(ATTRIBUTE_KEY, cred);
filterChain.doFilter(
servletRequest,
servletResponse
);
} else {
handleNeedAuthorization(projectName, capturedUsername, 0, request, response);
}
} catch (UnsupportedEncodingException e) {
throw new Error("Couldn't retrieve authentication", e);
}
}
}
} else {
handleNeedAuthorization(projectName, capturedUsername, 0, request, response);
if (requestUri.startsWith("/project")) {
Log.info("[{}] Invalid request URI", requestUri);
sendResponse(response,404, Arrays.asList(
"Invalid Project ID (must not have a '/project' prefix)"
));
return;
}
String projectId = Util.removeAllSuffixes(requestUri.split("/")[1], ".git");
BasicAuthCredentials basicAuthCreds = getBasicAuthCredentials(request);
if (basicAuthCreds == null) {
handleNeedAuthorization(projectId, "(unknown)", request, response);
return;
}
String username = basicAuthCreds.getUsername();
String password = basicAuthCreds.getPassword();
if (isLinkSharingId(projectId)) {
handleLinkSharingId(projectId, username, request, response);
return;
}
if (!isProjectId(projectId)) {
handleBadProjectId(projectId, username, request, response);
return;
}
final Credential cred = new Credential.Builder(
BearerToken.authorizationHeaderAccessMethod()
).build();
if (username.equals("git")) {
Log.debug("[{}] username is 'git', skipping password grant flow", projectId);
// Check that the access token is valid. In principle, we could
// wait until we make the actual request to the web api, but the
// JGit API doesn't make it easy to reply with a 401 and a custom
// error message. This is something we can do in this filter, so as
// a workaround, we use the /oauth/token/info endpoint to verify
// the access token.
//
// It's still theoretically possible for the web api request to
// fail later (for example, in the unlikely event that the token
// expired between the two requests). In that case, JGit will
// return a 401 without a custom error message.
int statusCode = checkAccessToken(oauth2, password, getClientIp(request));
if (statusCode == 429) {
handleRateLimit(projectId, username, request, response);
return;
} else if (statusCode == 401) {
handleBadAccessToken(projectId, request, response);
return;
} else if (statusCode >= 400) {
handleUnknownOauthServerError(projectId, statusCode, request, response);
return;
}
cred.setAccessToken(password);
} else if (this.isUserPasswordEnabled) {
String accessToken = null;
try {
accessToken = doPasswordGrantFlow(username, password, getClientIp(request));
} catch (TokenResponseException e) {
int statusCode = e.getStatusCode();
if (statusCode == 429) {
handleRateLimit(projectId, username, request, response);
} else if (statusCode == 400 || statusCode == 401) {
handleNeedAuthorization(projectId, username, request, response);
} else {
handleUnknownOauthServerError(projectId, statusCode, request, response);
}
return;
}
cred.setAccessToken(accessToken);
} else {
handleNeedAuthorization(projectId, username, request, response);
return;
}
servletRequest.setAttribute(ATTRIBUTE_KEY, cred);
filterChain.doFilter(
servletRequest,
servletResponse
);
}
@Override
public void destroy() {}
private void handleNeedAuthorization(
String projectName,
String userName,
int statusCode,
HttpServletRequest servletRequest,
HttpServletResponse servletResponse
) throws IOException {
Log.info(
"[{}] Unauthorized, User '{}' status={} ip={}",
projectName,
userName,
statusCode,
servletRequest.getRemoteAddr()
);
HttpServletResponse response = servletResponse;
response.setContentType("text/plain");
response.setHeader("WWW-Authenticate", "Basic realm=\"Git Bridge\"");
PrintWriter w = response.getWriter();
if (statusCode == 429) {
// Rate limit
response.setStatus(429);
w.println(
"Rate limit exceeded. Please wait and try again later."
);
} else {
response.setStatus(401);
w.println(
"Please sign in using your email address and Overleaf password."
);
w.println();
w.println(
"*Note*: if you sign in to Overleaf using another provider, "
+ "such "
);
w.println(
"as Google or Twitter, you need to set a password "
+ "on your Overleaf "
);
w.println(
"account first. "
+ "Please see https://www.overleaf.com/learn/how-to/Troubleshooting_git_bridge_problems "
);
w.println("for more information.");
}
w.close();
private boolean isLinkSharingId(String projectId) {
return projectId.matches("^[0-9]+[bcdfghjklmnpqrstvwxyz]{6,12}$");
}
private void handleMissingRepository(
String projectName,
MissingRepositoryException e,
HttpServletResponse response
) throws IOException {
Log.info("[{}] Project missing.", projectName);
private boolean isProjectId(String projectId) {
return projectId.matches("^[0-9a-f]{24}$");
}
private void sendResponse(HttpServletResponse response, int code, List<String> lines) throws IOException {
response.setContentType("text/plain");
// git special-cases 404 to give "repository '%s' not found",
// rather than displaying the raw status code.
response.setStatus(404);
response.setStatus(code);
PrintWriter w = response.getWriter();
for (String line : e.getDescriptionLines()) {
for (String line : lines) {
w.println(line);
}
w.close();
}
private void handleLinkSharingId(
String projectId,
String username,
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
Log.info(
"[{}] Bad project id, User '{}' ip={}",
projectId,
username,
getClientIp(request)
);
sendResponse(response, 404, Arrays.asList(
"Git access via link sharing link is not supported.",
"",
"You can find the project's git remote url by opening it in your browser",
"and selecting Git from the left sidebar in the project view.",
"",
"If this is unexpected, please contact us at support@overleaf.com, or",
"see https://www.overleaf.com/help/342 for more information."
));
}
private void handleBadProjectId(
String projectId,
String username,
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
Log.info(
"[{}] Bad project id, User '{}' ip={}",
projectId,
username,
getClientIp(request)
);
sendResponse(response, 404, Arrays.asList(
"This Overleaf project does not exist.",
"",
"If this is unexpected, please contact us at support@overleaf.com, or",
"see https://www.overleaf.com/help/342 for more information."
));
}
private void handleRateLimit(
String projectId,
String username,
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
Log.info(
"[{}] Rate limit, User '{}' ip={}",
projectId,
username,
getClientIp(request)
);
sendResponse(response, 429, Arrays.asList(
"Rate limit exceeded. Please wait and try again later."
));
}
private void handleNeedAuthorization(
String projectId,
String username,
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
Log.info(
"[{}] Unauthorized, User '{}' ip={}",
projectId,
username,
getClientIp(request)
);
response.setHeader("WWW-Authenticate", "Basic realm=\"Git Bridge\"");
if (this.isUserPasswordEnabled) {
sendResponse(response, 401, Arrays.asList(
"Log in using the email address and password you use for Overleaf.",
"",
"*Note*: if you use a provider such as Google or Twitter to sign into",
"your Overleaf account, you will need to set a password.",
"",
"See our help page for more support:",
"https://www.overleaf.com/learn/how-to/Troubleshooting_git_bridge_problems"
));
} else {
sendResponse(response, 401, Arrays.asList(
"Log in with the username 'git' and enter your Git authentication token",
"when prompted for a password.",
"",
"You can generate and manage your Git authentication tokens in",
"your Overleaf Account Settings."
));
}
}
private void handleBadAccessToken(
String projectId,
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
Log.info(
"[{}] Bad access token, ip={}",
projectId,
getClientIp(request)
);
sendResponse(response, 401, Arrays.asList(
"Enter your Git authentication token when prompted for a password.",
"",
"You can generate and manage your Git authentication tokens in",
"your Overleaf Account Settings."
));
}
private int checkAccessToken(
Oauth2 oauth2,
String accessToken,
String clientIp
) throws IOException {
GenericUrl url = new GenericUrl(
oauth2.getOauth2Server() + "/oauth/token/info?client_ip=" + clientIp
);
HttpRequest request = Instance.httpRequestFactory.buildGetRequest(url);
HttpHeaders headers = new HttpHeaders();
headers.setAuthorization("Bearer " + accessToken);
request.setHeaders(headers);
request.setThrowExceptionOnExecuteError(false);
HttpResponse response = request.execute();
int statusCode = response.getStatusCode();
response.disconnect();
return statusCode;
}
private void handleUnknownOauthServerError(
String projectId,
int statusCode,
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
Log.info(
"[{}] OAuth server error, statusCode={}, ip={}",
projectId,
statusCode,
getClientIp(request)
);
sendResponse(response, 500, Arrays.asList(
"Unexpected server error. Please try again later."
));
}
/**
* Gets the remote IP from the request.
*/
private String getClientIp(HttpServletRequest request) {
String clientIp = request.getHeader("X-Forwarded-For");
if (clientIp == null) {
clientIp = request.getRemoteAddr();
}
return clientIp;
}
/**
* Extract basic auth credentials from the request.
*
* Returns null if valid basic auth credentials couldn't be found.
*/
private BasicAuthCredentials getBasicAuthCredentials(HttpServletRequest request) {
String authHeader = request.getHeader("Authorization");
if (authHeader == null) {
return null;
}
StringTokenizer st = new StringTokenizer(authHeader);
if (!st.hasMoreTokens()) {
return null;
}
String basic = st.nextToken();
if (!basic.equalsIgnoreCase("Basic")) {
return null;
}
String credentials = null;
try {
credentials = new String(
Base64.decodeBase64(st.nextToken()),
"UTF-8"
);
} catch (UnsupportedEncodingException e) {
return null;
}
String[] split = credentials.split(":", 2);
if (split.length != 2) {
return null;
}
String username = split[0];
String password = split[1];
return new BasicAuthCredentials(username, password);
}
/**
* Perform a password grant flow with the OAuth server and return an access token.
*
* The access token is null if the password grant flow was unsuccessful.
*/
private String doPasswordGrantFlow(
String username,
String password,
String clientIp
) throws IOException {
return new PasswordTokenRequest(
Instance.httpTransport,
Instance.jsonFactory,
new GenericUrl(
oauth2.getOauth2Server()
+ "/oauth/token?client_ip="
+ clientIp
),
username,
password
).setClientAuthentication(
new ClientParametersAuthentication(
oauth2.getOauth2ClientID(),
oauth2.getOauth2ClientSecret()
)
).execute().getAccessToken();
}
}

View file

@ -0,0 +1,28 @@
package uk.ac.ic.wlgitbridge.snapshot.servermock.server;
import java.io.IOException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.Request;
import uk.ac.ic.wlgitbridge.util.Log;
public class MockOAuthRequestHandler extends AbstractHandler {
@Override
public void handle(
String target,
Request baseRequest,
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
String method = baseRequest.getMethod();
if (method.equals("GET") && target.equals("/oauth/token/info")) {
response.setContentType("application/json");
response.setStatus(HttpServletResponse.SC_OK);
response.getWriter().println("{}");
baseRequest.setHandled(true);
}
}
}

View file

@ -3,6 +3,7 @@ package uk.ac.ic.wlgitbridge.snapshot.servermock.server;
import org.eclipse.jetty.server.NetworkConnector;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.HandlerList;
import org.eclipse.jetty.server.handler.ResourceHandler;
import uk.ac.ic.wlgitbridge.snapshot.servermock.response.SnapshotResponseBuilder;
import uk.ac.ic.wlgitbridge.snapshot.servermock.state.SnapshotAPIState;
@ -22,7 +23,11 @@ public class MockSnapshotServer {
public MockSnapshotServer(int port, File resourceBase) {
server = new Server(port);
responseBuilder = new SnapshotResponseBuilder();
server.setHandler(getHandlerForResourceBase(resourceBase));
HandlerList handlers = new HandlerList();
handlers.addHandler(new MockOAuthRequestHandler());
handlers.addHandler(getHandlerForResourceBase(resourceBase));
server.setHandler(handlers);
}
private HandlerCollection getHandlerForResourceBase(File resourceBase) {

View file

@ -51,6 +51,10 @@ public class WLGitBridgeIntegrationTest {
private Runtime runtime = Runtime.getRuntime();
private static final String PROJECT_ID = "000000000000000000000000";
private static final String PROJECT_ID1 = "111111111111111111111111";
private static final String PROJECT_ID2 = "222222222222222222222222";
private Map<String, Map<String, SnapshotAPIState>> states = new HashMap<String, Map<String, SnapshotAPIState>>() {{
put("canCloneARepository", new HashMap<String, SnapshotAPIState>() {{
put("state", new SnapshotAPIStateBuilder(getResourceAsStream("/canCloneARepository/state/state.json")).build());
@ -185,7 +189,7 @@ public class WLGitBridgeIntegrationTest {
}
private File gitClone(String repositoryName, int port, File dir) throws IOException, InterruptedException {
String repo = "git clone http://127.0.0.1:" + port + "/" + repositoryName + ".git";
String repo = "git clone http://git:password@127.0.0.1:" + port + "/" + repositoryName;
Process gitProcess = runtime.exec(repo, null, dir);
int exitCode = gitProcess.waitFor();
if (exitCode != 0) {
@ -259,8 +263,8 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(33857, 3857)
});
wlgb.run();
File testprojDir = gitClone("testproj", 33857, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canCloneARepository/state/testproj"), testprojDir.toPath()));
File testprojDir = gitClone(PROJECT_ID, 33857, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canCloneARepository/state/" + PROJECT_ID), testprojDir.toPath()));
}
@Test
@ -272,10 +276,10 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(33858, 3858)
});
wlgb.run();
File testproj1Dir = gitClone("testproj1", 33858, dir);
File testproj2Dir = gitClone("testproj2", 33858, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canCloneMultipleRepositories/state/testproj1"), testproj1Dir.toPath()));
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canCloneMultipleRepositories/state/testproj2"), testproj2Dir.toPath()));
File testproj1Dir = gitClone(PROJECT_ID1, 33858, dir);
File testproj2Dir = gitClone(PROJECT_ID2, 33858, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canCloneMultipleRepositories/state/" + PROJECT_ID1), testproj1Dir.toPath()));
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canCloneMultipleRepositories/state/" + PROJECT_ID2), testproj2Dir.toPath()));
}
@Test
@ -287,11 +291,11 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(33859, 3859)
});
wlgb.run();
File testprojDir = gitClone("testproj", 33859, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullAModifiedTexFile/base/testproj"), testprojDir.toPath()));
File testprojDir = gitClone(PROJECT_ID, 33859, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullAModifiedTexFile/base/" + PROJECT_ID), testprojDir.toPath()));
server.setState(states.get("canPullAModifiedTexFile").get("withModifiedTexFile"));
gitPull(testprojDir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullAModifiedTexFile/withModifiedTexFile/testproj"), testprojDir.toPath()));
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullAModifiedTexFile/withModifiedTexFile/" + PROJECT_ID), testprojDir.toPath()));
}
@Test
@ -303,11 +307,11 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(33860, 3860)
});
wlgb.run();
File testprojDir = gitClone("testproj", 33860, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullADeletedTexFile/base/testproj"), testprojDir.toPath()));
File testprojDir = gitClone(PROJECT_ID, 33860, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullADeletedTexFile/base/" + PROJECT_ID), testprojDir.toPath()));
server.setState(states.get("canPullADeletedTexFile").get("withDeletedTexFile"));
gitPull(testprojDir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullADeletedTexFile/withDeletedTexFile/testproj"), testprojDir.toPath()));
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullADeletedTexFile/withDeletedTexFile/" + PROJECT_ID), testprojDir.toPath()));
}
@Test
@ -319,11 +323,11 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(33862, 3862)
});
wlgb.run();
File testprojDir = gitClone("testproj", 33862, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullAModifiedBinaryFile/base/testproj"), testprojDir.toPath()));
File testprojDir = gitClone(PROJECT_ID, 33862, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullAModifiedBinaryFile/base/" + PROJECT_ID), testprojDir.toPath()));
server.setState(states.get("canPullAModifiedBinaryFile").get("withModifiedBinaryFile"));
gitPull(testprojDir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullAModifiedBinaryFile/withModifiedBinaryFile/testproj"), testprojDir.toPath()));
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullAModifiedBinaryFile/withModifiedBinaryFile/" + PROJECT_ID), testprojDir.toPath()));
}
@Test
@ -335,11 +339,11 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(33863, 3863)
});
wlgb.run();
File testprojDir = gitClone("testproj", 33863, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullADeletedBinaryFile/base/testproj"), testprojDir.toPath()));
File testprojDir = gitClone(PROJECT_ID, 33863, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullADeletedBinaryFile/base/" + PROJECT_ID), testprojDir.toPath()));
server.setState(states.get("canPullADeletedBinaryFile").get("withDeletedBinaryFile"));
gitPull(testprojDir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullADeletedBinaryFile/withDeletedBinaryFile/testproj"), testprojDir.toPath()));
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullADeletedBinaryFile/withDeletedBinaryFile/" + PROJECT_ID), testprojDir.toPath()));
}
@Test
@ -351,11 +355,11 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(44001, 4001)
});
wlgb.run();
File testprojDir = gitClone("testproj", 44001, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullADuplicateBinaryFile/base/testproj"), testprojDir.toPath()));
File testprojDir = gitClone(PROJECT_ID, 44001, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullADuplicateBinaryFile/base/" + PROJECT_ID), testprojDir.toPath()));
server.setState(states.get("canPullADuplicateBinaryFile").get("withDuplicateBinaryFile"));
gitPull(testprojDir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullADuplicateBinaryFile/withDuplicateBinaryFile/testproj"), testprojDir.toPath()));
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullADuplicateBinaryFile/withDuplicateBinaryFile/" + PROJECT_ID), testprojDir.toPath()));
}
@Test
@ -367,8 +371,8 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(44002, 4002)
});
wlgb.run();
File testprojDir = gitClone("testproj", 44002, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canCloneDuplicateBinaryFiles/state/testproj"), testprojDir.toPath()));
File testprojDir = gitClone(PROJECT_ID, 44002, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canCloneDuplicateBinaryFiles/state/" + PROJECT_ID), testprojDir.toPath()));
}
@Test
@ -380,11 +384,11 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(44003, 4003)
});
wlgb.run();
File testprojDir = gitClone("testproj", 44003, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullUpdatedBinaryFiles/base/testproj"), testprojDir.toPath()));
File testprojDir = gitClone(PROJECT_ID, 44003, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullUpdatedBinaryFiles/base/" + PROJECT_ID), testprojDir.toPath()));
server.setState(states.get("canPullUpdatedBinaryFiles").get("withUpdatedBinaryFiles"));
gitPull(testprojDir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullUpdatedBinaryFiles/withUpdatedBinaryFiles/testproj"), testprojDir.toPath()));
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullUpdatedBinaryFiles/withUpdatedBinaryFiles/" + PROJECT_ID), testprojDir.toPath()));
}
@Test
@ -396,11 +400,11 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(33864, 3864)
});
wlgb.run();
File testprojDir = gitClone("testproj", 33864, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullAModifiedNestedFile/base/testproj"), testprojDir.toPath()));
File testprojDir = gitClone(PROJECT_ID, 33864, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullAModifiedNestedFile/base/" + PROJECT_ID), testprojDir.toPath()));
server.setState(states.get("canPullAModifiedNestedFile").get("withModifiedNestedFile"));
gitPull(testprojDir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullAModifiedNestedFile/withModifiedNestedFile/testproj"), testprojDir.toPath()));
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullAModifiedNestedFile/withModifiedNestedFile/" + PROJECT_ID), testprojDir.toPath()));
}
@Test
@ -412,11 +416,11 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(33865, 3865)
});
wlgb.run();
File testprojDir = gitClone("testproj", 33865, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullDeletedNestedFiles/base/testproj"), testprojDir.toPath()));
File testprojDir = gitClone(PROJECT_ID, 33865, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullDeletedNestedFiles/base/" + PROJECT_ID), testprojDir.toPath()));
server.setState(states.get("canPullDeletedNestedFiles").get("withDeletedNestedFiles"));
gitPull(testprojDir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullDeletedNestedFiles/withDeletedNestedFiles/testproj"), testprojDir.toPath()));
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPullDeletedNestedFiles/withDeletedNestedFiles/" + PROJECT_ID), testprojDir.toPath()));
}
@Test
@ -428,8 +432,8 @@ public class WLGitBridgeIntegrationTest {
});
wlgb.run();
server.setState(states.get("canPushFilesSuccessfully").get("state"));
File testprojDir = gitClone("testproj", 33866, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPushFilesSuccessfully/state/testproj"), testprojDir.toPath()));
File testprojDir = gitClone(PROJECT_ID, 33866, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canPushFilesSuccessfully/state/" + PROJECT_ID), testprojDir.toPath()));
assertEquals(0, runtime.exec("touch push.tex", null, testprojDir).waitFor());
gitAdd(testprojDir);
gitCommit(testprojDir, "push");
@ -437,7 +441,7 @@ public class WLGitBridgeIntegrationTest {
}
private static final String EXPECTED_OUT_PUSH_OUT_OF_DATE_FIRST =
"error: failed to push some refs to 'http://127.0.0.1:33867/testproj.git'\n" +
"error: failed to push some refs to 'http://127.0.0.1:33867/" + PROJECT_ID + "'\n" +
"hint: Updates were rejected because the tip of your current branch is behind\n" +
"hint: its remote counterpart. Integrate the remote changes (e.g.\n" +
"hint: 'git pull ...') before pushing again.\n" +
@ -452,8 +456,8 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(33867, 3867)
});
wlgb.run();
File testprojDir = gitClone("testproj", 33867, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/pushFailsOnFirstStageOutOfDate/state/testproj"), testprojDir.toPath()));
File testprojDir = gitClone(PROJECT_ID, 33867, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/pushFailsOnFirstStageOutOfDate/state/" + PROJECT_ID), testprojDir.toPath()));
runtime.exec("touch push.tex", null, testprojDir).waitFor();
gitAdd(testprojDir);
gitCommit(testprojDir, "push");
@ -462,7 +466,7 @@ public class WLGitBridgeIntegrationTest {
}
private static final String EXPECTED_OUT_PUSH_OUT_OF_DATE_SECOND =
"error: failed to push some refs to 'http://127.0.0.1:33868/testproj.git'\n" +
"error: failed to push some refs to 'http://127.0.0.1:33868/" + PROJECT_ID + "'\n" +
"hint: Updates were rejected because the tip of your current branch is behind\n" +
"hint: its remote counterpart. Integrate the remote changes (e.g.\n" +
"hint: 'git pull ...') before pushing again.\n" +
@ -477,8 +481,8 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(33868, 3868)
});
wlgb.run();
File testprojDir = gitClone("testproj", 33868, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/pushFailsOnSecondStageOutOfDate/state/testproj"), testprojDir.toPath()));
File testprojDir = gitClone(PROJECT_ID, 33868, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/pushFailsOnSecondStageOutOfDate/state/" + PROJECT_ID), testprojDir.toPath()));
runtime.exec("touch push.tex", null, testprojDir).waitFor();
gitAdd(testprojDir);
gitCommit(testprojDir, "push");
@ -492,9 +496,9 @@ public class WLGitBridgeIntegrationTest {
"remote: hint: file2.exe (invalid file extension)",
"remote: hint: hello world.png (rename to: hello_world.png)",
"remote: hint: an image.jpg (rename to: an_image.jpg)",
"To http://127.0.0.1:33869/testproj.git",
"To http://127.0.0.1:33869/" + PROJECT_ID,
"! [remote rejected] master -> master (invalid files)",
"error: failed to push some refs to 'http://127.0.0.1:33869/testproj.git'"
"error: failed to push some refs to 'http://127.0.0.1:33869/" + PROJECT_ID + "'"
);
@Test
@ -506,8 +510,8 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(33869, 3869)
});
wlgb.run();
File testprojDir = gitClone("testproj", 33869, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/pushFailsOnInvalidFiles/state/testproj"), testprojDir.toPath()));
File testprojDir = gitClone(PROJECT_ID, 33869, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/pushFailsOnInvalidFiles/state/" + PROJECT_ID), testprojDir.toPath()));
runtime.exec("touch push.tex", null, testprojDir).waitFor();
gitAdd(testprojDir);
gitCommit(testprojDir, "push");
@ -519,9 +523,9 @@ public class WLGitBridgeIntegrationTest {
private static final List<String> EXPECTED_OUT_PUSH_INVALID_PROJECT = Arrays.asList(
"remote: hint: project: no main file",
"remote: hint: The project would have no (editable) main .tex file.",
"To http://127.0.0.1:33870/testproj.git",
"To http://127.0.0.1:33870/" + PROJECT_ID,
"! [remote rejected] master -> master (invalid project)",
"error: failed to push some refs to 'http://127.0.0.1:33870/testproj.git'"
"error: failed to push some refs to 'http://127.0.0.1:33870/" + PROJECT_ID + "'"
);
@Test
@ -533,8 +537,8 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(33870, 3870)
});
wlgb.run();
File testprojDir = gitClone("testproj", 33870, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/pushFailsOnInvalidProject/state/testproj"), testprojDir.toPath()));
File testprojDir = gitClone(PROJECT_ID, 33870, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/pushFailsOnInvalidProject/state/" + PROJECT_ID), testprojDir.toPath()));
runtime.exec("touch push.tex", null, testprojDir).waitFor();
gitAdd(testprojDir);
gitCommit(testprojDir, "push");
@ -546,9 +550,9 @@ public class WLGitBridgeIntegrationTest {
private static final List<String> EXPECTED_OUT_PUSH_UNEXPECTED_ERROR = Arrays.asList(
"remote: hint: There was an internal error with the Overleaf server.",
"remote: hint: Please contact Overleaf.",
"To http://127.0.0.1:33871/testproj.git",
"To http://127.0.0.1:33871/" + PROJECT_ID,
"! [remote rejected] master -> master (Overleaf error)",
"error: failed to push some refs to 'http://127.0.0.1:33871/testproj.git'"
"error: failed to push some refs to 'http://127.0.0.1:33871/" + PROJECT_ID + "'"
);
/* this one prints a stack trace */
@ -561,8 +565,8 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(33871, 3871)
});
wlgb.run();
File testprojDir = gitClone("testproj", 33871, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/pushFailsOnUnexpectedError/state/testproj"), testprojDir.toPath()));
File testprojDir = gitClone(PROJECT_ID, 33871, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/pushFailsOnUnexpectedError/state/" + PROJECT_ID), testprojDir.toPath()));
runtime.exec("touch push.tex", null, testprojDir).waitFor();
gitAdd(testprojDir);
gitCommit(testprojDir, "push");
@ -576,9 +580,9 @@ public class WLGitBridgeIntegrationTest {
"remote:",
"remote: hint: You have 1 invalid files in your Overleaf project:",
"remote: hint: file1.exe (invalid file extension)",
"To http://127.0.0.1:33872/testproj.git",
"To http://127.0.0.1:33872/" + PROJECT_ID,
"! [remote rejected] master -> master (invalid files)",
"error: failed to push some refs to 'http://127.0.0.1:33872/testproj.git'"
"error: failed to push some refs to 'http://127.0.0.1:33872/" + PROJECT_ID + "'"
);
@Test
@ -590,10 +594,10 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(33872, 3872)
});
wlgb.run();
File testprojDir = gitClone("testproj", 33872, dir);
File testprojDir = gitClone(PROJECT_ID, 33872, dir);
// try to push invalid file; it should fail
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/pushSucceedsAfterRemovingInvalidFiles/invalidState/testproj"), testprojDir.toPath()));
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/pushSucceedsAfterRemovingInvalidFiles/invalidState/" + PROJECT_ID), testprojDir.toPath()));
assertEquals(0, runtime.exec("touch file1.exe", null, testprojDir).waitFor());
gitAdd(testprojDir);
gitCommit(testprojDir, "push");
@ -606,7 +610,7 @@ public class WLGitBridgeIntegrationTest {
gitCommit(testprojDir, "remove_invalid_file");
server.setState(states.get("pushSucceedsAfterRemovingInvalidFiles").get("validState"));
gitPush(testprojDir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/pushSucceedsAfterRemovingInvalidFiles/validState/testproj"), testprojDir.toPath()));
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/pushSucceedsAfterRemovingInvalidFiles/validState/" + PROJECT_ID), testprojDir.toPath()));
}
@Test
@ -629,8 +633,8 @@ public class WLGitBridgeIntegrationTest {
});
wlgb.run();
File testprojDir = gitClone("testproj", gitBridgePort, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canServePushedFiles/state/testproj"), testprojDir.toPath()));
File testprojDir = gitClone(PROJECT_ID, gitBridgePort, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canServePushedFiles/state/" + PROJECT_ID), testprojDir.toPath()));
runtime.exec("touch push.tex", null, testprojDir).waitFor();
gitAdd(testprojDir);
gitCommit(testprojDir, "push");
@ -677,17 +681,17 @@ public class WLGitBridgeIntegrationTest {
});
wlgb.run();
File rootGitDir = new File(wlgb.config.getRootGitDirectory());
File testProj1ServerDir = new File(rootGitDir, "testproj1");
File testProj2ServerDir = new File(rootGitDir, "testproj2");
File testProj1Dir = gitClone("testproj1", 33874, dir);
File testProj1ServerDir = new File(rootGitDir, PROJECT_ID1);
File testProj2ServerDir = new File(rootGitDir, PROJECT_ID2);
File testProj1Dir = gitClone(PROJECT_ID1, 33874, dir);
assertTrue(testProj1ServerDir.exists());
assertFalse(testProj2ServerDir.exists());
gitClone("testproj2", 33874, dir);
gitClone(PROJECT_ID2, 33874, dir);
while (testProj1ServerDir.exists());
assertFalse(testProj1ServerDir.exists());
assertTrue(testProj2ServerDir.exists());
FileUtils.deleteDirectory(testProj1Dir);
gitClone("testproj1", 33874, dir);
gitClone(PROJECT_ID1, 33874, dir);
while (testProj2ServerDir.exists());
assertTrue(testProj1ServerDir.exists());
assertFalse(testProj2ServerDir.exists());
@ -697,9 +701,9 @@ public class WLGitBridgeIntegrationTest {
"remote: hint: Your Git repository contains a reference we cannot resolve.",
"remote: hint: If your project contains a Git submodule,",
"remote: hint: please remove it and try again.",
"To http://127.0.0.1:33875/testproj.git",
"To http://127.0.0.1:33875/" + PROJECT_ID,
"! [remote rejected] master -> master (invalid git repo)",
"error: failed to push some refs to 'http://127.0.0.1:33875/testproj.git'"
"error: failed to push some refs to 'http://127.0.0.1:33875/" + PROJECT_ID + "'"
);
@Test
@ -711,7 +715,7 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(33875, 3875)
});
wlgb.run();
File testprojDir = gitClone("testproj", 33875, dir);
File testprojDir = gitClone(PROJECT_ID, 33875, dir);
runtime.exec("mkdir sub", null, testprojDir).waitFor();
File sub = new File(testprojDir, "sub");
runtime.exec("touch sub.txt", null, sub).waitFor();
@ -749,12 +753,12 @@ public class WLGitBridgeIntegrationTest {
assertEquals(404, response.getStatusCode());
assertEquals("{\"message\":\"HTTP error 404\"}", response.getResponseBody());
// With an unsupported URL outside the api, we should get a 500,
// which is rendered by our custom error handler.
// With an unsupported URL outside the api, the request is assumed to
// be from a git client and we should get a 401 because the request
// does not include basic auth credentials.
url = "http://127.0.0.1:" + gitBridgePort + "/foo";
response = asyncHttpClient().prepareGet(url).execute().get();
assertEquals(500, response.getStatusCode());
assertEquals("{\"message\":\"HTTP error 500\"}", response.getResponseBody());
assertEquals(401, response.getStatusCode());
}
@Test
@ -770,7 +774,7 @@ public class WLGitBridgeIntegrationTest {
});
wlgb.run();
Process gitProcess = runtime.exec("git clone http://127.0.0.1:" + gitBridgePort + "/testproj.git", null, dir);
Process gitProcess = runtime.exec("git clone http://git:password@127.0.0.1:" + gitBridgePort + "/" + PROJECT_ID, null, dir);
assertNotEquals(0, gitProcess.waitFor());
}
@ -787,7 +791,7 @@ public class WLGitBridgeIntegrationTest {
});
wlgb.run();
Process gitProcess = runtime.exec("git clone http://127.0.0.1:" + gitBridgePort + "/testproj.git", null, dir);
Process gitProcess = runtime.exec("git clone http://git:password@127.0.0.1:" + gitBridgePort + "/" + PROJECT_ID, null, dir);
assertNotEquals(0, gitProcess.waitFor());
}
@ -804,7 +808,7 @@ public class WLGitBridgeIntegrationTest {
});
wlgb.run();
Process gitProcess = runtime.exec("git clone http://127.0.0.1:" + gitBridgePort + "/testproj.git", null, dir);
Process gitProcess = runtime.exec("git clone http://git:password@127.0.0.1:" + gitBridgePort + "/" + PROJECT_ID, null, dir);
assertNotEquals(0, gitProcess.waitFor());
}
@ -819,10 +823,10 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(gitBridgePort, mockServerPort)
});
wlgb.run();
File testprojDir = gitClone("testproj", gitBridgePort, dir);
File testprojDir2 = gitClone("testproj2", gitBridgePort, dir);
File testprojDir = gitClone(PROJECT_ID, gitBridgePort, dir);
File testprojDir2 = gitClone(PROJECT_ID2, gitBridgePort, dir);
// Second project content is equal to content of the first
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canMigrateRepository/state/testproj"), testprojDir2.toPath()));
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canMigrateRepository/state/" + PROJECT_ID), testprojDir2.toPath()));
}
@Test
@ -837,8 +841,8 @@ public class WLGitBridgeIntegrationTest {
});
wlgb.run();
// don't clone the source project first
File testprojDir2 = gitClone("testproj2", gitBridgePort, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/skipMigrationWhenMigratedFromMissing/state/testproj2"), testprojDir2.toPath()));
File testprojDir2 = gitClone(PROJECT_ID2, gitBridgePort, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/skipMigrationWhenMigratedFromMissing/state/" + PROJECT_ID2), testprojDir2.toPath()));
}
@Test
@ -852,8 +856,8 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(gitBridgePort, mockServerPort)
});
wlgb.run();
File testprojDir = gitClone("testproj_no_change", gitBridgePort, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canCloneAMigratedRepositoryWithoutChanges/state/testproj_no_change"), testprojDir.toPath()));
File testprojDir = gitClone(PROJECT_ID, gitBridgePort, dir);
assertTrue(FileUtil.gitDirectoriesAreEqual(getResource("/canCloneAMigratedRepositoryWithoutChanges/state/" + PROJECT_ID), testprojDir.toPath()));
}
@Test
@ -867,7 +871,7 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(gitBridgePort, mockServerPort)
});
wlgb.run();
Process gitProcess = runtime.exec("git clone http://127.0.0.1:" + gitBridgePort + "/1234bbccddff.git", null, dir);
Process gitProcess = runtime.exec("git clone http://git:password@127.0.0.1:" + gitBridgePort + "/1234bbccddff.git", null, dir);
assertNotEquals(0, gitProcess.waitFor());
}
@ -884,7 +888,7 @@ public class WLGitBridgeIntegrationTest {
});
wlgb.run();
Process gitProcess = runtime.exec("git clone http://127.0.0.1:" + gitBridgePort + "/conflict.git", null, dir);
Process gitProcess = runtime.exec("git clone http://git:password@127.0.0.1:" + gitBridgePort + "/conflict.git", null, dir);
assertNotEquals(0, gitProcess.waitFor());
wlgb.stop();
}
@ -902,7 +906,7 @@ public class WLGitBridgeIntegrationTest {
});
wlgb.run();
Process gitProcess = runtime.exec("git clone http://127.0.0.1:" + gitBridgePort + "/project/1234abcd", null, dir);
Process gitProcess = runtime.exec("git clone http://git:password@127.0.0.1:" + gitBridgePort + "/project/1234abcd", null, dir);
assertNotEquals(0, gitProcess.waitFor());
List<String> actual = Util.linesFromStream(gitProcess.getErrorStream(), 0, "");
@ -996,7 +1000,7 @@ public class WLGitBridgeIntegrationTest {
});
wlgb.run();
HttpClient client = HttpClients.createDefault();
String urlBase = "http://127.0.0.1:" + gitBridgePort;
String urlBase = "http://git:password@127.0.0.1:" + gitBridgePort;
HttpPost gitLfsRequest = new HttpPost(urlBase+"/5f2419407929eb0026641967.git/info/lfs/objects/batch");
HttpResponse gitLfsResponse = client.execute(gitLfsRequest);
assertEquals(422, gitLfsResponse.getStatusLine().getStatusCode());
@ -1016,7 +1020,7 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(gitBridgePort, mockServerPort)
});
wlgb.run();
File testProjDir = gitClone("testproj", gitBridgePort, dir);
File testProjDir = gitClone(PROJECT_ID, gitBridgePort, dir);
File one = new File(testProjDir, "sub/one.txt");
one.createNewFile();
FileWriter fw = new FileWriter(one.getPath());
@ -1044,7 +1048,7 @@ public class WLGitBridgeIntegrationTest {
makeConfigFile(gitBridgePort, mockServerPort)
});
wlgb.run();
File testProjDir = gitClone("testproj", gitBridgePort, dir);
File testProjDir = gitClone(PROJECT_ID, gitBridgePort, dir);
server.setState(states.get("canPullIgnoredForceAddedFile").get("withUpdatedMainFile"));
gitPull(testProjDir);
File f = new File(testProjDir.getPath() + "/sub/one.txt");
@ -1084,7 +1088,7 @@ public class WLGitBridgeIntegrationTest {
" \"oauth2\": {\n" +
" \"oauth2ClientID\": \"clientID\",\n" +
" \"oauth2ClientSecret\": \"oauth2 client secret\",\n" +
" \"oauth2Server\": \"https://www.overleaf.com\"\n" +
" \"oauth2Server\": \"http://127.0.0.1:" + apiPort + "\"\n" +
" }";
if (swapCfg != null) {
cfgStr += ",\n" +

View file

@ -1,6 +1,6 @@
[
{
"project": "testproj_no_change",
"project": "000000000000000000000000",
"getDoc": {
"versionID": 0,
"createdAt": "2014-11-30T18:40:58.123Z",

View file

@ -1,6 +1,6 @@
[
{
"project": "testproj",
"project": "000000000000000000000000",
"getDoc": {
"versionID": 1,
"createdAt": "2014-11-30T18:40:58.123Z",
@ -31,7 +31,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:3857/state/testproj/min_mean_wait_evm_7_eps_150dpi.png",
"url": "http://127.0.0.1:3857/state/000000000000000000000000/min_mean_wait_evm_7_eps_150dpi.png",
"path": "min_mean_wait_evm_7_eps_150dpi.png"
}
]
@ -43,4 +43,4 @@
"versionID": 2
}
}
]
]

View file

@ -1,6 +1,6 @@
[
{
"project": "testproj",
"project": "000000000000000000000000",
"getDoc": {
"versionID": 1,
"createdAt": "2014-11-30T18:40:58.123Z",
@ -31,11 +31,11 @@
],
"atts": [
{
"url": "http://127.0.0.1:4002/state/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:4002/state/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410-copy.png"
},
{
"url": "http://127.0.0.1:4002/state/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:4002/state/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410.png"
}
]

View file

@ -1,6 +1,6 @@
[
{
"project": "testproj1",
"project": "111111111111111111111111",
"getDoc": {
"versionID": 1,
"createdAt": "2014-11-30T18:40:58.123Z",
@ -31,7 +31,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:3858/state/testproj1/overleaf-white-410.png",
"url": "http://127.0.0.1:3858/state/111111111111111111111111/overleaf-white-410.png",
"path": "overleaf-white-410.png"
}
]
@ -44,7 +44,7 @@
}
},
{
"project": "testproj2",
"project": "222222222222222222222222",
"getDoc": {
"versionID": 1,
"createdAt": "2014-11-30T18:40:58.123Z",
@ -75,7 +75,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:3858/state/testproj2/editor-versions-a7e4de19d015c3e7477e3f7eaa6c418e.png",
"url": "http://127.0.0.1:3858/state/222222222222222222222222/editor-versions-a7e4de19d015c3e7477e3f7eaa6c418e.png",
"path": "editor-versions-a7e4de19d015c3e7477e3f7eaa6c418e.png"
}
]
@ -87,4 +87,4 @@
"versionID": 2
}
}
]
]

View file

@ -1,12 +1,12 @@
[
{
"project": "testproj2",
"project": "222222222222222222222222",
"getDoc": {
"versionID": 1,
"createdAt": "2014-11-30T18:40:58.123Z",
"email": "jdleesmiller+1@gmail.com",
"name": "John+1",
"migratedFromId": "testproj"
"migratedFromId": "000000000000000000000000"
},
"getSavedVers": [],
"getForVers": [
@ -24,7 +24,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:3881/state/testproj/min_mean_wait_evm_7_eps_150dpi.png",
"url": "http://127.0.0.1:3881/state/000000000000000000000000/min_mean_wait_evm_7_eps_150dpi.png",
"path": "min_mean_wait_evm_7_eps_150dpi.png"
}
]
@ -37,7 +37,7 @@
}
},
{
"project": "testproj",
"project": "000000000000000000000000",
"getDoc": {
"versionID": 1,
"createdAt": "2014-11-30T18:40:58.123Z",
@ -68,7 +68,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:3881/state/testproj/min_mean_wait_evm_7_eps_150dpi.png",
"url": "http://127.0.0.1:3881/state/000000000000000000000000/min_mean_wait_evm_7_eps_150dpi.png",
"path": "min_mean_wait_evm_7_eps_150dpi.png"
}
]

View file

@ -1,6 +1,6 @@
[
{
"project": "testproj",
"project": "000000000000000000000000",
"getDoc": {
"versionID": 1,
"createdAt": "2014-11-30T18:40:58.123Z",
@ -31,7 +31,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:3863/base/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:3863/base/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410.png"
}
]
@ -43,4 +43,4 @@
"versionID": 2
}
}
]
]

View file

@ -1,6 +1,6 @@
[
{
"project": "testproj",
"project": "000000000000000000000000",
"getDoc": {
"versionID": 2,
"createdAt": "2014-11-30T18:40:58.123Z",
@ -53,7 +53,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:3863/base/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:3863/base/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410.png"
}
]
@ -65,4 +65,4 @@
"versionID": 2
}
}
]
]

View file

@ -1,6 +1,6 @@
[
{
"project": "testproj",
"project": "000000000000000000000000",
"getDoc": {
"versionID": 1,
"createdAt": "2014-11-30T18:40:58.123Z",
@ -31,7 +31,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:3860/base/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:3860/base/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410.png"
}
]
@ -43,4 +43,4 @@
"versionID": 2
}
}
]
]

View file

@ -1,6 +1,6 @@
[
{
"project": "testproj",
"project": "000000000000000000000000",
"getDoc": {
"versionID": 2,
"createdAt": "2014-11-30T18:40:58.123Z",
@ -34,7 +34,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:3860/withDeletedTexFile/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:3860/withDeletedTexFile/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410.png"
}
]
@ -53,7 +53,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:3860/base/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:3860/base/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410.png"
}
]
@ -65,4 +65,4 @@
"versionID": 2
}
}
]
]

View file

@ -1,6 +1,6 @@
[
{
"project": "testproj",
"project": "000000000000000000000000",
"getDoc": {
"versionID": 1,
"createdAt": "2014-11-30T18:40:58.123Z",
@ -31,7 +31,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:4001/base/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:4001/base/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410.png"
}
]
@ -43,4 +43,4 @@
"versionID": 2
}
}
]
]

View file

@ -1,6 +1,6 @@
[
{
"project": "testproj",
"project": "000000000000000000000000",
"getDoc": {
"versionID": 2,
"createdAt": "2014-11-30T18:40:58.123Z",
@ -38,11 +38,11 @@
],
"atts": [
{
"url": "http://127.0.0.1:4001/withDuplicateBinaryFile/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:4001/withDuplicateBinaryFile/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410.png"
},
{
"url": "http://127.0.0.1:4001/withDuplicateBinaryFile/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:4001/withDuplicateBinaryFile/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410-copy.png"
}
]
@ -61,7 +61,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:4001/withDuplicateBinaryFile/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:4001/withDuplicateBinaryFile/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410.png"
}
]
@ -73,4 +73,4 @@
"versionID": 2
}
}
]
]

View file

@ -1,6 +1,6 @@
[
{
"project": "testproj",
"project": "000000000000000000000000",
"getDoc": {
"versionID": 1,
"createdAt": "2014-11-30T18:40:58.123Z",
@ -31,7 +31,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:3862/base/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:3862/base/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410.png"
}
]
@ -43,4 +43,4 @@
"versionID": 2
}
}
]
]

View file

@ -1,6 +1,6 @@
[
{
"project": "testproj",
"project": "000000000000000000000000",
"getDoc": {
"versionID": 2,
"createdAt": "2014-11-30T18:40:58.123Z",
@ -38,7 +38,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:3862/withModifiedBinaryFile/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:3862/withModifiedBinaryFile/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410.png"
}
]
@ -57,7 +57,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:3862/base/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:3862/base/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410.png"
}
]
@ -69,4 +69,4 @@
"versionID": 2
}
}
]
]

View file

@ -1,6 +1,6 @@
[
{
"project": "testproj",
"project": "000000000000000000000000",
"getDoc": {
"versionID": 1,
"createdAt": "2014-11-30T18:40:58.123Z",
@ -31,7 +31,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:3864/base/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:3864/base/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410.png"
}
]
@ -43,4 +43,4 @@
"versionID": 2
}
}
]
]

View file

@ -1,6 +1,6 @@
[
{
"project": "testproj",
"project": "000000000000000000000000",
"getDoc": {
"versionID": 2,
"createdAt": "2014-11-30T18:40:58.123Z",
@ -46,7 +46,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:3864/withModifiedNestedFile/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:3864/withModifiedNestedFile/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410.png"
}
]
@ -65,7 +65,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:3864/base/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:3864/base/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410.png"
}
]
@ -77,4 +77,4 @@
"versionID": 2
}
}
]
]

View file

@ -1,6 +1,6 @@
[
{
"project": "testproj",
"project": "000000000000000000000000",
"getDoc": {
"versionID": 1,
"createdAt": "2014-11-30T18:40:58.123Z",
@ -31,7 +31,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:3859/base/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:3859/base/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410.png"
}
]
@ -43,4 +43,4 @@
"versionID": 2
}
}
]
]

View file

@ -1,6 +1,6 @@
[
{
"project": "testproj",
"project": "000000000000000000000000",
"getDoc": {
"versionID": 2,
"createdAt": "2014-11-30T18:40:58.123Z",
@ -38,7 +38,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:3859/withModifiedTexFile/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:3859/withModifiedTexFile/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410.png"
}
]
@ -57,7 +57,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:3859/base/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:3859/base/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410.png"
}
]
@ -69,4 +69,4 @@
"versionID": 2
}
}
]
]

View file

@ -1,6 +1,6 @@
[
{
"project": "testproj",
"project": "000000000000000000000000",
"getDoc": {
"versionID": 1,
"createdAt": "2014-11-30T18:40:58.123Z",
@ -39,7 +39,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:3865/base/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:3865/base/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410.png"
}
]
@ -51,4 +51,4 @@
"versionID": 2
}
}
]
]

View file

@ -1,6 +1,6 @@
[
{
"project": "testproj",
"project": "000000000000000000000000",
"getDoc": {
"versionID": 2,
"createdAt": "2014-11-30T18:40:58.123Z",
@ -38,7 +38,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:3865/withDeletedNestedFiles/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:3865/withDeletedNestedFiles/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410.png"
}
]
@ -65,7 +65,7 @@
],
"atts": [
{
"url": "http://127.0.0.1:3865/base/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:3865/base/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410.png"
}
]
@ -77,4 +77,4 @@
"versionID": 2
}
}
]
]

View file

@ -1,6 +1,6 @@
[
{
"project": "testproj",
"project": "000000000000000000000000",
"getDoc": {
"versionID": 1,
"createdAt": "2014-11-30T18:40:58.123Z",

View file

@ -1,6 +1,6 @@
[
{
"project": "testproj",
"project": "000000000000000000000000",
"getDoc": {
"versionID": 5,
"createdAt": "2014-11-30T18:40:58.123Z",

View file

@ -1,6 +1,6 @@
[
{
"project": "testproj",
"project": "000000000000000000000000",
"getDoc": {
"versionID": 1,
"createdAt": "2014-11-30T18:40:58.123Z",
@ -31,11 +31,11 @@
],
"atts": [
{
"url": "http://127.0.0.1:4003/base/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:4003/base/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410.png"
},
{
"url": "http://127.0.0.1:4003/base/testproj/overleaf-white-410.png",
"url": "http://127.0.0.1:4003/base/000000000000000000000000/overleaf-white-410.png",
"path": "overleaf-white-410-copy.png"
}
]
@ -47,4 +47,4 @@
"versionID": 2
}
}
]
]

Some files were not shown because too many files have changed in this diff Show more