Skip to content

Commit

Permalink
Merge branch 'main' into fix/string-as-defult-type
Browse files Browse the repository at this point in the history
  • Loading branch information
yk-eukarya authored Mar 4, 2025
2 parents 495823e + f4fef1b commit 550304f
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 60 deletions.
2 changes: 1 addition & 1 deletion server/internal/adapter/publicapi/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func NewController(project repo.Project, usecases *interfaces.Container, aur ass
}

func (c *Controller) checkProject(ctx context.Context, prj string) (*project.Project, error) {
pr, err := c.project.FindByPublicName(ctx, prj)
pr, err := c.project.FindByIDOrAlias(ctx, project.IDOrAlias(prj))
if err != nil {
if errors.Is(err, rerror.ErrNotFound) {
return nil, rerror.ErrNotFound
Expand Down
14 changes: 7 additions & 7 deletions server/internal/infrastructure/memory/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -110,26 +110,26 @@ func (r *Project) FindByIDOrAlias(_ context.Context, q project.IDOrAlias) (*proj
return nil, rerror.ErrNotFound
}

func (r *Project) FindByPublicName(_ context.Context, name string) (*project.Project, error) {
func (r *Project) IsAliasAvailable(_ context.Context, name string) (bool, error) {
if r.err != nil {
return nil, r.err
return false, r.err
}

if name == "" {
return nil, nil
return false, nil
}

// no need to filter by workspace, because alias is unique across all workspaces
p := r.data.Find(func(_ id.ProjectID, v *project.Project) bool {
return v.Alias() == name && r.f.CanRead(v.Workspace())
return v.Alias() == name
})

if p != nil {
return p, nil
return false, nil
}
return nil, rerror.ErrNotFound
return true, nil
}


func (r *Project) FindByPublicAPIToken(ctx context.Context, token string) (*project.Project, error) {
if r.err != nil {
return nil, r.err
Expand Down
30 changes: 15 additions & 15 deletions server/internal/infrastructure/memory/project_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ func TestProjectRepo_FindByIDs(t *testing.T) {
}
}

func TestProjectRepo_FindByPublicName(t *testing.T) {
func TestProjectRepo_IsAliasAvailable(t *testing.T) {
mocknow := time.Now().Truncate(time.Millisecond).UTC()
tid1 := accountdomain.NewWorkspaceID()
id1 := id.NewProjectID()
Expand All @@ -468,7 +468,7 @@ func TestProjectRepo_FindByPublicName(t *testing.T) {
seeds project.List
arg string
filter *repo.WorkspaceFilter
want *project.Project
want bool
wantErr error
mockErr bool
}{
Expand All @@ -477,8 +477,8 @@ func TestProjectRepo_FindByPublicName(t *testing.T) {
seeds: project.List{},
arg: "xyz123",
filter: nil,
want: nil,
wantErr: rerror.ErrNotFound,
want: true,
wantErr: nil,
},
{
name: "Not found",
Expand All @@ -487,8 +487,8 @@ func TestProjectRepo_FindByPublicName(t *testing.T) {
},
arg: "xyz123",
filter: nil,
want: nil,
wantErr: rerror.ErrNotFound,
want: true,
wantErr: nil,
},
{
name: "public Found",
Expand All @@ -497,16 +497,16 @@ func TestProjectRepo_FindByPublicName(t *testing.T) {
},
arg: "xyz123",
filter: nil,
want: p1,
want: false,
wantErr: nil,
},
{
name: "linited Found",
name: "limited Found",
seeds: project.List{
p2,
},
arg: "xyz321",
want: p2,
want: false,
filter: nil,
wantErr: nil,
},
Expand All @@ -519,20 +519,20 @@ func TestProjectRepo_FindByPublicName(t *testing.T) {
},
arg: "xyz123",
filter: nil,
want: p1,
want: false,
wantErr: nil,
},
{
name: "Filtered should not Found",
name: "Filtered should Found",
seeds: project.List{
p1,
project.New().NewID().Workspace(accountdomain.NewWorkspaceID()).MustBuild(),
project.New().NewID().Workspace(accountdomain.NewWorkspaceID()).MustBuild(),
},
arg: "xyz123",
filter: &repo.WorkspaceFilter{Readable: []accountdomain.WorkspaceID{accountdomain.NewWorkspaceID()}, Writable: []accountdomain.WorkspaceID{}},
want: nil,
wantErr: rerror.ErrNotFound,
want: false,
wantErr: nil,
},
{
name: "Filtered should Found",
Expand All @@ -543,7 +543,7 @@ func TestProjectRepo_FindByPublicName(t *testing.T) {
},
arg: "xyz123",
filter: &repo.WorkspaceFilter{Readable: []accountdomain.WorkspaceID{tid1}, Writable: []accountdomain.WorkspaceID{}},
want: p1,
want: false,
wantErr: nil,
},
{
Expand Down Expand Up @@ -573,7 +573,7 @@ func TestProjectRepo_FindByPublicName(t *testing.T) {
r = r.Filtered(*tc.filter)
}

got, err := r.FindByPublicName(ctx, tc.arg)
got, err := r.IsAliasAvailable(ctx, tc.arg)
if tc.wantErr != nil {
assert.ErrorIs(t, err, tc.wantErr)
return
Expand Down
27 changes: 22 additions & 5 deletions server/internal/infrastructure/mongo/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (

var (
// TODO: the `publication.token` should be unique, this should be fixed in the future
projectIndexes = []string{"workspace", "publication.token"}
projectIndexes = []string{"workspace"}
projectUniqueIndexes = []string{"id"}
)

Expand All @@ -31,7 +31,21 @@ func NewProject(client *mongox.Client) repo.Project {
}

func (r *ProjectRepo) Init() error {
return createIndexes(context.Background(), r.client, projectIndexes, projectUniqueIndexes)
idx := mongox.IndexFromKeys(projectIndexes, false)
idx = append(idx, mongox.IndexFromKeys(projectUniqueIndexes, true)...)
idx = append(idx, mongox.Index{
Name: "re_publication_token",
Key: bson.D{{Key: "publication.token", Value: 1}},
Unique: true,
Filter: bson.M{"publication.token": bson.M{"$type": "string"}},
})
idx = append(idx, mongox.Index{
Name: "re_alias",
Key: bson.D{{Key: "alias", Value: 1}},
Unique: true,
Filter: bson.M{"alias": bson.M{"$type": "string"}},
})
return createIndexes2(context.Background(), r.client, idx...)
}

func (r *ProjectRepo) Filtered(f repo.WorkspaceFilter) repo.Project {
Expand Down Expand Up @@ -90,13 +104,16 @@ func (r *ProjectRepo) FindByIDOrAlias(ctx context.Context, id project.IDOrAlias)
return r.findOne(ctx, filter)
}

func (r *ProjectRepo) FindByPublicName(ctx context.Context, name string) (*project.Project, error) {
func (r *ProjectRepo) IsAliasAvailable(ctx context.Context, name string) (bool, error) {
if name == "" {
return nil, rerror.ErrNotFound
return false, nil
}
return r.findOne(ctx, bson.M{

// no need to filter by workspace, because alias is unique across all workspaces
c, err := r.client.Count(ctx, bson.M{
"alias": name,
})
return c == 0 && err == nil, err
}

func (r *ProjectRepo) FindByPublicAPIToken(ctx context.Context, token string) (*project.Project, error) {
Expand Down
30 changes: 15 additions & 15 deletions server/internal/infrastructure/mongo/project_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ func Test_projectRepo_FindByIDs(t *testing.T) {
}
}

func Test_projectRepo_FindByPublicName(t *testing.T) {
func Test_projectRepo_IsAliasAvailable(t *testing.T) {
now := time.Now().Truncate(time.Millisecond).UTC()
tid1 := accountdomain.NewWorkspaceID()
id1 := id.NewProjectID()
Expand All @@ -445,16 +445,16 @@ func Test_projectRepo_FindByPublicName(t *testing.T) {
seeds project.List
arg string
filter *repo.WorkspaceFilter
want *project.Project
want bool
wantErr error
}{
{
name: "Not found in empty db",
seeds: project.List{},
arg: "xyz123",
filter: nil,
want: nil,
wantErr: rerror.ErrNotFound,
want: true,
wantErr: nil,
},
{
name: "Not found",
Expand All @@ -463,8 +463,8 @@ func Test_projectRepo_FindByPublicName(t *testing.T) {
},
arg: "xyz123",
filter: nil,
want: nil,
wantErr: rerror.ErrNotFound,
want: true,
wantErr: nil,
},
{
name: "public Found",
Expand All @@ -473,16 +473,16 @@ func Test_projectRepo_FindByPublicName(t *testing.T) {
},
arg: "xyz123",
filter: nil,
want: p1,
want: false,
wantErr: nil,
},
{
name: "linited Found",
name: "limited Found",
seeds: project.List{
p2,
},
arg: "xyz321",
want: p2,
want: false,
filter: nil,
wantErr: nil,
},
Expand All @@ -495,20 +495,20 @@ func Test_projectRepo_FindByPublicName(t *testing.T) {
},
arg: "xyz123",
filter: nil,
want: p1,
want: false,
wantErr: nil,
},
{
name: "Filtered should not Found",
name: "Filtered should Found",
seeds: project.List{
p1,
project.New().NewID().Workspace(accountdomain.NewWorkspaceID()).MustBuild(),
project.New().NewID().Workspace(accountdomain.NewWorkspaceID()).MustBuild(),
},
arg: "xyz123",
filter: &repo.WorkspaceFilter{Readable: []accountdomain.WorkspaceID{accountdomain.NewWorkspaceID()}, Writable: []accountdomain.WorkspaceID{}},
want: nil,
wantErr: rerror.ErrNotFound,
want: false,
wantErr: nil,
},
{
name: "Filtered should Found",
Expand All @@ -519,7 +519,7 @@ func Test_projectRepo_FindByPublicName(t *testing.T) {
},
arg: "xyz123",
filter: &repo.WorkspaceFilter{Readable: []accountdomain.WorkspaceID{tid1}, Writable: []accountdomain.WorkspaceID{}},
want: p1,
want: false,
wantErr: nil,
},
}
Expand All @@ -544,7 +544,7 @@ func Test_projectRepo_FindByPublicName(t *testing.T) {
r = r.Filtered(*tc.filter)
}

got, err := r.FindByPublicName(ctx, tc.arg)
got, err := r.IsAliasAvailable(ctx, tc.arg)
if tc.wantErr != nil {
assert.ErrorIs(t, err, tc.wantErr)
return
Expand Down
21 changes: 5 additions & 16 deletions server/internal/usecase/interactor/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package interactor

import (
"context"
"errors"
"time"

"github.com/reearth/reearth-cms/server/internal/usecase"
Expand All @@ -13,7 +12,6 @@ import (
"github.com/reearth/reearth-cms/server/pkg/project"
"github.com/reearth/reearthx/account/accountdomain"
"github.com/reearth/reearthx/account/accountdomain/workspace"
"github.com/reearth/reearthx/rerror"
"github.com/reearth/reearthx/usecasex"
)

Expand Down Expand Up @@ -54,11 +52,9 @@ func (i *Project) Create(ctx context.Context, p interfaces.CreateProjectParam, o
pb = pb.Description(*p.Description)
}
if p.Alias != nil {
proj2, _ := i.repos.Project.FindByPublicName(ctx, *p.Alias)
if proj2 != nil {
if ok, _ := i.repos.Project.IsAliasAvailable(ctx, *p.Alias); !ok {
return nil, interfaces.ErrProjectAliasAlreadyUsed
}

pb = pb.Alias(*p.Alias)
}
if len(p.RequestRoles) > 0 {
Expand Down Expand Up @@ -95,10 +91,8 @@ func (i *Project) Update(ctx context.Context, p interfaces.UpdateProjectParam, o
proj.UpdateDescription(*p.Description)
}

if p.Alias != nil {
proj2, _ := i.repos.Project.FindByPublicName(ctx, *p.Alias)

if proj2 != nil && proj2.ID() != proj.ID() {
if p.Alias != nil && *p.Alias != proj.Alias() {
if ok, _ := i.repos.Project.IsAliasAvailable(ctx, *p.Alias); !ok {
return nil, interfaces.ErrProjectAliasAlreadyUsed
}

Expand Down Expand Up @@ -140,12 +134,7 @@ func (i *Project) CheckAlias(ctx context.Context, alias string) (bool, error) {
return false, project.ErrInvalidAlias
}

prj, err := i.repos.Project.FindByPublicName(ctx, alias)
if prj == nil && err == nil || err != nil && errors.Is(err, rerror.ErrNotFound) {
return true, nil
}

return false, err
return i.repos.Project.IsAliasAvailable(ctx, alias)
})
}

Expand Down Expand Up @@ -182,7 +171,7 @@ func (i *Project) RegenerateToken(ctx context.Context, pId id.ProjectID, operato
return nil, interfaces.ErrOperationDenied
}

if p.Publication() == nil || p.Publication().Scope() != project.PublicationScopeLimited {
if p.Publication() == nil || p.Publication().Scope() != project.PublicationScopeLimited {
return nil, interfaces.ErrInvalidProject
}

Expand Down
2 changes: 1 addition & 1 deletion server/internal/usecase/repo/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ type Project interface {
FindByID(context.Context, id.ProjectID) (*project.Project, error)
FindByIDOrAlias(context.Context, project.IDOrAlias) (*project.Project, error)
FindByWorkspaces(context.Context, accountdomain.WorkspaceIDList, *usecasex.Pagination) (project.List, *usecasex.PageInfo, error)
FindByPublicName(context.Context, string) (*project.Project, error)
IsAliasAvailable(context.Context, string) (bool, error)
CountByWorkspace(context.Context, accountdomain.WorkspaceID) (int, error)
FindByPublicAPIToken(context.Context, string) (*project.Project, error)
Save(context.Context, *project.Project) error
Expand Down

0 comments on commit 550304f

Please sign in to comment.