satellite/{console,satellitedb}: add methods for project invite table
This change immplements methods for interacting with the project member invitations table. Resolves #5766 Change-Id: I0090c50f9fde5bcdae4ebdaa72cdcaa84d341b54
This commit is contained in:
parent
defb9eae82
commit
7a17dc5e07
@ -19,6 +19,8 @@ type DB interface {
|
||||
Projects() Projects
|
||||
// ProjectMembers is a getter for ProjectMembers repository.
|
||||
ProjectMembers() ProjectMembers
|
||||
// ProjectInvitations is a getter for ProjectInvitations repository.
|
||||
ProjectInvitations() ProjectInvitations
|
||||
// APIKeys is a getter for APIKeys repository.
|
||||
APIKeys() APIKeys
|
||||
// RegistrationTokens is a getter for RegistrationTokens repository.
|
||||
|
32
satellite/console/projectinvitations.go
Normal file
32
satellite/console/projectinvitations.go
Normal file
@ -0,0 +1,32 @@
|
||||
// Copyright (C) 2023 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package console
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"storj.io/common/uuid"
|
||||
)
|
||||
|
||||
// ProjectInvitations exposes methods to manage pending project member invitations in the database.
|
||||
//
|
||||
// architecture: Database
|
||||
type ProjectInvitations interface {
|
||||
// Insert is a method for inserting a project member invitation into the database.
|
||||
Insert(ctx context.Context, projectID uuid.UUID, email string) (*ProjectInvitation, error)
|
||||
// GetByProjectID returns all of the project member invitations for the project specified by the given ID.
|
||||
GetByProjectID(ctx context.Context, projectID uuid.UUID) ([]ProjectInvitation, error)
|
||||
// GetByEmail returns all of the project member invitations for the specified email address.
|
||||
GetByEmail(ctx context.Context, email string) ([]ProjectInvitation, error)
|
||||
// Delete is a method for deleting a project member invitation from the database.
|
||||
Delete(ctx context.Context, projectID uuid.UUID, email string) error
|
||||
}
|
||||
|
||||
// ProjectInvitation represents a pending project member invitation.
|
||||
type ProjectInvitation struct {
|
||||
ProjectID uuid.UUID
|
||||
Email string
|
||||
CreatedAt time.Time
|
||||
}
|
@ -46,6 +46,11 @@ func (db *ConsoleDB) ProjectMembers() console.ProjectMembers {
|
||||
return &projectMembers{db.methods, db.db}
|
||||
}
|
||||
|
||||
// ProjectInvitations is a getter for ProjectInvitations repository.
|
||||
func (db *ConsoleDB) ProjectInvitations() console.ProjectInvitations {
|
||||
return &projectInvitations{db.methods}
|
||||
}
|
||||
|
||||
// APIKeys is a getter for APIKeys repository.
|
||||
func (db *ConsoleDB) APIKeys() console.APIKeys {
|
||||
db.apikeysOnce.Do(func() {
|
||||
|
101
satellite/satellitedb/projectinvitations.go
Normal file
101
satellite/satellitedb/projectinvitations.go
Normal file
@ -0,0 +1,101 @@
|
||||
// Copyright (C) 2023 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package satellitedb
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"storj.io/common/uuid"
|
||||
"storj.io/storj/satellite/console"
|
||||
"storj.io/storj/satellite/satellitedb/dbx"
|
||||
)
|
||||
|
||||
// Ensure that projectInvitations implements console.ProjectInvitations.
|
||||
var _ console.ProjectInvitations = (*projectInvitations)(nil)
|
||||
|
||||
// projectInvitations is an implementation of console.ProjectInvitations.
|
||||
type projectInvitations struct {
|
||||
db dbx.Methods
|
||||
}
|
||||
|
||||
// Insert is a method for inserting a project member invitation into the database.
|
||||
func (invites *projectInvitations) Insert(ctx context.Context, projectID uuid.UUID, email string) (_ *console.ProjectInvitation, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
dbxInvite, err := invites.db.Create_ProjectInvitation(ctx,
|
||||
dbx.ProjectInvitation_ProjectId(projectID[:]),
|
||||
dbx.ProjectInvitation_Email(normalizeEmail(email)),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return projectInvitationFromDBX(dbxInvite)
|
||||
}
|
||||
|
||||
// GetByProjectID returns all of the project member invitations for the project specified by the given ID.
|
||||
func (invites *projectInvitations) GetByProjectID(ctx context.Context, projectID uuid.UUID) (_ []console.ProjectInvitation, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
dbxInvites, err := invites.db.All_ProjectInvitation_By_ProjectId(ctx, dbx.ProjectInvitation_ProjectId(projectID[:]))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return projectInvitationSliceFromDBX(dbxInvites)
|
||||
}
|
||||
|
||||
// GetByEmail returns all of the project member invitations for the specified email address.
|
||||
func (invites *projectInvitations) GetByEmail(ctx context.Context, email string) (_ []console.ProjectInvitation, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
dbxInvites, err := invites.db.All_ProjectInvitation_By_Email(ctx, dbx.ProjectInvitation_Email(normalizeEmail(email)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return projectInvitationSliceFromDBX(dbxInvites)
|
||||
}
|
||||
|
||||
// Delete is a method for deleting a project member invitation from the database.
|
||||
func (invites *projectInvitations) Delete(ctx context.Context, projectID uuid.UUID, email string) (err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
_, err = invites.db.Delete_ProjectInvitation_By_ProjectId_And_Email(ctx,
|
||||
dbx.ProjectInvitation_ProjectId(projectID[:]),
|
||||
dbx.ProjectInvitation_Email(normalizeEmail(email)),
|
||||
)
|
||||
return err
|
||||
}
|
||||
|
||||
// projectInvitationFromDBX converts a project member invitation from the database to a *console.ProjectInvitation.
|
||||
func projectInvitationFromDBX(dbxInvite *dbx.ProjectInvitation) (_ *console.ProjectInvitation, err error) {
|
||||
if dbxInvite == nil {
|
||||
return nil, Error.New("dbx invitation is nil")
|
||||
}
|
||||
|
||||
projectID, err := uuid.FromBytes(dbxInvite.ProjectId)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &console.ProjectInvitation{
|
||||
ProjectID: projectID,
|
||||
Email: dbxInvite.Email,
|
||||
CreatedAt: dbxInvite.CreatedAt,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// projectInvitationSliceFromDBX converts a project member invitation slice from the database to a
|
||||
// slice of console.ProjectInvitation.
|
||||
func projectInvitationSliceFromDBX(dbxInvites []*dbx.ProjectInvitation) (invites []console.ProjectInvitation, err error) {
|
||||
for _, dbxInvite := range dbxInvites {
|
||||
invite, err := projectInvitationFromDBX(dbxInvite)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
invites = append(invites, *invite)
|
||||
}
|
||||
return invites, nil
|
||||
}
|
96
satellite/satellitedb/projectinvitations_test.go
Normal file
96
satellite/satellitedb/projectinvitations_test.go
Normal file
@ -0,0 +1,96 @@
|
||||
// Copyright (C) 2023 Storj Labs, Inc.
|
||||
// See LICENSE for copying information.
|
||||
|
||||
package satellitedb_test
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"storj.io/common/testcontext"
|
||||
"storj.io/common/testrand"
|
||||
"storj.io/storj/satellite"
|
||||
"storj.io/storj/satellite/console"
|
||||
"storj.io/storj/satellite/satellitedb/satellitedbtest"
|
||||
)
|
||||
|
||||
func TestProjectInvitations(t *testing.T) {
|
||||
satellitedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db satellite.DB) {
|
||||
invitesDB := db.Console().ProjectInvitations()
|
||||
projectsDB := db.Console().Projects()
|
||||
projID := testrand.UUID()
|
||||
projID2 := testrand.UUID()
|
||||
email := "user@mail.test"
|
||||
email2 := "user2@mail.test"
|
||||
|
||||
_, err := projectsDB.Insert(ctx, &console.Project{ID: projID})
|
||||
require.NoError(t, err)
|
||||
_, err = projectsDB.Insert(ctx, &console.Project{ID: projID2})
|
||||
require.NoError(t, err)
|
||||
|
||||
invite, err := invitesDB.Insert(ctx, projID, email)
|
||||
require.NoError(t, err)
|
||||
require.WithinDuration(t, time.Now(), invite.CreatedAt, time.Minute)
|
||||
require.Equal(t, projID, invite.ProjectID)
|
||||
require.Equal(t, strings.ToUpper(email), invite.Email)
|
||||
|
||||
_, err = invitesDB.Insert(ctx, projID, email)
|
||||
require.Error(t, err)
|
||||
|
||||
inviteSameEmail, err := invitesDB.Insert(ctx, projID2, email)
|
||||
require.NoError(t, err)
|
||||
inviteSameProject, err := invitesDB.Insert(ctx, projID, email2)
|
||||
require.NoError(t, err)
|
||||
|
||||
t.Run("get invitations by email", func(t *testing.T) {
|
||||
ctx := testcontext.New(t)
|
||||
|
||||
invites, err := invitesDB.GetByEmail(ctx, "nobody@mail.test")
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, invites)
|
||||
|
||||
invites, err = invitesDB.GetByEmail(ctx, "uSeR@mAiL.tEsT")
|
||||
require.NoError(t, err)
|
||||
require.ElementsMatch(t, invites, []console.ProjectInvitation{*invite, *inviteSameEmail})
|
||||
})
|
||||
|
||||
t.Run("get invitations by project ID", func(t *testing.T) {
|
||||
ctx := testcontext.New(t)
|
||||
|
||||
invites, err := invitesDB.GetByProjectID(ctx, testrand.UUID())
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, invites)
|
||||
|
||||
invites, err = invitesDB.GetByProjectID(ctx, projID)
|
||||
require.NoError(t, err)
|
||||
require.ElementsMatch(t, invites, []console.ProjectInvitation{*invite, *inviteSameProject})
|
||||
})
|
||||
|
||||
t.Run("delete invitation", func(t *testing.T) {
|
||||
ctx := testcontext.New(t)
|
||||
|
||||
require.NoError(t, invitesDB.Delete(ctx, projID, email))
|
||||
|
||||
invites, err := invitesDB.GetByEmail(ctx, email)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, invites, []console.ProjectInvitation{*inviteSameEmail})
|
||||
})
|
||||
|
||||
t.Run("ensure project removal deletes invitations", func(t *testing.T) {
|
||||
ctx := testcontext.New(t)
|
||||
|
||||
require.NoError(t, projectsDB.Delete(ctx, projID))
|
||||
|
||||
invites, err := invitesDB.GetByProjectID(ctx, projID)
|
||||
require.NoError(t, err)
|
||||
require.Empty(t, invites)
|
||||
|
||||
invites, err = invitesDB.GetByEmail(ctx, email)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, invites, []console.ProjectInvitation{*inviteSameEmail})
|
||||
})
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue
Block a user