Skip to content

Commit

Permalink
Merge pull request #5 from openfort-xyz/feat/delete-share
Browse files Browse the repository at this point in the history
Feat/delete share
  • Loading branch information
gllm-dev authored Apr 11, 2024
2 parents 37a3a1c + c270a7c commit a2a3a5c
Show file tree
Hide file tree
Showing 7 changed files with 142 additions and 0 deletions.
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -285,3 +285,21 @@ OR
"entropy": "none"
}
```

#### 3. Delete Share
- **DELETE**: `https://shield.openfort.xyz/shares`
- **Request Headers**:
- `Authorization`: Bearer Token
- `x-auth-provider`: 'openfort' or 'custom'
- `x-openfort-provider`: 'firebase' // Optional: Only required if x-auth-provider is 'openfort' and using third-party authentication
- `x-openfort-token-type`: 'idToken' // Optional: Only required if x-auth-provider is 'openfort' and using third-party authentication
- `x-encryption-part`: 'myRhu0uoymTgFE567285c6gunZa8bRtgUBdOWxp96kg=' // Optional: Only required if the share have project entropy
- **Example Request**:
```shell
curl --location --request DELETE 'https://shield.openfort.xyz/shares' \
--header 'Authorization: Bearer •••••••' \
--header 'x-auth-provider: openfort' \
--header 'x-openfort-provider: firebase' \
--header 'x-openfort-token-type: idToken' \
--header 'x-api-key: d2d617ff-dbb6-480d-993f-dc8ac8307617'
```
19 changes: 19 additions & 0 deletions internal/applications/shareapp/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,25 @@ func (a *ShareApplication) GetShare(ctx context.Context, opts ...Option) (*share
return shr, nil
}

func (a *ShareApplication) DeleteShare(ctx context.Context) error {
a.logger.InfoContext(ctx, "deleting share")
usrID := contexter.GetUserID(ctx)

shr, err := a.shareRepo.GetByUserID(ctx, usrID)
if err != nil {
a.logger.ErrorContext(ctx, "failed to get share by user ID", logger.Error(err))
return fromDomainError(err)
}

err = a.shareRepo.Delete(ctx, shr.ID)
if err != nil {
a.logger.ErrorContext(ctx, "failed to delete share", logger.Error(err))
return fromDomainError(err)
}

return nil
}

func (a *ShareApplication) reconstructEncryptionKey(ctx context.Context, projID string, opt options) (string, error) {
if opt.encryptionPart == nil || *opt.encryptionPart == "" {
return "", ErrEncryptionPartRequired
Expand Down
59 changes: 59 additions & 0 deletions internal/applications/shareapp/app_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,3 +325,62 @@ func TestShareApplication_RegisterShare(t *testing.T) {
})
}
}

func TestShareApplication_DeleteShare(t *testing.T) {
ctx := contexter.WithProjectID(context.Background(), "project_id")
ctx = contexter.WithUserID(ctx, "user_id")
shareRepo := new(sharemockrepo.MockShareRepository)
projectRepo := new(projectmockrepo.MockProjectRepository)
shareSvc := sharesvc.New(shareRepo)
app := New(shareSvc, shareRepo, projectRepo)

tc := []struct {
name string
wantErr error
mock func()
}{
{
name: "success",
wantErr: nil,
mock: func() {
shareRepo.ExpectedCalls = nil
shareRepo.On("GetByUserID", mock.Anything, "user_id").Return(&share.Share{ID: "share-id"}, nil)
shareRepo.On("Delete", mock.Anything, mock.Anything).Return(nil)
},
},
{
name: "share not found",
wantErr: ErrShareNotFound,
mock: func() {
shareRepo.ExpectedCalls = nil
shareRepo.On("GetByUserID", mock.Anything, "user_id").Return(nil, domain.ErrShareNotFound)
},
},
{
name: "repository error",
wantErr: ErrInternal,
mock: func() {
shareRepo.ExpectedCalls = nil
shareRepo.On("GetByUserID", mock.Anything, "user_id").Return(nil, errors.New("repository error"))
},
},
{
name: "delete error",
wantErr: ErrInternal,
mock: func() {
shareRepo.ExpectedCalls = nil
shareRepo.On("GetByUserID", mock.Anything, "user_id").Return(&share.Share{ID: "share-id"}, nil)
shareRepo.On("Delete", mock.Anything, mock.Anything).Return(errors.New("repository error"))
},
},
}

for _, tt := range tc {
t.Run(tt.name, func(t *testing.T) {
tt.mock()
ass := assert.New(t)
err := app.DeleteShare(ctx)
ass.ErrorIs(tt.wantErr, err)
})
}
}
1 change: 1 addition & 0 deletions internal/core/ports/repositories/shares.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
type ShareRepository interface {
Create(ctx context.Context, shr *share.Share) error
GetByUserID(ctx context.Context, userID string) (*share.Share, error)
Delete(ctx context.Context, shareID string) error
ListDecryptedByProjectID(ctx context.Context, projectID string) ([]*share.Share, error)
UpdateProjectEncryption(ctx context.Context, shareID string, encrypted string) error
}
28 changes: 28 additions & 0 deletions internal/infrastructure/handlers/rest/sharehdl/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,34 @@ func (h *Handler) RegisterShare(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusCreated)
}

// DeleteShare deletes a share
// @Summary Delete share
// @Description Delete a share for the user
// @Tags Share
// @Accept json
// @Produce json
// @Param X-API-Key header string true "API Key"
// @Param Authorization header string true "Bearer token"
// @Param X-Auth-Provider header string true "Auth Provider"
// @Param X-Openfort-Provider header string false "Openfort Provider"
// @Param X-Openfort-Token-Type header string false "Openfort Token Type"
// @Success 204 "Description: Share deleted successfully"
// @Failure 404 "Description: Not Found"
// @Failure 500 "Description: Internal Server Error"
// @Router /shares [delete]
func (h *Handler) DeleteShare(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
h.logger.InfoContext(ctx, "deleting share")

err := h.app.DeleteShare(ctx)
if err != nil {
api.RespondWithError(w, fromApplicationError(err))
return
}

w.WriteHeader(http.StatusNoContent)
}

// GetShare gets a share
// @Summary Get share
// @Description Get a share for the user
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ func (m *MockShareRepository) GetByUserID(ctx context.Context, userID string) (*
return args.Get(0).(*share.Share), args.Error(1)
}

func (m *MockShareRepository) Delete(ctx context.Context, shareID string) error {
args := m.Mock.Called(ctx, shareID)
return args.Error(0)
}

func (m *MockShareRepository) ListDecryptedByProjectID(ctx context.Context, projectID string) ([]*share.Share, error) {
args := m.Mock.Called(ctx, projectID)
if args.Get(0) == nil {
Expand Down
12 changes: 12 additions & 0 deletions internal/infrastructure/repositories/sql/sharerepo/repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,18 @@ func (r *repository) GetByUserID(ctx context.Context, userID string) (*share.Sha
return r.parser.toDomain(dbShr), nil
}

func (r *repository) Delete(ctx context.Context, shareID string) error {
r.logger.InfoContext(ctx, "deleting share", slog.String("id", shareID))

err := r.db.Where("id = ?", shareID).Delete(&Share{}).Error
if err != nil {
r.logger.ErrorContext(ctx, "error deleting share", logger.Error(err))
return err
}

return nil
}

func (r *repository) ListDecryptedByProjectID(ctx context.Context, projectID string) ([]*share.Share, error) {
r.logger.InfoContext(ctx, "listing shares", slog.String("project_id", projectID))

Expand Down

0 comments on commit a2a3a5c

Please sign in to comment.