Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 520b3ef

Browse files
committed
Add migrations to prevent deleted users with links
1 parent bad125a commit 520b3ef

File tree

4 files changed

+52
-16
lines changed

4 files changed

+52
-16
lines changed

coderd/database/dbmem/dbmem.go

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5534,10 +5534,26 @@ func (q *FakeQuerier) InsertUserGroupsByName(_ context.Context, arg database.Ins
55345534
return nil
55355535
}
55365536

5537+
// Took the error from the real database.
5538+
var deletedUserLinkError = &pq.Error{
5539+
Severity: "ERROR",
5540+
// "raise_exception" error
5541+
Code: "P0001",
5542+
Message: "Cannot create user_link for deleted user",
5543+
Where: "PL/pgSQL function insert_user_links_fail_if_user_deleted() line 7 at RAISE",
5544+
File: "pl_exec.c",
5545+
Line: "3864",
5546+
Routine: "exec_stmt_raise",
5547+
}
5548+
55375549
func (q *FakeQuerier) InsertUserLink(_ context.Context, args database.InsertUserLinkParams) (database.UserLink, error) {
55385550
q.mutex.Lock()
55395551
defer q.mutex.Unlock()
55405552

5553+
if u, err := q.getUserByIDNoLock(args.UserID); err == nil && u.Deleted {
5554+
return database.UserLink{}, deletedUserLinkError
5555+
}
5556+
55415557
//nolint:gosimple
55425558
link := database.UserLink{
55435559
UserID: args.UserID,
@@ -6682,20 +6698,15 @@ func (q *FakeQuerier) UpdateUserDeletedByID(_ context.Context, params database.U
66826698
if u.ID == params.ID {
66836699
u.Deleted = params.Deleted
66846700
q.users[i] = u
6685-
// NOTE: In the real world, this is done by a trigger.
6686-
i := 0
6687-
for {
6688-
if i >= len(q.apiKeys) {
6689-
break
6690-
}
6691-
k := q.apiKeys[i]
6692-
if k.UserID == u.ID {
6693-
q.apiKeys[i] = q.apiKeys[len(q.apiKeys)-1]
6694-
q.apiKeys = q.apiKeys[:len(q.apiKeys)-1]
6695-
// We removed an element, so decrement
6696-
i--
6697-
}
6698-
i++
6701+
if params.Deleted {
6702+
// NOTE: In the real world, this is done by a trigger.
6703+
q.apiKeys = slices.DeleteFunc(q.apiKeys, func(u database.APIKey) bool {
6704+
return params.ID == u.UserID
6705+
})
6706+
6707+
q.userLinks = slices.DeleteFunc(q.userLinks, func(u database.UserLink) bool {
6708+
return params.ID == u.UserID
6709+
})
66996710
}
67006711
return nil
67016712
}
@@ -6750,6 +6761,10 @@ func (q *FakeQuerier) UpdateUserLink(_ context.Context, params database.UpdateUs
67506761
q.mutex.Lock()
67516762
defer q.mutex.Unlock()
67526763

6764+
if u, err := q.getUserByIDNoLock(params.UserID); err == nil && u.Deleted {
6765+
return database.UserLink{}, deletedUserLinkError
6766+
}
6767+
67536768
for i, link := range q.userLinks {
67546769
if link.UserID == params.UserID && link.LoginType == params.LoginType {
67556770
link.OAuthAccessToken = params.OAuthAccessToken

coderd/userauth_test.go

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"net/url"
1010
"strings"
1111
"testing"
12+
"time"
1213

1314
"github.com/coreos/go-oidc/v3/oidc"
1415
"github.com/golang-jwt/jwt/v4"
@@ -24,6 +25,7 @@ import (
2425
"github.com/coder/coder/v2/coderd/coderdtest"
2526
"github.com/coder/coder/v2/coderd/coderdtest/oidctest"
2627
"github.com/coder/coder/v2/coderd/database"
28+
"github.com/coder/coder/v2/coderd/database/dbauthz"
2729
"github.com/coder/coder/v2/coderd/database/dbgen"
2830
"github.com/coder/coder/v2/coderd/database/dbtestutil"
2931
"github.com/coder/coder/v2/coderd/promoauth"
@@ -632,7 +634,7 @@ func TestUserOAuth2Github(t *testing.T) {
632634
coderEmail,
633635
}
634636

635-
owner := coderdtest.New(t, &coderdtest.Options{
637+
owner, db := coderdtest.NewWithDatabase(t, &coderdtest.Options{
636638
Auditor: auditor,
637639
GithubOAuth2Config: &coderd.GithubOAuth2Config{
638640
AllowSignups: true,
@@ -655,9 +657,12 @@ func TestUserOAuth2Github(t *testing.T) {
655657
},
656658
},
657659
})
658-
coderdtest.CreateFirstUser(t, owner)
660+
first := coderdtest.CreateFirstUser(t, owner)
659661

660662
ctx := testutil.Context(t, testutil.WaitLong)
663+
ownerUser, err := owner.User(context.Background(), "me")
664+
require.NoError(t, err)
665+
661666
// Create the user, then delete the user, then create again.
662667
// This causes the email change to fail.
663668
client := codersdk.New(owner.URL)
@@ -668,6 +673,22 @@ func TestUserOAuth2Github(t *testing.T) {
668673

669674
err = owner.DeleteUser(ctx, deleted.ID)
670675
require.NoError(t, err)
676+
// Check no user links for the user
677+
links, err := db.GetUserLinksByUserID(dbauthz.As(ctx, coderdtest.AuthzUserSubject(ownerUser, first.OrganizationID)), deleted.ID)
678+
require.NoError(t, err)
679+
require.Empty(t, links)
680+
681+
// Make sure a user_link cannot be created with a deleted user.
682+
_, err = db.InsertUserLink(dbauthz.AsSystemRestricted(ctx), database.InsertUserLinkParams{
683+
UserID: deleted.ID,
684+
LoginType: "github",
685+
LinkedID: "100",
686+
OAuthAccessToken: "random",
687+
OAuthRefreshToken: "random",
688+
OAuthExpiry: time.Now(),
689+
DebugContext: []byte(`{}`),
690+
})
691+
require.ErrorContains(t, err, "Cannot create user_link for deleted user")
671692

672693
// Create the user again.
673694
client, _ = fake.Login(t, client, jwt.MapClaims{})

0 commit comments

Comments
 (0)