-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[api] delete file #1122
base: main
Are you sure you want to change the base?
[api] delete file #1122
Conversation
b31bc38
to
446a1ff
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good job. I have only some minor comments
Great comments @kostas-kou ! Fixed most of them in 92903a6, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work! Especially on the tests, very extensive.
I don't have any significant remark on the PR.
353261a
to
3ac7e5e
Compare
@kostas-kou and @pahatz, thanks for your reviews! I have fixed the weird comment, rebased on main and also rebased to get rid of the fixup-commits. Only 3ac7e5e is new, the rest is the same as when you reviewed. |
...and added 8a745c4 for the rbac |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haven't tested, but it looks good. Tiny minor comments :-)
last_event=$(psql -U postgres -h postgres -d sda -At -c "SELECT event FROM sda.file_event_log WHERE file_id='$fileid' order by started_at desc limit 1;") | ||
|
||
if [ "$last_event" != "disabled" ]; then | ||
echo "The file $fileid does not have the expected las event 'disabled', but $last_event." | ||
fi |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe it is too much, but shouldn't the test check at this point that the file was deleted from the s3 bucket as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes... it shoud. Fixed in 109e7e2
sda/cmd/api/api.md
Outdated
- `/file/:username/*fileid` | ||
- accepts `DELETE` requests | ||
- marks the file as `disabled` in the database, and deletes it from the inbox. | ||
- The file is identfied by its id, returned by `users/:username/:files` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- The file is identfied by its id, returned by `users/:username/:files` | |
- The file is identified by its id, returned by `users/:username/:files` |
sda/cmd/api/api.go
Outdated
} | ||
|
||
submissionUser := c.Param("username") | ||
log.Warn("submission user:", submissionUser) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why log.Warn
and not log.Debug
or log.Info
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No reason 😬 ... Changed in 109e7e2
sda/cmd/api/api.go
Outdated
|
||
fileID := c.Param("file") | ||
fileID = strings.TrimPrefix(fileID, "/") | ||
log.Warn("submission file:", fileID) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why log.Warn
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No reason. Changed in 109e7e2
8a745c4
to
0f445c8
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
More specific comments are coming
0f445c8
to
109e7e2
Compare
109e7e2
to
d690e54
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is a few things here that we need to think more about.
- In FEGA the submitter can trigger ingestion of an uploaded file. That means we also needs to be able to remove a file both from the inbox and the archive during a cleaning operation. As well as the backup site if that is configured.
- The API can also be used by the submitter and that means we can't use the same functions or structs sometimes as that might leak things the submitter should not be able to see.
{ | ||
"role": "admin", | ||
"path": "/file/*", | ||
"action": "(DELETE)" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"action": "(DELETE)" | |
"action": "DELETE" |
Single action doesn't require parentheses
@@ -54,6 +56,10 @@ func main() { | |||
if err != nil { | |||
log.Fatal(err) | |||
} | |||
Conf.API.INBOX, err = storage.NewBackend(Conf.Inbox) | |||
if err != nil { | |||
log.Fatal(err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
log.Fatal
is the equivalent of doing log.Error
followed by os.Exit(1)
, something we shouldn't do when we have established connections to the MQ and DB.
The proper way is to have a shutdown function that will ensure that the external connections get's closed before the application closes
@@ -20,6 +20,11 @@ | |||
"path": "/file/accession", | |||
"action": "POST" | |||
}, | |||
{ | |||
"role": "admin", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"role": "admin", | |
"role": "submission", |
Removing files from the inbox is something the helpdesk should be able to do.
@@ -100,6 +106,7 @@ func setup(config *config.Config) *http.Server { | |||
r.POST("/c4gh-keys/add", rbac(e), addC4ghHash) // Adds a key hash to the database | |||
r.GET("/c4gh-keys/list", rbac(e), listC4ghHashes) // Lists key hashes in the database | |||
r.POST("/c4gh-keys/deprecate/*keyHash", rbac(e), deprecateC4ghHash) // Deprecate a given key hash | |||
r.DELETE("/file/:username/*file", rbac(e), deleteFile) // Delete a file from inbox |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The *file
here will catch a full path i.e. /path/to/file.c4gh
. If we want' that semantics we should probably call it filePath
.
If we not intend to use the file path but instead use the file id (to cope with BPs expected upload structure) the *file
should be :file
or :fileID
as we only expect a single value (no slashes).
filePath := "" | ||
// Get the file path from the fileID and submission user | ||
if filePath, err = Conf.API.DB.GetInboxFilePathFromID(submissionUser, fileID); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
filePath := "" | |
// Get the file path from the fileID and submission user | |
if filePath, err = Conf.API.DB.GetInboxFilePathFromID(submissionUser, fileID); err != nil { | |
// Get the file path from the fileID and submission user | |
filePath, err := Conf.API.DB.GetInboxFilePathFromID(submissionUser, fileID) | |
if err != nil { |
// The deleteFile function deletes files from the inbox and marks them as | ||
// discarded in the db. Files are identified by their ids and the user id. | ||
func deleteFile(c *gin.Context) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} | ||
|
||
// Requires a filepath instead of fileID | ||
// Note: The remove fails randomly sometimes |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// Note: The remove fails randomly sometimes |
File removal should never fail randomly.
If this is in the tests it's because of timing issues in the S3 backend (metadata not stored before deletion is initated).
exit 1 | ||
fi | ||
# delete it | ||
resp="$(curl -s -k -L -o /dev/null -w "%{http_code}\n" -H "Authorization: Bearer $token" -H "Content-Type: application/json" -X DELETE "http://api:8080/file/[email protected]/$fileid")" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
resp="$(curl -s -k -L -o /dev/null -w "%{http_code}\n" -H "Authorization: Bearer $token" -H "Content-Type: application/json" -X DELETE "http://api:8080/file/[email protected]/$fileid")" | |
resp="$(curl -s -k -L -o /dev/null -w "%{http_code}\n" -H "Authorization: Bearer $token" -X DELETE "http://api:8080/file/[email protected]/$fileid")" |
Content type header not needed since we are not sending any payload.
@@ -46,6 +46,7 @@ type SyncData struct { | |||
} | |||
|
|||
type SubmissionFileInfo struct { | |||
FileID string `json:"fileID"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This struct is also used when the submission user wants to list the files that have been uploaded and the FileID
is not something that the submitter needs to see.
"AND EXISTS (SELECT 1 FROM " + | ||
"(SELECT event from sda.file_event_log where file_id = $2 order by started_at desc limit 1) " + | ||
"as subquery WHERE event in ('registered', 'uploaded', 'submitted', 'ingested', 'error'))" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will be a bit iffy since in FEGA if the submission user adds a file to a run by mistake that file will be ingest, archived, backed up and given a stable ID (a case we actually will ned to be able to handle).
If we want to limit this to files that only have been uploaded to the inbox ingested
can not be a valid event since then the file will also be in the archive.
Instead we probably need to check if the file has had a state of ingested
, verified
, archived
or ready
and then also remove it from the archive. If the file has had the state backed up
we also need to remove the file from the backup site.
Related issue(s) and PR(s)
This PR closes #1134 .
Description
This PR adds the delete file functionality to the
api
component. Specifically, it deletes the file from the inbox and it adds a new file log event, setting the file status todisabled
.Also, it adds the
fileID
to thelist
functionality of theapi
, since that field is needed in order to delete a file:How to test
make build-all
thenPR_NUMBER=$(date +%F) docker compose -f .github/integration/sda-s3-integration.yml run integration_test
.List the files (eg with
http://localhost:8090/users/[email protected]/files
) and make sure files in the inbox can be deleted, and that archived files can not be deleted.