From 1f44cf2665ab34a6aa23cb4d21138feafa10ef3b Mon Sep 17 00:00:00 2001 From: raararaara Date: Mon, 8 Jan 2024 18:03:58 +0900 Subject: [PATCH 1/9] Add FindProjectInfoBySecretKey and FindUserInfoById Add FindProjectInfoBySecretKey and FindUserInfoById --- server/backend/database/database.go | 9 +++++ server/backend/database/memory/database.go | 35 +++++++++++++++++++ .../backend/database/memory/database_test.go | 4 +++ server/backend/database/mongo/client.go | 34 ++++++++++++++++++ server/backend/database/mongo/client_test.go | 4 +++ .../backend/database/testcases/testcases.go | 19 ++++++++++ server/projects/projects.go | 18 ++++++++++ server/rpc/interceptors/admin_auth.go | 19 ++++++---- server/users/users.go | 12 +++++++ 9 files changed, 148 insertions(+), 6 deletions(-) diff --git a/server/backend/database/database.go b/server/backend/database/database.go index be0118e2f..ff64ab009 100644 --- a/server/backend/database/database.go +++ b/server/backend/database/database.go @@ -68,6 +68,12 @@ type Database interface { publicKey string, ) (*ProjectInfo, error) + // FindProjectInfoBySecretKey returns a project by secret key. + FindProjectInfoBySecretKey( + ctx context.Context, + secretKey string, + ) (*ProjectInfo, error) + // FindProjectInfoByName returns a project by the given name. FindProjectInfoByName( ctx context.Context, @@ -118,6 +124,9 @@ type Database interface { // FindUserInfo returns a user by the given username. FindUserInfo(ctx context.Context, username string) (*UserInfo, error) + // FindUserInfoById finds a user by the given id. + FindUserInfoById(ctx context.Context, id string) (*UserInfo, error) + // ListUserInfos returns all users. ListUserInfos(ctx context.Context) ([]*UserInfo, error) diff --git a/server/backend/database/memory/database.go b/server/backend/database/memory/database.go index 7a45335cb..423c20137 100644 --- a/server/backend/database/memory/database.go +++ b/server/backend/database/memory/database.go @@ -75,6 +75,25 @@ func (d *DB) FindProjectInfoByPublicKey( return raw.(*database.ProjectInfo).DeepCopy(), nil } +// FindProjectInfoBySecretKey returns a project by secret key. +func (d *DB) FindProjectInfoBySecretKey( + _ context.Context, + secretKey string, +) (*database.ProjectInfo, error) { + txn := d.db.Txn(false) + defer txn.Abort() + + raw, err := txn.First(tblProjects, "secret_key", secretKey) + if err != nil { + return nil, fmt.Errorf("find project by secret key: %w", err) + } + if raw == nil { + return nil, fmt.Errorf("%s: %w", secretKey, database.ErrProjectNotFound) + } + + return raw.(*database.ProjectInfo).DeepCopy(), nil +} + // FindProjectInfoByName returns a project by the given name. func (d *DB) FindProjectInfoByName( _ context.Context, @@ -379,6 +398,22 @@ func (d *DB) FindUserInfo(_ context.Context, username string) (*database.UserInf return raw.(*database.UserInfo).DeepCopy(), nil } +// FindUserInfoById finds a user by the given id. +func (d *DB) FindUserInfoById(_ context.Context, id string) (*database.UserInfo, error) { + txn := d.db.Txn(false) + defer txn.Abort() + + raw, err := txn.First(tblUsers, "id", id) + if err != nil { + return nil, fmt.Errorf("find user by id: %w", err) + } + if raw == nil { + return nil, fmt.Errorf("%s: %w", id, database.ErrUserNotFound) + } + + return raw.(*database.UserInfo).DeepCopy(), nil +} + // ListUserInfos returns all users. func (d *DB) ListUserInfos(_ context.Context) ([]*database.UserInfo, error) { txn := d.db.Txn(false) diff --git a/server/backend/database/memory/database_test.go b/server/backend/database/memory/database_test.go index 2486f8bf1..1f691b693 100644 --- a/server/backend/database/memory/database_test.go +++ b/server/backend/database/memory/database_test.go @@ -56,6 +56,10 @@ func TestDB(t *testing.T) { testcases.RunListUserInfosTest(t, db) }) + t.Run("FindProjectInfoBySecretKey test", func(t *testing.T) { + testcases.RunFindProjectInfoBySecretKeyTest(t, db) + }) + t.Run("FindProjectInfoByName test", func(t *testing.T) { testcases.RunFindProjectInfoByNameTest(t, db) }) diff --git a/server/backend/database/mongo/client.go b/server/backend/database/mongo/client.go index 5429f58f7..0555d1359 100644 --- a/server/backend/database/mongo/client.go +++ b/server/backend/database/mongo/client.go @@ -313,6 +313,23 @@ func (c *Client) FindProjectInfoByPublicKey(ctx context.Context, publicKey strin return &projectInfo, nil } +// FindProjectInfoBySecretKey returns a project by secret key. +func (c *Client) FindProjectInfoBySecretKey(ctx context.Context, secretKey string) (*database.ProjectInfo, error) { + result := c.collection(colProjects).FindOne(ctx, bson.M{ + "secret_key": secretKey, + }) + + projectInfo := database.ProjectInfo{} + if err := result.Decode(&projectInfo); err != nil { + if err == mongo.ErrNoDocuments { + return nil, fmt.Errorf("%s: %w", secretKey, database.ErrProjectNotFound) + } + return nil, fmt.Errorf("decode project info: %w", err) + } + + return &projectInfo, nil +} + // FindProjectInfoByName returns a project by name. func (c *Client) FindProjectInfoByName( ctx context.Context, @@ -451,6 +468,23 @@ func (c *Client) FindUserInfo(ctx context.Context, username string) (*database.U return &userInfo, nil } +// FindUserInfoById returns a user by id. +func (c *Client) FindUserInfoById(ctx context.Context, id string) (*database.UserInfo, error) { + result := c.collection(colUsers).FindOne(ctx, bson.M{ + "_id": id, + }) + + userInfo := database.UserInfo{} + if err := result.Decode(&userInfo); err != nil { + if err == mongo.ErrNoDocuments { + return nil, fmt.Errorf("%s: %w", id, database.ErrUserNotFound) + } + return nil, fmt.Errorf("decode user info: %w", err) + } + + return &userInfo, nil +} + // ListUserInfos returns all users. func (c *Client) ListUserInfos( ctx context.Context, diff --git a/server/backend/database/mongo/client_test.go b/server/backend/database/mongo/client_test.go index 9eaf04034..627f1c4f2 100644 --- a/server/backend/database/mongo/client_test.go +++ b/server/backend/database/mongo/client_test.go @@ -73,6 +73,10 @@ func TestClient(t *testing.T) { testcases.RunListUserInfosTest(t, cli) }) + t.Run("FindProjectInfoBySecretKey test", func(t *testing.T) { + testcases.RunFindProjectInfoBySecretKeyTest(t, cli) + }) + t.Run("FindProjectInfoByName test", func(t *testing.T) { testcases.RunFindProjectInfoByNameTest(t, cli) }) diff --git a/server/backend/database/testcases/testcases.go b/server/backend/database/testcases/testcases.go index 3cc19121c..a972711ee 100644 --- a/server/backend/database/testcases/testcases.go +++ b/server/backend/database/testcases/testcases.go @@ -72,6 +72,25 @@ func RunFindDocInfoTest( }) } +// RunFindProjectInfoBySecretKeyTest runs the FindProjectInfoBySecretKey test for the given db. +func RunFindProjectInfoBySecretKeyTest( + t *testing.T, + db database.Database, +) { + t.Run("FindProjectInfoBySecretKey test", func(t *testing.T) { + ctx := context.Background() + + info1, err := db.CreateProjectInfo(ctx, t.Name(), dummyOwnerID, clientDeactivateThreshold) + assert.NoError(t, err) + _, err = db.CreateProjectInfo(ctx, t.Name(), otherOwnerID, clientDeactivateThreshold) + assert.NoError(t, err) + + info2, err := db.FindProjectInfoBySecretKey(ctx, info1.SecretKey) + assert.NoError(t, err) + assert.Equal(t, info1.ID, info2.ID) + }) +} + // RunFindProjectInfoByNameTest runs the FindProjectInfoByName test for the given db. func RunFindProjectInfoByNameTest( t *testing.T, diff --git a/server/projects/projects.go b/server/projects/projects.go index ab9ee2370..229e9d387 100644 --- a/server/projects/projects.go +++ b/server/projects/projects.go @@ -107,3 +107,21 @@ func GetProjectFromAPIKey(ctx context.Context, be *backend.Backend, apiKey strin return info.ToProject(), nil } + +// GetProjectFromSecretKey returns a project from a secret key. +func GetProjectFromSecretKey(ctx context.Context, be *backend.Backend, secretKey string) (*types.Project, error) { + if secretKey == "" { + info, err := be.DB.FindProjectInfoByID(ctx, database.DefaultProjectID) + if err != nil { + return nil, err + } + return info.ToProject(), nil + } + + info, err := be.DB.FindProjectInfoBySecretKey(ctx, secretKey) + if err != nil { + return nil, err + } + + return info.ToProject(), nil +} diff --git a/server/rpc/interceptors/admin_auth.go b/server/rpc/interceptors/admin_auth.go index 2855d308c..607075cfc 100644 --- a/server/rpc/interceptors/admin_auth.go +++ b/server/rpc/interceptors/admin_auth.go @@ -28,6 +28,7 @@ import ( "github.com/yorkie-team/yorkie/api/types" "github.com/yorkie-team/yorkie/server/backend" + "github.com/yorkie-team/yorkie/server/projects" "github.com/yorkie-team/yorkie/server/rpc/auth" "github.com/yorkie-team/yorkie/server/rpc/connecthelper" "github.com/yorkie-team/yorkie/server/users" @@ -161,14 +162,20 @@ func (i *AdminAuthInterceptor) authenticate( } claims, err := i.tokenManager.Verify(authorization) - if err != nil { - return nil, grpcstatus.Errorf(codes.Unauthenticated, "authorization is invalid") + if err == nil { + user, err := users.GetUser(ctx, i.backend, claims.Username) + if err == nil { + return user, nil + } } - user, err := users.GetUser(ctx, i.backend, claims.Username) - if err != nil { - return nil, grpcstatus.Errorf(codes.Unauthenticated, "authorization is invalid") + project, err := projects.GetProjectFromSecretKey(ctx, i.backend, authorization) + if err == nil { + user, err := users.GetUserById(ctx, i.backend, project.Owner.String()) + if err == nil { + return user, nil + } } - return user, nil + return nil, grpcstatus.Errorf(codes.Unauthenticated, "authorization is invalid") } diff --git a/server/users/users.go b/server/users/users.go index e24d383f0..a59bb2413 100644 --- a/server/users/users.go +++ b/server/users/users.go @@ -81,3 +81,15 @@ func GetUser( return info.ToUser(), nil } + +func GetUserById( + ctx context.Context, + be *backend.Backend, + id string, +) (*types.User, error) { + info, err := be.DB.FindUserInfoById(ctx, id) + if err != nil { + return nil, err + } + return info.ToUser(), nil +} From ebfb46517e74870047d4941e092ecc3d30f5f5e1 Mon Sep 17 00:00:00 2001 From: raararaara Date: Tue, 9 Jan 2024 13:57:28 +0900 Subject: [PATCH 2/9] Fix lint error --- server/backend/database/database.go | 2 +- server/backend/database/memory/database.go | 4 ++-- server/backend/database/mongo/client.go | 4 ++-- server/rpc/interceptors/admin_auth.go | 2 +- server/users/users.go | 5 +++-- 5 files changed, 9 insertions(+), 8 deletions(-) diff --git a/server/backend/database/database.go b/server/backend/database/database.go index ff64ab009..468c05e30 100644 --- a/server/backend/database/database.go +++ b/server/backend/database/database.go @@ -125,7 +125,7 @@ type Database interface { FindUserInfo(ctx context.Context, username string) (*UserInfo, error) // FindUserInfoById finds a user by the given id. - FindUserInfoById(ctx context.Context, id string) (*UserInfo, error) + FindUserInfoByID(ctx context.Context, id string) (*UserInfo, error) // ListUserInfos returns all users. ListUserInfos(ctx context.Context) ([]*UserInfo, error) diff --git a/server/backend/database/memory/database.go b/server/backend/database/memory/database.go index 423c20137..d05857eef 100644 --- a/server/backend/database/memory/database.go +++ b/server/backend/database/memory/database.go @@ -398,8 +398,8 @@ func (d *DB) FindUserInfo(_ context.Context, username string) (*database.UserInf return raw.(*database.UserInfo).DeepCopy(), nil } -// FindUserInfoById finds a user by the given id. -func (d *DB) FindUserInfoById(_ context.Context, id string) (*database.UserInfo, error) { +// FindUserInfoByID finds a user by the given ID. +func (d *DB) FindUserInfoByID(_ context.Context, id string) (*database.UserInfo, error) { txn := d.db.Txn(false) defer txn.Abort() diff --git a/server/backend/database/mongo/client.go b/server/backend/database/mongo/client.go index 0555d1359..64b3eb18a 100644 --- a/server/backend/database/mongo/client.go +++ b/server/backend/database/mongo/client.go @@ -468,8 +468,8 @@ func (c *Client) FindUserInfo(ctx context.Context, username string) (*database.U return &userInfo, nil } -// FindUserInfoById returns a user by id. -func (c *Client) FindUserInfoById(ctx context.Context, id string) (*database.UserInfo, error) { +// FindUserInfoByID returns a user by ID. +func (c *Client) FindUserInfoByID(ctx context.Context, id string) (*database.UserInfo, error) { result := c.collection(colUsers).FindOne(ctx, bson.M{ "_id": id, }) diff --git a/server/rpc/interceptors/admin_auth.go b/server/rpc/interceptors/admin_auth.go index 607075cfc..0dd3483d4 100644 --- a/server/rpc/interceptors/admin_auth.go +++ b/server/rpc/interceptors/admin_auth.go @@ -171,7 +171,7 @@ func (i *AdminAuthInterceptor) authenticate( project, err := projects.GetProjectFromSecretKey(ctx, i.backend, authorization) if err == nil { - user, err := users.GetUserById(ctx, i.backend, project.Owner.String()) + user, err := users.GetUserByID(ctx, i.backend, project.Owner.String()) if err == nil { return user, nil } diff --git a/server/users/users.go b/server/users/users.go index a59bb2413..0ff99b19d 100644 --- a/server/users/users.go +++ b/server/users/users.go @@ -82,12 +82,13 @@ func GetUser( return info.ToUser(), nil } -func GetUserById( +// GetUserByID returns a user by ID. +func GetUserByID( ctx context.Context, be *backend.Backend, id string, ) (*types.User, error) { - info, err := be.DB.FindUserInfoById(ctx, id) + info, err := be.DB.FindUserInfoByID(ctx, id) if err != nil { return nil, err } From d3916692677b523032bd6f3bd5dd0677e6ffd1d1 Mon Sep 17 00:00:00 2001 From: raararaara Date: Tue, 9 Jan 2024 14:01:09 +0900 Subject: [PATCH 3/9] Fix lint error --- server/rpc/interceptors/admin_auth.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/rpc/interceptors/admin_auth.go b/server/rpc/interceptors/admin_auth.go index ad085c4fd..ac3bce2f7 100644 --- a/server/rpc/interceptors/admin_auth.go +++ b/server/rpc/interceptors/admin_auth.go @@ -178,5 +178,5 @@ func (i *AdminAuthInterceptor) authenticate( } } - return nil, grpcstatus.Errorf(codes.Unauthenticated, "authorization is invalid") + return nil, connect.NewError(connect.CodeUnauthenticated, ErrUnauthenticated) } From cd8f9be232a145fa52405635fcd63e3e930a74bb Mon Sep 17 00:00:00 2001 From: raararaara Date: Tue, 9 Jan 2024 15:44:10 +0900 Subject: [PATCH 4/9] Update FindProjectInfoBySecretKey test Update FindProjectInfoBySecretKey test --- server/backend/database/testcases/testcases.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/server/backend/database/testcases/testcases.go b/server/backend/database/testcases/testcases.go index a972711ee..23772ad61 100644 --- a/server/backend/database/testcases/testcases.go +++ b/server/backend/database/testcases/testcases.go @@ -80,14 +80,16 @@ func RunFindProjectInfoBySecretKeyTest( t.Run("FindProjectInfoBySecretKey test", func(t *testing.T) { ctx := context.Background() - info1, err := db.CreateProjectInfo(ctx, t.Name(), dummyOwnerID, clientDeactivateThreshold) - assert.NoError(t, err) - _, err = db.CreateProjectInfo(ctx, t.Name(), otherOwnerID, clientDeactivateThreshold) + username := "admin@yorkie.dev" + password := "hashed-password" + + _, project, err := db.EnsureDefaultUserAndProject(ctx, username, password, clientDeactivateThreshold) assert.NoError(t, err) - info2, err := db.FindProjectInfoBySecretKey(ctx, info1.SecretKey) + info2, err := db.FindProjectInfoBySecretKey(ctx, project.SecretKey) assert.NoError(t, err) - assert.Equal(t, info1.ID, info2.ID) + + assert.Equal(t, project.ID, info2.ID) }) } From 6ab7f5b93c46e8e9b1024efa8391ae6ce061036c Mon Sep 17 00:00:00 2001 From: raararaara Date: Wed, 10 Jan 2024 15:39:23 +0900 Subject: [PATCH 5/9] Add comment for authentication casework --- server/rpc/interceptors/admin_auth.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/rpc/interceptors/admin_auth.go b/server/rpc/interceptors/admin_auth.go index ac3bce2f7..ed9c6483a 100644 --- a/server/rpc/interceptors/admin_auth.go +++ b/server/rpc/interceptors/admin_auth.go @@ -162,6 +162,7 @@ func (i *AdminAuthInterceptor) authenticate( return nil, connect.NewError(connect.CodeUnauthenticated, ErrUnauthenticated) } + // NOTE(raararaara): If the token is access token, return the user of the token. claims, err := i.tokenManager.Verify(authorization) if err == nil { user, err := users.GetUser(ctx, i.backend, claims.Username) @@ -170,6 +171,7 @@ func (i *AdminAuthInterceptor) authenticate( } } + // NOTE(raararaara): If the token is secret key, return the owner of the project. project, err := projects.GetProjectFromSecretKey(ctx, i.backend, authorization) if err == nil { user, err := users.GetUserByID(ctx, i.backend, project.Owner.String()) From a6a9e19a0e563a742b3544934a3c2a58c95910b4 Mon Sep 17 00:00:00 2001 From: raararaara Date: Wed, 10 Jan 2024 15:44:31 +0900 Subject: [PATCH 6/9] Fix comment lint --- server/backend/database/database.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/backend/database/database.go b/server/backend/database/database.go index 468c05e30..24dba1091 100644 --- a/server/backend/database/database.go +++ b/server/backend/database/database.go @@ -124,7 +124,7 @@ type Database interface { // FindUserInfo returns a user by the given username. FindUserInfo(ctx context.Context, username string) (*UserInfo, error) - // FindUserInfoById finds a user by the given id. + // FindUserInfoByID finds a user by the given id. FindUserInfoByID(ctx context.Context, id string) (*UserInfo, error) // ListUserInfos returns all users. From f1cb1d8aa6ff1cfaa39e63dc707e2833495fe331 Mon Sep 17 00:00:00 2001 From: raararaara Date: Wed, 10 Jan 2024 16:51:42 +0900 Subject: [PATCH 7/9] Use types.ID to identify --- server/backend/database/database.go | 2 +- server/backend/database/memory/database.go | 6 +++--- server/rpc/interceptors/admin_auth.go | 2 +- server/users/users.go | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/server/backend/database/database.go b/server/backend/database/database.go index 24dba1091..d04a7ecc3 100644 --- a/server/backend/database/database.go +++ b/server/backend/database/database.go @@ -125,7 +125,7 @@ type Database interface { FindUserInfo(ctx context.Context, username string) (*UserInfo, error) // FindUserInfoByID finds a user by the given id. - FindUserInfoByID(ctx context.Context, id string) (*UserInfo, error) + FindUserInfoByID(ctx context.Context, id types.ID) (*UserInfo, error) // ListUserInfos returns all users. ListUserInfos(ctx context.Context) ([]*UserInfo, error) diff --git a/server/backend/database/memory/database.go b/server/backend/database/memory/database.go index d05857eef..a8497268d 100644 --- a/server/backend/database/memory/database.go +++ b/server/backend/database/memory/database.go @@ -399,16 +399,16 @@ func (d *DB) FindUserInfo(_ context.Context, username string) (*database.UserInf } // FindUserInfoByID finds a user by the given ID. -func (d *DB) FindUserInfoByID(_ context.Context, id string) (*database.UserInfo, error) { +func (d *DB) FindUserInfoByID(_ context.Context, clientID types.ID) (*database.UserInfo, error) { txn := d.db.Txn(false) defer txn.Abort() - raw, err := txn.First(tblUsers, "id", id) + raw, err := txn.First(tblUsers, "id", clientID.String()) if err != nil { return nil, fmt.Errorf("find user by id: %w", err) } if raw == nil { - return nil, fmt.Errorf("%s: %w", id, database.ErrUserNotFound) + return nil, fmt.Errorf("%s: %w", clientID, database.ErrUserNotFound) } return raw.(*database.UserInfo).DeepCopy(), nil diff --git a/server/rpc/interceptors/admin_auth.go b/server/rpc/interceptors/admin_auth.go index ed9c6483a..f46d6cf39 100644 --- a/server/rpc/interceptors/admin_auth.go +++ b/server/rpc/interceptors/admin_auth.go @@ -174,7 +174,7 @@ func (i *AdminAuthInterceptor) authenticate( // NOTE(raararaara): If the token is secret key, return the owner of the project. project, err := projects.GetProjectFromSecretKey(ctx, i.backend, authorization) if err == nil { - user, err := users.GetUserByID(ctx, i.backend, project.Owner.String()) + user, err := users.GetUserByID(ctx, i.backend, project.Owner) if err == nil { return user, nil } diff --git a/server/users/users.go b/server/users/users.go index 0ff99b19d..9f4019b43 100644 --- a/server/users/users.go +++ b/server/users/users.go @@ -86,7 +86,7 @@ func GetUser( func GetUserByID( ctx context.Context, be *backend.Backend, - id string, + id types.ID, ) (*types.User, error) { info, err := be.DB.FindUserInfoByID(ctx, id) if err != nil { From 6c2c9ee4d65990f9e97c304877a5566c62370115 Mon Sep 17 00:00:00 2001 From: raararaara Date: Wed, 10 Jan 2024 17:31:57 +0900 Subject: [PATCH 8/9] Add encodeID for mongo and add FindUserInfoByID test --- .../backend/database/memory/database_test.go | 4 ++ server/backend/database/mongo/client.go | 39 +++++++++++-------- server/backend/database/mongo/client_test.go | 4 ++ .../backend/database/testcases/testcases.go | 18 +++++++++ 4 files changed, 48 insertions(+), 17 deletions(-) diff --git a/server/backend/database/memory/database_test.go b/server/backend/database/memory/database_test.go index 1f691b693..2e247fcff 100644 --- a/server/backend/database/memory/database_test.go +++ b/server/backend/database/memory/database_test.go @@ -56,6 +56,10 @@ func TestDB(t *testing.T) { testcases.RunListUserInfosTest(t, db) }) + t.Run("FindUserInfoByID test", func(t *testing.T) { + testcases.RunFindUserInfoByIDTest(t, db) + }) + t.Run("FindProjectInfoBySecretKey test", func(t *testing.T) { testcases.RunFindProjectInfoBySecretKeyTest(t, db) }) diff --git a/server/backend/database/mongo/client.go b/server/backend/database/mongo/client.go index 64b3eb18a..602281419 100644 --- a/server/backend/database/mongo/client.go +++ b/server/backend/database/mongo/client.go @@ -468,23 +468,6 @@ func (c *Client) FindUserInfo(ctx context.Context, username string) (*database.U return &userInfo, nil } -// FindUserInfoByID returns a user by ID. -func (c *Client) FindUserInfoByID(ctx context.Context, id string) (*database.UserInfo, error) { - result := c.collection(colUsers).FindOne(ctx, bson.M{ - "_id": id, - }) - - userInfo := database.UserInfo{} - if err := result.Decode(&userInfo); err != nil { - if err == mongo.ErrNoDocuments { - return nil, fmt.Errorf("%s: %w", id, database.ErrUserNotFound) - } - return nil, fmt.Errorf("decode user info: %w", err) - } - - return &userInfo, nil -} - // ListUserInfos returns all users. func (c *Client) ListUserInfos( ctx context.Context, @@ -502,6 +485,28 @@ func (c *Client) ListUserInfos( return infos, nil } +// FindUserInfoByID returns a user by ID. +func (c *Client) FindUserInfoByID(ctx context.Context, clientID types.ID) (*database.UserInfo, error) { + encodedClientID, err := encodeID(clientID) + if err != nil { + return nil, err + } + + result := c.collection(colUsers).FindOne(ctx, bson.M{ + "_id": encodedClientID, + }) + + userInfo := database.UserInfo{} + if err := result.Decode(&userInfo); err != nil { + if err == mongo.ErrNoDocuments { + return nil, fmt.Errorf("%s: %w", clientID, database.ErrUserNotFound) + } + return nil, fmt.Errorf("decode user info: %w", err) + } + + return &userInfo, nil +} + // ActivateClient activates the client of the given key. func (c *Client) ActivateClient(ctx context.Context, projectID types.ID, key string) (*database.ClientInfo, error) { encodedProjectID, err := encodeID(projectID) diff --git a/server/backend/database/mongo/client_test.go b/server/backend/database/mongo/client_test.go index 627f1c4f2..6b5ff9466 100644 --- a/server/backend/database/mongo/client_test.go +++ b/server/backend/database/mongo/client_test.go @@ -73,6 +73,10 @@ func TestClient(t *testing.T) { testcases.RunListUserInfosTest(t, cli) }) + t.Run("FindUserInfoByID test", func(t *testing.T) { + testcases.RunFindUserInfoByIDTest(t, cli) + }) + t.Run("FindProjectInfoBySecretKey test", func(t *testing.T) { testcases.RunFindProjectInfoBySecretKeyTest(t, cli) }) diff --git a/server/backend/database/testcases/testcases.go b/server/backend/database/testcases/testcases.go index 23772ad61..ea7cb00e7 100644 --- a/server/backend/database/testcases/testcases.go +++ b/server/backend/database/testcases/testcases.go @@ -295,6 +295,24 @@ func RunListUserInfosTest(t *testing.T, db database.Database) { }) } +// RunFindUserInfoByIDTest runs the FindUserInfoByID test for the given db. +func RunFindUserInfoByIDTest(t *testing.T, db database.Database) { + t.Run("RunFindUserInfoByID test", func(t *testing.T) { + ctx := context.Background() + + username := "findUserInfoTestAccount" + password := "temporary-password" + + user, _, err := db.EnsureDefaultUserAndProject(ctx, username, password, clientDeactivateThreshold) + assert.NoError(t, err) + + info1, err := db.FindUserInfoByID(ctx, user.ID) + assert.NoError(t, err) + + assert.Equal(t, user.ID, info1.ID) + }) +} + // RunActivateClientDeactivateClientTest runs the ActivateClient and DeactivateClient tests for the given db. func RunActivateClientDeactivateClientTest(t *testing.T, db database.Database, projectID types.ID) { t.Run("activate and find client test", func(t *testing.T) { From b3a93275abf0d17c6ad65ff3f6f7bee7e5b93d7c Mon Sep 17 00:00:00 2001 From: Youngteac Hong Date: Fri, 12 Jan 2024 18:19:46 +0900 Subject: [PATCH 9/9] Remove returning default project and add comment --- server/projects/projects.go | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/server/projects/projects.go b/server/projects/projects.go index 229e9d387..956ced116 100644 --- a/server/projects/projects.go +++ b/server/projects/projects.go @@ -92,6 +92,7 @@ func UpdateProject( // GetProjectFromAPIKey returns a project from an API key. func GetProjectFromAPIKey(ctx context.Context, be *backend.Backend, apiKey string) (*types.Project, error) { + // TODO(hackerwins): Default project without API key should be allowed only in standalone mode. if apiKey == "" { info, err := be.DB.FindProjectInfoByID(ctx, database.DefaultProjectID) if err != nil { @@ -110,14 +111,6 @@ func GetProjectFromAPIKey(ctx context.Context, be *backend.Backend, apiKey strin // GetProjectFromSecretKey returns a project from a secret key. func GetProjectFromSecretKey(ctx context.Context, be *backend.Backend, secretKey string) (*types.Project, error) { - if secretKey == "" { - info, err := be.DB.FindProjectInfoByID(ctx, database.DefaultProjectID) - if err != nil { - return nil, err - } - return info.ToProject(), nil - } - info, err := be.DB.FindProjectInfoBySecretKey(ctx, secretKey) if err != nil { return nil, err