From 6e3cbb9712972aa41e75857be2d7a431daa504b3 Mon Sep 17 00:00:00 2001 From: Yehor Butko Date: Fri, 11 Jan 2019 12:08:51 +0200 Subject: [PATCH] V3-978 Create missing unit tests for satellitedb (#1025) * V3-978 Create missing unit tests for satellitedb * fixing linter * removing redundant checks from tests --- pkg/satellite/apikeys.go | 4 +- pkg/satellite/satelliteauth/claims_test.go | 42 ++++++ pkg/satellite/satelliteauth/token_test.go | 26 ++++ pkg/satellite/satellitedb/apikeys_test.go | 121 ++++++++++++++++++ pkg/satellite/satellitedb/db_test.go | 82 ++++++++++++ .../satellitedb/projectmembers_test.go | 43 ++++--- pkg/satellite/satellitedb/projects_test.go | 34 ++--- pkg/satellite/satellitedb/users_test.go | 26 +--- pkg/satellite/satellitedb/utils_test.go | 3 - pkg/satellite/service.go | 2 +- web/satellite/src/api/projects.ts | 4 +- 11 files changed, 311 insertions(+), 76 deletions(-) create mode 100644 pkg/satellite/satelliteauth/claims_test.go create mode 100644 pkg/satellite/satelliteauth/token_test.go create mode 100644 pkg/satellite/satellitedb/apikeys_test.go create mode 100644 pkg/satellite/satellitedb/db_test.go diff --git a/pkg/satellite/apikeys.go b/pkg/satellite/apikeys.go index f8242a09d..54820d8b8 100644 --- a/pkg/satellite/apikeys.go +++ b/pkg/satellite/apikeys.go @@ -61,8 +61,8 @@ func APIKeyFromBytes(b []byte) *APIKey { return key } -// createAPIKey creates new api key -func createAPIKey() (*APIKey, error) { +// CreateAPIKey creates new api key +func CreateAPIKey() (*APIKey, error) { key := new(APIKey) n, err := io.ReadFull(rand.Reader, key[:]) diff --git a/pkg/satellite/satelliteauth/claims_test.go b/pkg/satellite/satelliteauth/claims_test.go new file mode 100644 index 000000000..b56923901 --- /dev/null +++ b/pkg/satellite/satelliteauth/claims_test.go @@ -0,0 +1,42 @@ +// Copyright (C) 2018 Storj Labs, Inc. +// See LICENSE for copying information. + +package satelliteauth + +import ( + "testing" + "time" + + "github.com/skyrings/skyring-common/tools/uuid" + "github.com/stretchr/testify/assert" +) + +func TestClaims(t *testing.T) { + id, err := uuid.New() + assert.Nil(t, err) + assert.NoError(t, err) + assert.NotNil(t, id) + + claims := Claims{ + ID: *id, + Email: "someEmail@ukr.net", + Expiration: time.Now(), + } + + claimsBytes, err := claims.JSON() + assert.NoError(t, err) + assert.NotNil(t, claimsBytes) + + parsedClaims, err := FromJSON(claimsBytes) + assert.NoError(t, err) + assert.NotNil(t, parsedClaims) + + assert.Equal(t, parsedClaims.Email, claims.Email) + assert.Equal(t, parsedClaims.ID, claims.ID) + assert.Equal(t, parsedClaims.Expiration.Year(), claims.Expiration.Year()) + assert.Equal(t, parsedClaims.Expiration.Month(), claims.Expiration.Month()) + assert.Equal(t, parsedClaims.Expiration.Day(), claims.Expiration.Day()) + assert.Equal(t, parsedClaims.Expiration.Hour(), claims.Expiration.Hour()) + assert.Equal(t, parsedClaims.Expiration.Minute(), claims.Expiration.Minute()) + assert.Equal(t, parsedClaims.Expiration.Second(), claims.Expiration.Second()) +} diff --git a/pkg/satellite/satelliteauth/token_test.go b/pkg/satellite/satelliteauth/token_test.go new file mode 100644 index 000000000..053299047 --- /dev/null +++ b/pkg/satellite/satelliteauth/token_test.go @@ -0,0 +1,26 @@ +// Copyright (C) 2018 Storj Labs, Inc. +// See LICENSE for copying information. + +package satelliteauth + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestToken(t *testing.T) { + token := Token{ + Payload: []byte{1, 2, 3}, + Signature: []byte{4, 5, 6}, + } + + tokenString := token.String() + assert.NotNil(t, tokenString) + assert.Equal(t, len(tokenString) > 0, true) + + tokenFromString, err := FromBase64URLString(tokenString) + assert.NoError(t, err) + assert.Equal(t, tokenFromString.Payload, token.Payload) + assert.Equal(t, tokenFromString.Signature, token.Signature) +} diff --git a/pkg/satellite/satellitedb/apikeys_test.go b/pkg/satellite/satellitedb/apikeys_test.go new file mode 100644 index 000000000..bcd7aa4ba --- /dev/null +++ b/pkg/satellite/satellitedb/apikeys_test.go @@ -0,0 +1,121 @@ +// Copyright (C) 2018 Storj Labs, Inc. +// See LICENSE for copying information. + +package satellitedb + +import ( + "fmt" + "testing" + + "github.com/stretchr/testify/assert" + "storj.io/storj/internal/testcontext" + "storj.io/storj/pkg/satellite" +) + +func TestApiKeysRepository(t *testing.T) { + ctx := testcontext.New(t) + defer ctx.Cleanup() + + // creating in-memory db and opening connection + db, err := New("sqlite3", "file::memory:?mode=memory&cache=shared") + if err != nil { + t.Fatal(err) + } + defer ctx.Check(db.Close) + + // creating tables + err = db.CreateTables() + if err != nil { + t.Fatal(err) + } + + projects := db.Projects() + apikeys := db.APIKeys() + + project, err := projects.Insert(ctx, &satellite.Project{ + Name: "ProjectName", + TermsAccepted: 1, + Description: "projects description", + }) + assert.NotNil(t, project) + assert.NoError(t, err) + + t.Run("Creation success", func(t *testing.T) { + for i := 0; i < 10; i++ { + key, err := satellite.CreateAPIKey() + assert.NoError(t, err) + + keyInfo := satellite.APIKeyInfo{ + Name: fmt.Sprintf("key %d", i), + ProjectID: project.ID, + } + + createdKey, err := apikeys.Create(ctx, *key, keyInfo) + assert.NotNil(t, createdKey) + assert.NoError(t, err) + } + }) + + t.Run("GetByProjectID success", func(t *testing.T) { + keys, err := apikeys.GetByProjectID(ctx, project.ID) + assert.NotNil(t, keys) + assert.Equal(t, len(keys), 10) + assert.NoError(t, err) + }) + + t.Run("Get By ID success", func(t *testing.T) { + keys, err := apikeys.GetByProjectID(ctx, project.ID) + assert.NotNil(t, keys) + assert.Equal(t, len(keys), 10) + assert.NoError(t, err) + + key, err := apikeys.Get(ctx, keys[0].ID) + assert.NotNil(t, key) + assert.Equal(t, keys[0].ID, key.ID) + assert.NoError(t, err) + }) + + t.Run("Update success", func(t *testing.T) { + keys, err := apikeys.GetByProjectID(ctx, project.ID) + assert.NotNil(t, keys) + assert.Equal(t, len(keys), 10) + assert.NoError(t, err) + + key, err := apikeys.Get(ctx, keys[0].ID) + assert.NotNil(t, key) + assert.Equal(t, keys[0].ID, key.ID) + assert.NoError(t, err) + + key.Name = "some new name" + + err = apikeys.Update(ctx, *key) + assert.NoError(t, err) + + updatedKey, err := apikeys.Get(ctx, keys[0].ID) + assert.NotNil(t, key) + assert.Equal(t, key.Name, updatedKey.Name) + assert.NoError(t, err) + }) + + t.Run("Delete success", func(t *testing.T) { + keys, err := apikeys.GetByProjectID(ctx, project.ID) + assert.NotNil(t, keys) + assert.Equal(t, len(keys), 10) + assert.NoError(t, err) + + key, err := apikeys.Get(ctx, keys[0].ID) + assert.NotNil(t, key) + assert.Equal(t, keys[0].ID, key.ID) + assert.NoError(t, err) + + key.Name = "some new name" + + err = apikeys.Delete(ctx, key.ID) + assert.NoError(t, err) + + keys, err = apikeys.GetByProjectID(ctx, project.ID) + assert.NotNil(t, keys) + assert.Equal(t, len(keys), 9) + assert.NoError(t, err) + }) +} diff --git a/pkg/satellite/satellitedb/db_test.go b/pkg/satellite/satellitedb/db_test.go new file mode 100644 index 000000000..bf75c5bae --- /dev/null +++ b/pkg/satellite/satellitedb/db_test.go @@ -0,0 +1,82 @@ +// Copyright (C) 2018 Storj Labs, Inc. +// See LICENSE for copying information. + +package satellitedb + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "storj.io/storj/internal/testcontext" +) + +func TestDatabase(t *testing.T) { + ctx := testcontext.New(t) + defer ctx.Cleanup() + + t.Run("BeginTx return err when db is nil", func(t *testing.T) { + db := &Database{ + db: nil, + } + + transaction, err := db.BeginTx(ctx) + assert.Error(t, err) + assert.Nil(t, transaction) + }) + + t.Run("BeginTx and Commit success", func(t *testing.T) { + db, err := New("sqlite3", "file::memory:?mode=memory&cache=shared") + if err != nil { + t.Fatal(err) + } + + transaction, err := db.BeginTx(ctx) + assert.NoError(t, err) + assert.NotNil(t, transaction) + + err = transaction.Commit() + assert.NoError(t, err) + + err = db.Close() + assert.NoError(t, err) + }) + + t.Run("BeginTx and Rollback success", func(t *testing.T) { + db, err := New("sqlite3", "file::memory:?mode=memory&cache=shared") + if err != nil { + t.Fatal(err) + } + + transaction, err := db.BeginTx(ctx) + assert.NoError(t, err) + assert.NotNil(t, transaction) + + err = transaction.Rollback() + assert.NoError(t, err) + + err = db.Close() + assert.NoError(t, err) + }) + + t.Run("Commit fails", func(t *testing.T) { + transaction := &DBTx{ + Database: &Database{ + tx: nil, + }, + } + + err := transaction.Commit() + assert.Error(t, err) + }) + + t.Run("Rollback fails", func(t *testing.T) { + transaction := &DBTx{ + Database: &Database{ + tx: nil, + }, + } + + err := transaction.Rollback() + assert.Error(t, err) + }) +} diff --git a/pkg/satellite/satellitedb/projectmembers_test.go b/pkg/satellite/satellitedb/projectmembers_test.go index ecc18ef23..42b9c995f 100644 --- a/pkg/satellite/satellitedb/projectmembers_test.go +++ b/pkg/satellite/satellitedb/projectmembers_test.go @@ -44,7 +44,6 @@ func TestProjectMembersRepository(t *testing.T) { projMember, err := projectMembers.Insert(ctx, *unexistingUserID, createdProjects[0].ID) assert.Nil(t, projMember) - assert.NotNil(t, err) assert.Error(t, err) }) @@ -54,82 +53,79 @@ func TestProjectMembersRepository(t *testing.T) { projMember, err := projectMembers.Insert(ctx, createdUsers[0].ID, *unexistingProjectID) assert.Nil(t, projMember) - assert.NotNil(t, err) assert.Error(t, err) }) t.Run("Insert success", func(t *testing.T) { projMember1, err := projectMembers.Insert(ctx, createdUsers[0].ID, createdProjects[0].ID) assert.NotNil(t, projMember1) - assert.Nil(t, err) assert.NoError(t, err) projMember2, err := projectMembers.Insert(ctx, createdUsers[1].ID, createdProjects[0].ID) assert.NotNil(t, projMember2) - assert.Nil(t, err) assert.NoError(t, err) projMember3, err := projectMembers.Insert(ctx, createdUsers[3].ID, createdProjects[0].ID) assert.NotNil(t, projMember3) - assert.Nil(t, err) assert.NoError(t, err) projMember4, err := projectMembers.Insert(ctx, createdUsers[4].ID, createdProjects[0].ID) assert.NotNil(t, projMember4) - assert.Nil(t, err) assert.NoError(t, err) projMember5, err := projectMembers.Insert(ctx, createdUsers[5].ID, createdProjects[0].ID) assert.NotNil(t, projMember5) - assert.Nil(t, err) assert.NoError(t, err) projMember6, err := projectMembers.Insert(ctx, createdUsers[2].ID, createdProjects[1].ID) assert.NotNil(t, projMember6) - assert.Nil(t, err) assert.NoError(t, err) + + projMember7, err := projectMembers.Insert(ctx, createdUsers[0].ID, createdProjects[1].ID) + assert.NotNil(t, projMember7) + assert.NoError(t, err) + }) + + t.Run("Get projects by userID", func(t *testing.T) { + projects, err := projects.GetByUserID(ctx, createdUsers[0].ID) + assert.NoError(t, err) + assert.NotNil(t, projects) + assert.Equal(t, len(projects), 2) }) t.Run("Get paged", func(t *testing.T) { // sql injection test. F.E '%SomeText%' = > ''%SomeText%' OR 'x' != '%'' will be true members, err := projectMembers.GetByProjectID(ctx, createdProjects[0].ID, satellite.Pagination{Limit: 6, Offset: 0, Search: "son%' OR 'x' != '", Order: 2}) - assert.Nil(t, err) assert.NoError(t, err) assert.Nil(t, members) assert.Equal(t, 0, len(members)) members, err = projectMembers.GetByProjectID(ctx, createdProjects[0].ID, satellite.Pagination{Limit: 3, Offset: 0, Search: "", Order: 1}) - assert.Nil(t, err) assert.NoError(t, err) assert.NotNil(t, members) assert.Equal(t, 3, len(members)) members, err = projectMembers.GetByProjectID(ctx, createdProjects[0].ID, satellite.Pagination{Limit: 2, Offset: 0, Search: "Liam", Order: 2}) - assert.Nil(t, err) assert.NoError(t, err) assert.NotNil(t, members) assert.Equal(t, 2, len(members)) members, err = projectMembers.GetByProjectID(ctx, createdProjects[0].ID, satellite.Pagination{Limit: 2, Offset: 0, Search: "Liam", Order: 1}) - assert.Nil(t, err) assert.NoError(t, err) assert.NotNil(t, members) assert.Equal(t, 2, len(members)) members, err = projectMembers.GetByProjectID(ctx, createdProjects[0].ID, satellite.Pagination{Limit: 6, Offset: 0, Search: "son", Order: 123}) - assert.Nil(t, err) assert.NoError(t, err) assert.NotNil(t, members) assert.Equal(t, 5, len(members)) members, err = projectMembers.GetByProjectID(ctx, createdProjects[0].ID, satellite.Pagination{Limit: 6, Offset: 3, Search: "son", Order: 2}) - assert.Nil(t, err) assert.NoError(t, err) assert.NotNil(t, members) assert.Equal(t, 2, len(members)) members, err = projectMembers.GetByProjectID(ctx, createdProjects[0].ID, satellite.Pagination{Limit: -123, Offset: -14, Search: "son", Order: 2}) - assert.NotNil(t, err) assert.Error(t, err) assert.Nil(t, members) assert.Equal(t, 0, len(members)) @@ -140,7 +136,6 @@ func TestProjectMembersRepository(t *testing.T) { selectedMembers1, err := projectMembers.GetByMemberID(ctx, originalMember1.ID) assert.NotNil(t, selectedMembers1) - assert.Nil(t, err) assert.NoError(t, err) assert.Equal(t, originalMember1.ID, selectedMembers1[0].MemberID) @@ -148,10 +143,24 @@ func TestProjectMembersRepository(t *testing.T) { selectedMembers2, err := projectMembers.GetByMemberID(ctx, originalMember2.ID) assert.NotNil(t, selectedMembers2) - assert.Nil(t, err) assert.NoError(t, err) assert.Equal(t, originalMember2.ID, selectedMembers2[0].MemberID) }) + + t.Run("Delete member by memberID and projectID success", func(t *testing.T) { + err := projectMembers.Delete(ctx, createdUsers[0].ID, createdProjects[0].ID) + assert.NoError(t, err) + + projMembers, err := projectMembers.GetByProjectID(ctx, createdProjects[0].ID, satellite.Pagination{ + Order: 1, + Search: "", + Offset: 0, + Limit: 100, + }) + assert.NoError(t, err) + assert.NotNil(t, projectMembers) + assert.Equal(t, len(projMembers), 4) + }) } func prepareUsersAndProjects(ctx context.Context, t *testing.T, users satellite.Users, projects satellite.Projects) ([]*satellite.User, []*satellite.Project) { diff --git a/pkg/satellite/satellitedb/projects_test.go b/pkg/satellite/satellitedb/projects_test.go index da7eef882..fad4df9e1 100644 --- a/pkg/satellite/satellitedb/projects_test.go +++ b/pkg/satellite/satellitedb/projects_test.go @@ -60,7 +60,6 @@ func TestProjectsRepository(t *testing.T) { Email: email, PasswordHash: []byte(pass), }) - assert.NoError(t, err) assert.NotNil(t, owner) @@ -71,19 +70,22 @@ func TestProjectsRepository(t *testing.T) { } project, err = projects.Insert(ctx, project) - assert.NotNil(t, project) - assert.Nil(t, err) assert.NoError(t, err) }) t.Run("Get project success", func(t *testing.T) { - projectByID, err := projects.Get(ctx, project.ID) - - assert.Nil(t, err) assert.NoError(t, err) + assert.Equal(t, projectByID.ID, project.ID) + assert.Equal(t, projectByID.Name, name) + assert.Equal(t, projectByID.Description, description) + assert.Equal(t, projectByID.TermsAccepted, 1) + }) + t.Run("Get by projectID success", func(t *testing.T) { + projectByID, err := projects.Get(ctx, project.ID) + assert.NoError(t, err) assert.Equal(t, projectByID.ID, project.ID) assert.Equal(t, projectByID.Name, name) assert.Equal(t, projectByID.Description, description) @@ -92,7 +94,6 @@ func TestProjectsRepository(t *testing.T) { t.Run("Update project success", func(t *testing.T) { oldProject, err := projects.Get(ctx, project.ID) - assert.NoError(t, err) assert.NotNil(t, oldProject) @@ -104,15 +105,11 @@ func TestProjectsRepository(t *testing.T) { } err = projects.Update(ctx, newProject) - - assert.Nil(t, err) assert.NoError(t, err) // fetching updated project from db newProject, err = projects.Get(ctx, oldProject.ID) - assert.NoError(t, err) - assert.Equal(t, newProject.ID, oldProject.ID) assert.Equal(t, newProject.Description, newDescription) assert.Equal(t, newProject.TermsAccepted, 2) @@ -120,25 +117,18 @@ func TestProjectsRepository(t *testing.T) { t.Run("Delete project success", func(t *testing.T) { oldProject, err := projects.Get(ctx, project.ID) - assert.NoError(t, err) assert.NotNil(t, oldProject) err = projects.Delete(ctx, oldProject.ID) - - assert.Nil(t, err) assert.NoError(t, err) _, err = projects.Get(ctx, oldProject.ID) - - assert.NotNil(t, err) assert.Error(t, err) }) t.Run("GetAll success", func(t *testing.T) { allProjects, err := projects.GetAll(ctx) - - assert.Nil(t, err) assert.NoError(t, err) assert.Equal(t, len(allProjects), 0) @@ -149,13 +139,9 @@ func TestProjectsRepository(t *testing.T) { } _, err = projects.Insert(ctx, newProject) - - assert.Nil(t, err) assert.NoError(t, err) allProjects, err = projects.GetAll(ctx) - - assert.Nil(t, err) assert.NoError(t, err) assert.Equal(t, len(allProjects), 1) @@ -166,13 +152,9 @@ func TestProjectsRepository(t *testing.T) { } _, err = projects.Insert(ctx, newProject2) - - assert.Nil(t, err) assert.NoError(t, err) allProjects, err = projects.GetAll(ctx) - - assert.Nil(t, err) assert.NoError(t, err) assert.Equal(t, len(allProjects), 2) }) diff --git a/pkg/satellite/satellitedb/users_test.go b/pkg/satellite/satellitedb/users_test.go index bc1c3d28a..1ee18d26d 100644 --- a/pkg/satellite/satellitedb/users_test.go +++ b/pkg/satellite/satellitedb/users_test.go @@ -49,10 +49,7 @@ func TestUserRepository(t *testing.T) { t.Run("User insertion success", func(t *testing.T) { id, err := uuid.New() - - if err != nil { - assert.NoError(t, err) - } + assert.NoError(t, err) user := &satellite.User{ ID: *id, @@ -64,8 +61,6 @@ func TestUserRepository(t *testing.T) { } _, err = repository.Insert(ctx, user) - - assert.Nil(t, err) assert.NoError(t, err) }) @@ -79,24 +74,18 @@ func TestUserRepository(t *testing.T) { } _, err = repository.Insert(ctx, user) - - assert.NotNil(t, err) assert.Error(t, err) }) t.Run("Get user success", func(t *testing.T) { userByEmail, err := repository.GetByEmail(ctx, email) - assert.Equal(t, userByEmail.FirstName, name) assert.Equal(t, userByEmail.LastName, lastName) - assert.Nil(t, err) assert.NoError(t, err) userByID, err := repository.Get(ctx, userByEmail.ID) - assert.Equal(t, userByID.FirstName, name) assert.Equal(t, userByID.LastName, lastName) - assert.Nil(t, err) assert.NoError(t, err) assert.Equal(t, userByID.ID, userByEmail.ID) @@ -109,7 +98,6 @@ func TestUserRepository(t *testing.T) { t.Run("Update user success", func(t *testing.T) { oldUser, err := repository.GetByEmail(ctx, email) - assert.NoError(t, err) newUser := &satellite.User{ @@ -121,14 +109,10 @@ func TestUserRepository(t *testing.T) { } err = repository.Update(ctx, newUser) - - assert.Nil(t, err) assert.NoError(t, err) newUser, err = repository.Get(ctx, oldUser.ID) - assert.NoError(t, err) - assert.Equal(t, newUser.ID, oldUser.ID) assert.Equal(t, newUser.FirstName, newName) assert.Equal(t, newUser.LastName, newLastName) @@ -139,17 +123,12 @@ func TestUserRepository(t *testing.T) { t.Run("Delete user success", func(t *testing.T) { oldUser, err := repository.GetByEmail(ctx, newEmail) - assert.NoError(t, err) err = repository.Delete(ctx, oldUser.ID) - - assert.Nil(t, err) assert.NoError(t, err) _, err = repository.Get(ctx, oldUser.ID) - - assert.NotNil(t, err) assert.Error(t, err) }) } @@ -157,9 +136,7 @@ func TestUserRepository(t *testing.T) { func TestUserFromDbx(t *testing.T) { t.Run("can't create dbo from nil dbx model", func(t *testing.T) { user, err := userFromDBX(nil) - assert.Nil(t, user) - assert.NotNil(t, err) assert.Error(t, err) }) @@ -176,7 +153,6 @@ func TestUserFromDbx(t *testing.T) { user, err := userFromDBX(&dbxUser) assert.Nil(t, user) - assert.NotNil(t, err) assert.Error(t, err) }) } diff --git a/pkg/satellite/satellitedb/utils_test.go b/pkg/satellite/satellitedb/utils_test.go index 801755c4d..d948221aa 100644 --- a/pkg/satellite/satellitedb/utils_test.go +++ b/pkg/satellite/satellitedb/utils_test.go @@ -26,10 +26,7 @@ func TestBytesToUUID(t *testing.T) { assert.NoError(t, err) result, err := bytesToUUID(id[:]) - - assert.Nil(t, err) assert.NoError(t, err) - assert.Equal(t, result, *id) }) } diff --git a/pkg/satellite/service.go b/pkg/satellite/service.go index 37b26ae3e..d9a91aa08 100644 --- a/pkg/satellite/service.go +++ b/pkg/satellite/service.go @@ -431,7 +431,7 @@ func (s *Service) CreateAPIKey(ctx context.Context, projectID uuid.UUID, name st return nil, nil, ErrUnauthorized.Wrap(err) } - key, err := createAPIKey() + key, err := CreateAPIKey() if err != nil { return nil, nil, err } diff --git a/web/satellite/src/api/projects.ts b/web/satellite/src/api/projects.ts index 4b2048b15..d38ff41c0 100644 --- a/web/satellite/src/api/projects.ts +++ b/web/satellite/src/api/projects.ts @@ -97,7 +97,7 @@ export async function updateProjectRequest(projectID: string, description: strin updateProjectDescription( id: "${projectID}", description: "${description}" - ) + ) {name} }` ), fetchPolicy: 'no-cache', @@ -131,7 +131,7 @@ export async function deleteProjectRequest(projectID: string): Promise