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

Skip to content

fix: use unique ID for linked accounts #3441

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 35 commits into from
Aug 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
305f696
fix: use unique ID for linked accounts
sreya Aug 9, 2022
b4ab301
fixup a bunch of stuff
sreya Aug 9, 2022
dd2df9c
gofmt
sreya Aug 9, 2022
0356f46
make fake db happy
sreya Aug 9, 2022
6b1b900
make audit happy
sreya Aug 9, 2022
8f63d5c
fix some tests
sreya Aug 10, 2022
de7db33
make gen
sreya Aug 10, 2022
5fdf899
fix tests
sreya Aug 10, 2022
3a4d049
fmt
sreya Aug 10, 2022
4108ece
begin refactoring PR
sreya Aug 11, 2022
14b5382
finish migration
sreya Aug 12, 2022
8553501
use main sql.dump
sreya Aug 12, 2022
f748d3d
lift error
sreya Aug 12, 2022
c1b9871
new migration
sreya Aug 12, 2022
e41c103
more rewriting
sreya Aug 12, 2022
bb9b777
even more rewriting
sreya Aug 12, 2022
d940dae
finish up some test fixing
sreya Aug 12, 2022
c97d572
typos
sreya Aug 12, 2022
10bfe77
Merge branch 'main' into jon/userauth
sreya Aug 12, 2022
28a37f1
fix some remaining tests
sreya Aug 12, 2022
c889bf0
fix a gnarly bug
sreya Aug 12, 2022
0196a49
add a down migration
sreya Aug 12, 2022
b5dc95b
add fkey on user_links, fix tests, add comments
sreya Aug 12, 2022
f2f76e9
add login_type to users table
sreya Aug 12, 2022
940ced4
Merge branch 'main' into jon/userauth
sreya Aug 12, 2022
eb266db
fix login_type query
sreya Aug 13, 2022
4671bf6
fix tests
sreya Aug 13, 2022
c41f4e6
fix audit
sreya Aug 13, 2022
f3d8392
fix down
sreya Aug 13, 2022
cc8400b
fix one more test
sreya Aug 13, 2022
5c7cbae
Merge branch 'main' into jon/userauth
sreya Aug 17, 2022
083d256
pr comments
sreya Aug 17, 2022
92c185d
fix conflicting migration file
sreya Aug 17, 2022
05595d8
generate.sh
sreya Aug 17, 2022
aa90148
butcher the english language to appease colin
sreya Aug 17, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions coderd/audit/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ var AuditableResources = auditMap(map[any]map[string]Action{
"updated_at": ActionIgnore, // Changes, but is implicit and not helpful in a diff.
"status": ActionTrack,
"rbac_roles": ActionTrack,
"login_type": ActionIgnore,
},
&database.Workspace{}: {
"id": ActionTrack,
Expand Down
106 changes: 89 additions & 17 deletions coderd/database/databasefake/databasefake.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ type data struct {
organizations []database.Organization
organizationMembers []database.OrganizationMember
users []database.User
userLinks []database.UserLink

// New tables
auditLogs []database.AuditLog
Expand Down Expand Up @@ -1453,20 +1454,16 @@ func (q *fakeQuerier) InsertAPIKey(_ context.Context, arg database.InsertAPIKeyP

//nolint:gosimple
key := database.APIKey{
ID: arg.ID,
LifetimeSeconds: arg.LifetimeSeconds,
HashedSecret: arg.HashedSecret,
IPAddress: arg.IPAddress,
UserID: arg.UserID,
ExpiresAt: arg.ExpiresAt,
CreatedAt: arg.CreatedAt,
UpdatedAt: arg.UpdatedAt,
LastUsed: arg.LastUsed,
LoginType: arg.LoginType,
OAuthAccessToken: arg.OAuthAccessToken,
OAuthRefreshToken: arg.OAuthRefreshToken,
OAuthIDToken: arg.OAuthIDToken,
OAuthExpiry: arg.OAuthExpiry,
ID: arg.ID,
LifetimeSeconds: arg.LifetimeSeconds,
HashedSecret: arg.HashedSecret,
IPAddress: arg.IPAddress,
UserID: arg.UserID,
ExpiresAt: arg.ExpiresAt,
CreatedAt: arg.CreatedAt,
UpdatedAt: arg.UpdatedAt,
LastUsed: arg.LastUsed,
LoginType: arg.LoginType,
}
q.apiKeys = append(q.apiKeys, key)
return key, nil
Expand Down Expand Up @@ -1743,6 +1740,7 @@ func (q *fakeQuerier) InsertUser(_ context.Context, arg database.InsertUserParam
Username: arg.Username,
Status: database.UserStatusActive,
RBACRoles: arg.RBACRoles,
LoginType: arg.LoginType,
}
q.users = append(q.users, user)
return user, nil
Expand Down Expand Up @@ -1898,9 +1896,6 @@ func (q *fakeQuerier) UpdateAPIKeyByID(_ context.Context, arg database.UpdateAPI
apiKey.LastUsed = arg.LastUsed
apiKey.ExpiresAt = arg.ExpiresAt
apiKey.IPAddress = arg.IPAddress
apiKey.OAuthAccessToken = arg.OAuthAccessToken
apiKey.OAuthRefreshToken = arg.OAuthRefreshToken
apiKey.OAuthExpiry = arg.OAuthExpiry
q.apiKeys[index] = apiKey
return nil
}
Expand Down Expand Up @@ -2259,3 +2254,80 @@ func (q *fakeQuerier) GetDeploymentID(_ context.Context) (string, error) {

return q.deploymentID, nil
}

func (q *fakeQuerier) GetUserLinkByLinkedID(_ context.Context, id string) (database.UserLink, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()

for _, link := range q.userLinks {
if link.LinkedID == id {
return link, nil
}
}
return database.UserLink{}, sql.ErrNoRows
}

func (q *fakeQuerier) GetUserLinkByUserIDLoginType(_ context.Context, params database.GetUserLinkByUserIDLoginTypeParams) (database.UserLink, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()

for _, link := range q.userLinks {
if link.UserID == params.UserID && link.LoginType == params.LoginType {
return link, nil
}
}
return database.UserLink{}, sql.ErrNoRows
}

func (q *fakeQuerier) InsertUserLink(_ context.Context, args database.InsertUserLinkParams) (database.UserLink, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()

//nolint:gosimple
link := database.UserLink{
UserID: args.UserID,
LoginType: args.LoginType,
LinkedID: args.LinkedID,
OAuthAccessToken: args.OAuthAccessToken,
OAuthRefreshToken: args.OAuthRefreshToken,
OAuthExpiry: args.OAuthExpiry,
}

q.userLinks = append(q.userLinks, link)

return link, nil
}

func (q *fakeQuerier) UpdateUserLinkedID(_ context.Context, params database.UpdateUserLinkedIDParams) (database.UserLink, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()

for i, link := range q.userLinks {
if link.UserID == params.UserID && link.LoginType == params.LoginType {
link.LinkedID = params.LinkedID

q.userLinks[i] = link
return link, nil
}
}

return database.UserLink{}, sql.ErrNoRows
}

func (q *fakeQuerier) UpdateUserLink(_ context.Context, params database.UpdateUserLinkParams) (database.UserLink, error) {
q.mutex.RLock()
defer q.mutex.RUnlock()

for i, link := range q.userLinks {
if link.UserID == params.UserID && link.LoginType == params.LoginType {
link.OAuthAccessToken = params.OAuthAccessToken
link.OAuthRefreshToken = params.OAuthRefreshToken
link.OAuthExpiry = params.OAuthExpiry

q.userLinks[i] = link
return link, nil
}
}

return database.UserLink{}, sql.ErrNoRows
}
1 change: 1 addition & 0 deletions coderd/database/db_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func TestNestedInTx(t *testing.T) {
CreatedAt: database.Now(),
UpdatedAt: database.Now(),
RBACRoles: []string{},
LoginType: database.LoginTypeGithub,
})
return err
})
Expand Down
22 changes: 17 additions & 5 deletions coderd/database/dump.sql

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions coderd/database/generate.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ SCRIPT_DIR=$(dirname "${BASH_SOURCE[0]}")
(
cd "$SCRIPT_DIR"

# Dump the updated schema.
go run dump/main.go
# The logic below depends on the exact version being correct :(
go run github.com/kyleconroy/sqlc/cmd/[email protected] generate

Expand Down
23 changes: 23 additions & 0 deletions coderd/database/migrations/000035_linked_user_id.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
-- This migration makes no attempt to try to populate
-- the oauth_access_token, oauth_refresh_token, and oauth_expiry
-- columns of api_key rows with the values from the dropped user_links
-- table.
BEGIN;

DROP TABLE IF EXISTS user_links;

ALTER TABLE
api_keys
ADD COLUMN oauth_access_token text DEFAULT ''::text NOT NULL;

ALTER TABLE
api_keys
ADD COLUMN oauth_refresh_token text DEFAULT ''::text NOT NULL;

ALTER TABLE
api_keys
ADD COLUMN oauth_expiry timestamp with time zone DEFAULT '0001-01-01 00:00:00+00'::timestamp with time zone NOT NULL;

ALTER TABLE users DROP COLUMN login_type;

COMMIT;
74 changes: 74 additions & 0 deletions coderd/database/migrations/000035_linked_user_id.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
BEGIN;

CREATE TABLE IF NOT EXISTS user_links (
user_id uuid NOT NULL,
login_type login_type NOT NULL,
linked_id text DEFAULT ''::text NOT NULL,
oauth_access_token text DEFAULT ''::text NOT NULL,
oauth_refresh_token text DEFAULT ''::text NOT NULL,
oauth_expiry timestamp with time zone DEFAULT '0001-01-01 00:00:00+00'::timestamp with time zone NOT NULL,
PRIMARY KEY(user_id, login_type),
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

-- This migrates columns on api_keys to the new user_links table.
-- It does this by finding all the API keys for each user, choosing
-- the most recently updated for each one and then assigning its relevant
-- values to the user_links table.
-- A user should at most have a row for an OIDC account and a Github account.
-- 'password' login types are ignored.

INSERT INTO user_links
(
user_id,
login_type,
linked_id,
oauth_access_token,
oauth_refresh_token,
oauth_expiry
)
SELECT
keys.user_id,
keys.login_type,
'',
keys.oauth_access_token,
keys.oauth_refresh_token,
keys.oauth_expiry
FROM
(
SELECT
row_number() OVER (partition by user_id, login_type ORDER BY last_used DESC) AS x,
api_keys.* FROM api_keys
) as keys
WHERE x=1 AND keys.login_type != 'password';

-- Drop columns that have been migrated to user_links.
-- It appears the 'oauth_id_token' was unused and so it has
-- been dropped here as well to avoid future confusion.
ALTER TABLE api_keys
DROP COLUMN oauth_access_token,
DROP COLUMN oauth_refresh_token,
DROP COLUMN oauth_id_token,
DROP COLUMN oauth_expiry;

ALTER TABLE users ADD COLUMN login_type login_type NOT NULL DEFAULT 'password';

UPDATE
users
SET
login_type = (
SELECT
login_type
FROM
user_links
WHERE
user_links.user_id = users.id
ORDER BY oauth_expiry DESC
LIMIT 1
)
FROM
user_links
WHERE
user_links.user_id = users.id;

COMMIT;
34 changes: 20 additions & 14 deletions coderd/database/models.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions coderd/database/querier.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading