diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/Bridge.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/Bridge.java index 4faa53ebae..f01a9fb792 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/Bridge.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/Bridge.java @@ -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 */ /** diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/DBStore.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/DBStore.java index ff1e05ee0c..9b7f8eebd6 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/DBStore.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/DBStore.java @@ -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); } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/noop/NoopDbStore.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/noop/NoopDbStore.java index 0f0f9abb7c..15846f28a4 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/noop/NoopDbStore.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/noop/NoopDbStore.java @@ -72,4 +72,7 @@ public class NoopDbStore implements DBStore { public String getSwapCompression(String projectName) { return null; } + + @Override + public void deleteProject(String projectName) {} } diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/SqliteDBStore.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/SqliteDBStore.java index ec59313bae..1699915da9 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/SqliteDBStore.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/SqliteDBStore.java @@ -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()) { diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/delete/DeleteAllFilesInProjectSQLUpdate.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/delete/DeleteAllFilesInProjectSQLUpdate.java new file mode 100644 index 0000000000..dd6e15daed --- /dev/null +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/delete/DeleteAllFilesInProjectSQLUpdate.java @@ -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); + } +} diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/delete/DeleteProjectSQLUpdate.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/delete/DeleteProjectSQLUpdate.java new file mode 100644 index 0000000000..64153cf504 --- /dev/null +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/update/delete/DeleteProjectSQLUpdate.java @@ -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); + } +} diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/GitBridgeServer.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/GitBridgeServer.java index 312e3648b9..5e76f00128 100644 --- a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/GitBridgeServer.java +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/GitBridgeServer.java @@ -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); diff --git a/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/ProjectDeletionHandler.java b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/ProjectDeletionHandler.java new file mode 100644 index 0000000000..c47ecb6c61 --- /dev/null +++ b/services/git-bridge/src/main/java/uk/ac/ic/wlgitbridge/server/ProjectDeletionHandler.java @@ -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); + } + } +} diff --git a/services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/SqliteDBStoreTest.java b/services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/SqliteDBStoreTest.java index 9c88db88d8..faf30e390b 100644 --- a/services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/SqliteDBStoreTest.java +++ b/services/git-bridge/src/test/java/uk/ac/ic/wlgitbridge/bridge/db/sqlite/SqliteDBStoreTest.java @@ -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")); + } }