diff --git a/api/http.go b/api/http.go index 0a04dd7..148ad34 100644 --- a/api/http.go +++ b/api/http.go @@ -49,6 +49,7 @@ func NewHTTPServer(cfg *gpaste.ServerConfig) *HTTPServer { r.Get("/", srv.HandlerIndex) r.Post("/api/file", srv.HandlerAPIFilePost) r.Get("/api/file/{id}", srv.HandlerAPIFileGet) + r.Delete("/api/file/{id}", srv.HandlerAPIFileDelete) r.Post("/api/login", srv.HandlerAPILogin) r.Post("/api/user", srv.HandlerAPIUserCreate) srv.Handler = r @@ -117,6 +118,23 @@ func (s *HTTPServer) HandlerAPIFileGet(w http.ResponseWriter, r *http.Request) { } } +func (s *HTTPServer) HandlerAPIFileDelete(w http.ResponseWriter, r *http.Request) { + // TODO: Require auth + id := chi.URLParam(r, "id") + if id == "" { + w.WriteHeader(http.StatusBadRequest) + return + } + + err := s.Files.Delete(id) + if err != nil { + w.WriteHeader(http.StatusBadRequest) + return + } + reqID := middleware.GetReqID(r.Context()) + s.Logger.Infow("Deleted file", "id", id, "req_id", reqID) +} + func (s *HTTPServer) processMultiPartFormUpload(w http.ResponseWriter, r *http.Request) { reqID := middleware.GetReqID(r.Context()) diff --git a/api/http_test.go b/api/http_test.go index 6309384..13081e3 100644 --- a/api/http_test.go +++ b/api/http_test.go @@ -8,11 +8,15 @@ import ( "mime/multipart" "net/http" "net/http/httptest" + "strings" "testing" + "time" "git.t-juice.club/torjus/gpaste" "git.t-juice.club/torjus/gpaste/api" + "git.t-juice.club/torjus/gpaste/files" "git.t-juice.club/torjus/gpaste/users" + "github.com/google/uuid" ) func TestHandlers(t *testing.T) { @@ -99,6 +103,42 @@ func TestHandlers(t *testing.T) { } }) }) + t.Run("HandlerAPIFileDelete", func(t *testing.T) { + cfg := &gpaste.ServerConfig{ + SigningSecret: "abc123", + Store: &gpaste.ServerStoreConfig{ + Type: "memory", + }, + URL: "http://localhost:8080", + } + hs := api.NewHTTPServer(cfg) + fileBody := io.NopCloser(strings.NewReader("roflcopter")) + file := &files.File{ + ID: uuid.NewString(), + OriginalFilename: "testpls.txt", + MaxViews: 9, + ExpiresOn: time.Now().Add(10 * time.Hour), + Body: fileBody, + } + + if err := hs.Files.Store(file); err != nil { + t.Fatalf("Error storing file: %s", err) + } + + rr := httptest.NewRecorder() + url := fmt.Sprintf("/api/file/%s", file.ID) + req := httptest.NewRequest(http.MethodDelete, url, nil) + hs.Handler.ServeHTTP(rr, req) + + if rr.Result().StatusCode != http.StatusOK { + t.Fatalf("Delete returned wrong status: %s", rr.Result().Status) + } + + if _, err := hs.Files.Get(file.ID); err == nil { + t.Errorf("Getting after delete returned no error") + } + + }) t.Run("HandlerAPILogin", func(t *testing.T) { // TODO: Add test username := "admin" diff --git a/client/client.go b/client/client.go index f787d44..5e76ecc 100644 --- a/client/client.go +++ b/client/client.go @@ -203,3 +203,24 @@ func (c *Client) Upload(ctx context.Context, files ...*files.File) ([]api.Respon return expectedResp, nil } + +func (c *Client) Delete(ctx context.Context, id string) error { + url := fmt.Sprintf("%s/api/file/%s", c.BaseURL, id) + + req, err := http.NewRequestWithContext(ctx, http.MethodDelete, url, nil) + if err != nil { + return fmt.Errorf("error creating request: %w", err) + } + + req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.AuthToken)) + resp, err := c.httpClient.Do(req) + if err != nil { + return fmt.Errorf("unable to perform request: %s", err) + } + + if resp.StatusCode != http.StatusOK { + return fmt.Errorf("got non-ok response from server: %s", resp.Status) + } + + return nil +} diff --git a/cmd/client/actions/actions.go b/cmd/client/actions/actions.go index 3270a86..67c5095 100644 --- a/cmd/client/actions/actions.go +++ b/cmd/client/actions/actions.go @@ -39,6 +39,22 @@ func ActionUpload(c *cli.Context) error { return nil } +func ActionDelete(c *cli.Context) error { + clnt := client.Client{ + BaseURL: c.String("url"), + } + for _, arg := range c.Args().Slice() { + ctx, cancel := context.WithTimeout(c.Context, 5*time.Second) + defer cancel() + if err := clnt.Delete(ctx, arg); err != nil { + fmt.Printf("Error deleting file %s\n", arg) + fmt.Printf("%s\n", err) + } + fmt.Printf("Deleted %s\n", arg) + } + return nil +} + func ActionLogin(c *cli.Context) error { username := c.Args().First() if username == "" { diff --git a/cmd/client/client.go b/cmd/client/client.go index 3274bcc..35e62c1 100644 --- a/cmd/client/client.go +++ b/cmd/client/client.go @@ -37,6 +37,12 @@ func main() { ArgsUsage: "FILE [FILE]...", Action: actions.ActionUpload, }, + { + Name: "delete", + Usage: "Delete file(s)", + ArgsUsage: "FILE [FILE]...", + Action: actions.ActionDelete, + }, { Name: "login", Usage: "Login to gpaste server",