Merge pull request #12671 from overleaf/em-git-bridge-delete-project

Add endpoint to delete project data in git bridge

GitOrigin-RevId: bdc9701284255166bf4a122dad5fd89ced0c0ca2
This commit is contained in:
Eric Mc Sween 2023-04-24 10:39:45 -04:00 committed by Copybot
parent afd1195902
commit c539e960e7
9 changed files with 136 additions and 11 deletions

View file

@ -677,6 +677,20 @@ public class Bridge {
);
}
/**
* Delete a project's data
*/
public void deleteProject(String projectName) {
Log.info("[{}] deleting project", projectName);
dbStore.deleteProject(projectName);
try {
repoStore.remove(projectName);
} catch (IOException e) {
Log.warn("Failed to delete repository for project {}: {}", projectName, e);
}
swapStore.remove(projectName);
}
/* PRIVATE */
/**

View file

@ -41,4 +41,8 @@ public interface DBStore {
*/
void setLastAccessedTime(String projectName, Timestamp time);
/**
* Delete the metadata associated with the given project.
*/
void deleteProject(String projectName);
}

View file

@ -72,4 +72,7 @@ public class NoopDbStore implements DBStore {
public String getSwapCompression(String projectName) {
return null;
}
@Override
public void deleteProject(String projectName) {}
}

View file

@ -112,12 +112,12 @@ public class SqliteDBStore implements DBStore {
@Override
public void swap(String projectName, String compressionMethod) {
update(new UpdateSwap(projectName, compressionMethod));
update(new UpdateSwap(projectName, compressionMethod));
}
@Override
public void restore(String projectName) {
update(new UpdateRestore(projectName));
update(new UpdateRestore(projectName));
}
@Override
@ -125,6 +125,12 @@ public class SqliteDBStore implements DBStore {
return query(new GetSwapCompression(projectName));
}
@Override
public void deleteProject(String projectName) {
update(new DeleteAllFilesInProjectSQLUpdate(projectName));
update(new DeleteProjectSQLUpdate(projectName));
}
private Connection openConnectionTo(File dbFile) {
File parentDir = dbFile.getParentFile();
if (!parentDir.exists() && !parentDir.mkdirs()) {

View file

@ -0,0 +1,24 @@
package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.delete;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
public class DeleteAllFilesInProjectSQLUpdate implements SQLUpdate {
private final String projectName;
public DeleteAllFilesInProjectSQLUpdate(String projectName) {
this.projectName = projectName;
}
@Override
public String getSQL() {
return "DELETE FROM `url_index_store` WHERE `project_name` = ?";
}
@Override
public void addParametersToStatement(PreparedStatement statement) throws SQLException {
statement.setString(1, projectName);
}
}

View file

@ -0,0 +1,24 @@
package uk.ac.ic.wlgitbridge.bridge.db.sqlite.update.delete;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import uk.ac.ic.wlgitbridge.bridge.db.sqlite.SQLUpdate;
public class DeleteProjectSQLUpdate implements SQLUpdate {
private final String projectName;
public DeleteProjectSQLUpdate(String projectName) {
this.projectName = projectName;
}
@Override
public String getSQL() {
return "DELETE FROM `projects` WHERE `name` = ?";
}
@Override
public void addParametersToStatement(PreparedStatement statement) throws SQLException {
statement.setString(1, projectName);
}
}

View file

@ -148,6 +148,7 @@ public class GitBridgeServer {
HandlerCollection handlers = new HandlerList();
handlers.addHandler(initResourceHandler());
handlers.addHandler(new PostbackHandler(bridge));
handlers.addHandler(new ProjectDeletionHandler(bridge));
handlers.addHandler(new DefaultHandler());
api.setHandler(handlers);

View file

@ -0,0 +1,39 @@
package uk.ac.ic.wlgitbridge.server;
import java.io.IOException;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
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.bridge.Bridge;
public class ProjectDeletionHandler extends AbstractHandler {
private final Bridge bridge;
private final Pattern routePattern = Pattern.compile("^/projects/([0-9a-f]{24})$");
public ProjectDeletionHandler(Bridge bridge) {
this.bridge = bridge;
}
@Override
public void handle(
String target,
Request baseRequest,
HttpServletRequest request,
HttpServletResponse response
) throws IOException {
String method = baseRequest.getMethod();
Matcher matcher = routePattern.matcher(target);
if (method.equals("DELETE") && target != null && matcher.matches()) {
String projectName = matcher.group(1);
response.setContentType("text/plain");
response.setStatus(204);
this.bridge.deleteProject(projectName);
baseRequest.setHandled(true);
}
}
}

View file

@ -71,15 +71,15 @@ public class SqliteDBStoreTest {
@Test
public void swapAndRestore() {
String projectName = "something";
String compression = "bzip2";
dbStore.setLatestVersionForProject(projectName, 42);
dbStore.swap(projectName, compression);
assertNull(dbStore.getOldestUnswappedProject());
assertEquals(dbStore.getSwapCompression(projectName), compression);
// and restore
dbStore.restore(projectName);
assertEquals(dbStore.getSwapCompression(projectName), null);
String projectName = "something";
String compression = "bzip2";
dbStore.setLatestVersionForProject(projectName, 42);
dbStore.swap(projectName, compression);
assertNull(dbStore.getOldestUnswappedProject());
assertEquals(dbStore.getSwapCompression(projectName), compression);
// and restore
dbStore.restore(projectName);
assertEquals(dbStore.getSwapCompression(projectName), null);
}
@Test
@ -160,4 +160,14 @@ public class SqliteDBStoreTest {
assertEquals(ProjectState.SWAPPED, dbStore.getProjectState("asdf"));
}
@Test
public void testDeleteProject() {
dbStore.setLatestVersionForProject("project1", 1);
dbStore.setLatestVersionForProject("project2", 1);
assertEquals(ProjectState.PRESENT, dbStore.getProjectState("project1"));
assertEquals(ProjectState.PRESENT, dbStore.getProjectState("project2"));
dbStore.deleteProject("project1");
assertEquals(ProjectState.NOT_PRESENT, dbStore.getProjectState("project1"));
assertEquals(ProjectState.PRESENT, dbStore.getProjectState("project2"));
}
}