Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ It handles file uploads to a Google Cloud Storage (GCS) bucket.

## Features

- Receives files from the frontend and uploads them to a specified GCS bucket.
- Built with Go for performance and reliability.
- Dockerized for easy deployment.
- Uploading files to the cloud storage (GCS)
- Displaying metadata about stored and received objects
- Sharing files in the store via email or private/public links
- Previewing supported file types (image, video, audio, pdf)
- Adding notes attached to stored files

## Prerequisites

Expand Down
49 changes: 41 additions & 8 deletions internal/api/data_delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package api

import (
"database/sql"
"encoding/json"
"fmt"
"log"
"net/http"
Expand Down Expand Up @@ -70,20 +71,52 @@ func (s *APIServer) deleteAccount(w http.ResponseWriter, r *http.Request) {
pkg.WriteJSONResponse(w, http.StatusForbidden, "authorization_failed", nil)
return
}
bucketName := pkg.GetUserBucketName(s.bucketHandler.GetBucketBaseName(), authUserData.Id)

fullResponse := map[string]any{}
fullResponse["bucket"] = map[string]any{
"name": bucketName,
"deleted": false,
}

type DeleteAccountRequest struct {
DeleteUserData bool `json:"delete_user_data"`
}

var req DeleteAccountRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
pkg.WriteJSONResponse(w, http.StatusBadRequest, "bad_request", "")
return
}

if req.DeleteUserData {
if err := s.bucketHandler.DeleteBucket(ctx, bucketName); err != nil {
log.Printf("failed to delete bucket %s err: %s\n", bucketName, err)
fullResponse["bucket"] = map[string]any{
"name": bucketName,
"deleted": false,
}
}

fullResponse["bucket"] = map[string]any{
"name": bucketName,
"deleted": true,
}
}

deletedAccount, err := s.repository.Queries.DeleteAccount(ctx, authUserData.Id)
if err != nil {
log.Println("issues deleting object: ", err)
pkg.WriteJSONResponse(w, http.StatusInternalServerError, "authorization_failed", nil)
return
}
pkg.WriteJSONResponse(w, http.StatusOK, "success", map[string]any{
"account_deleted": map[string]any{
"id": deletedAccount.GoogleID,
"email": deletedAccount.UserEmail,
"user_name": deletedAccount.UserName.String,
},
})

fullResponse["account_deleted"] = map[string]any{
"id": deletedAccount.GoogleID,
"email": deletedAccount.UserEmail,
"user_name": deletedAccount.UserName.String,
}

pkg.WriteJSONResponse(w, http.StatusOK, "success", fullResponse)

}
49 changes: 49 additions & 0 deletions internal/cloud_storage/gcs/gcs_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -407,3 +407,52 @@ func (b *GCSBucketHandler) DeleteObjectFromBucket(ctx context.Context, object, b
log.Printf("object deleted successfully: (%s,%s)", o.BucketName(), o.ObjectName())
return nil
}

func (b *GCSBucketHandler) getAllObjectNames(ctx context.Context, bucket string) ([]string, error) {
ctx, cancel := context.WithTimeout(ctx, time.Second*10)
defer cancel()

objectNames := []string{}

it := b.Client.Bucket(bucket).Objects(ctx, nil)
for {
attrs, err := it.Next()

if err == iterator.Done {
break
}
if err != nil {
return objectNames, fmt.Errorf("Bucket(%q).Objects: %w", bucket, err)
}
objectNames = append(objectNames, attrs.Name)
}

return objectNames, nil
}

func (b *GCSBucketHandler) DeleteBucket(ctx context.Context, bucket string) error {
ctx, cancel := context.WithTimeout(ctx, time.Minute*1)
defer cancel()

objectsInBucket, err := b.getAllObjectNames(ctx, bucket)
if err != nil {
log.Println("failed_fetching_bucket_info, err: ", err)
}

gcsBucket := b.Client.Bucket(bucket)
for _, o := range objectsInBucket {
object := gcsBucket.Object(o)
if err := object.Delete(ctx); err != nil {
log.Printf("failed deleting object %s, err: %s\n", o, err)
}
log.Printf("deleted object %s", o)
}

if err := gcsBucket.Delete(ctx); err != nil {
log.Println(err)
return fmt.Errorf("failed_deleting_bucket")
}

log.Printf("deleted bucket: %s\n", bucket)
return nil
}
1 change: 1 addition & 0 deletions internal/cloud_storage/types/object.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ type ObjectStorage interface {
GetBucketBaseName() string
GenerateSignedURL(ctx context.Context, bucket, object string, expiresAt time.Time) (string, error)
DeleteObjectFromBucket(ctx context.Context, object, bucket string) error
DeleteBucket(ctx context.Context, bucket string) error
Close() error
}