Skip to content

Commit f69a629

Browse files
committed
Add OAuth2 provider codes and tokens to database
1 parent 07cccf9 commit f69a629

21 files changed

+1290
-86
lines changed

coderd/database/dbauthz/dbauthz.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -801,13 +801,40 @@ func (q *querier) DeleteOAuth2ProviderAppByID(ctx context.Context, id uuid.UUID)
801801
return q.db.DeleteOAuth2ProviderAppByID(ctx, id)
802802
}
803803

804+
func (q *querier) DeleteOAuth2ProviderAppCodeByID(ctx context.Context, id uuid.UUID) error {
805+
code, err := q.db.GetOAuth2ProviderAppCodeByID(ctx, id)
806+
if err != nil {
807+
return err
808+
}
809+
if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(code.UserID.String())); err != nil {
810+
return err
811+
}
812+
return q.db.DeleteOAuth2ProviderAppCodeByID(ctx, id)
813+
}
814+
815+
func (q *querier) DeleteOAuth2ProviderAppCodesByAppAndUserID(ctx context.Context, arg database.DeleteOAuth2ProviderAppCodesByAppAndUserIDParams) error {
816+
if err := q.authorizeContext(ctx, rbac.ActionDelete,
817+
rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(arg.UserID.String())); err != nil {
818+
return err
819+
}
820+
return q.db.DeleteOAuth2ProviderAppCodesByAppAndUserID(ctx, arg)
821+
}
822+
804823
func (q *querier) DeleteOAuth2ProviderAppSecretByID(ctx context.Context, id uuid.UUID) error {
805824
if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceOAuth2ProviderAppSecret); err != nil {
806825
return err
807826
}
808827
return q.db.DeleteOAuth2ProviderAppSecretByID(ctx, id)
809828
}
810829

830+
func (q *querier) DeleteOAuth2ProviderAppTokensByAppAndUserID(ctx context.Context, arg database.DeleteOAuth2ProviderAppTokensByAppAndUserIDParams) error {
831+
if err := q.authorizeContext(ctx, rbac.ActionDelete,
832+
rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(arg.UserID.String())); err != nil {
833+
return err
834+
}
835+
return q.db.DeleteOAuth2ProviderAppTokensByAppAndUserID(ctx, arg)
836+
}
837+
811838
func (q *querier) DeleteOldProvisionerDaemons(ctx context.Context) error {
812839
if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceSystem); err != nil {
813840
return err
@@ -1175,6 +1202,18 @@ func (q *querier) GetOAuth2ProviderAppByID(ctx context.Context, id uuid.UUID) (d
11751202
return q.db.GetOAuth2ProviderAppByID(ctx, id)
11761203
}
11771204

1205+
func (q *querier) GetOAuth2ProviderAppCodeByAppIDAndSecret(ctx context.Context, arg database.GetOAuth2ProviderAppCodeByAppIDAndSecretParams) (database.OAuth2ProviderAppCode, error) {
1206+
return fetch(q.log, q.auth, q.db.GetOAuth2ProviderAppCodeByAppIDAndSecret)(ctx, arg)
1207+
}
1208+
1209+
func (q *querier) GetOAuth2ProviderAppCodeByID(ctx context.Context, id uuid.UUID) (database.OAuth2ProviderAppCode, error) {
1210+
return fetch(q.log, q.auth, q.db.GetOAuth2ProviderAppCodeByID)(ctx, id)
1211+
}
1212+
1213+
func (q *querier) GetOAuth2ProviderAppSecretByAppIDAndSecret(ctx context.Context, arg database.GetOAuth2ProviderAppSecretByAppIDAndSecretParams) (database.OAuth2ProviderAppSecret, error) {
1214+
return fetch(q.log, q.auth, q.db.GetOAuth2ProviderAppSecretByAppIDAndSecret)(ctx, arg)
1215+
}
1216+
11781217
func (q *querier) GetOAuth2ProviderAppSecretByID(ctx context.Context, id uuid.UUID) (database.OAuth2ProviderAppSecret, error) {
11791218
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceOAuth2ProviderAppSecret); err != nil {
11801219
return database.OAuth2ProviderAppSecret{}, err
@@ -1196,6 +1235,15 @@ func (q *querier) GetOAuth2ProviderApps(ctx context.Context) ([]database.OAuth2P
11961235
return q.db.GetOAuth2ProviderApps(ctx)
11971236
}
11981237

1238+
func (q *querier) GetOAuth2ProviderAppsByUserID(ctx context.Context, userID uuid.UUID) ([]database.GetOAuth2ProviderAppsByUserIDRow, error) {
1239+
// These two authz checks make sure the caller can read all their own tokens.
1240+
if err := q.authorizeContext(ctx, rbac.ActionRead,
1241+
rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(userID.String())); err != nil {
1242+
return []database.GetOAuth2ProviderAppsByUserIDRow{}, err
1243+
}
1244+
return q.db.GetOAuth2ProviderAppsByUserID(ctx, userID)
1245+
}
1246+
11991247
func (q *querier) GetOAuthSigningKey(ctx context.Context) (string, error) {
12001248
if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil {
12011249
return "", err
@@ -2242,13 +2290,32 @@ func (q *querier) InsertOAuth2ProviderApp(ctx context.Context, arg database.Inse
22422290
return q.db.InsertOAuth2ProviderApp(ctx, arg)
22432291
}
22442292

2293+
func (q *querier) InsertOAuth2ProviderAppCode(ctx context.Context, arg database.InsertOAuth2ProviderAppCodeParams) (database.OAuth2ProviderAppCode, error) {
2294+
if err := q.authorizeContext(ctx, rbac.ActionCreate,
2295+
rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(arg.UserID.String())); err != nil {
2296+
return database.OAuth2ProviderAppCode{}, err
2297+
}
2298+
return q.db.InsertOAuth2ProviderAppCode(ctx, arg)
2299+
}
2300+
22452301
func (q *querier) InsertOAuth2ProviderAppSecret(ctx context.Context, arg database.InsertOAuth2ProviderAppSecretParams) (database.OAuth2ProviderAppSecret, error) {
22462302
if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceOAuth2ProviderAppSecret); err != nil {
22472303
return database.OAuth2ProviderAppSecret{}, err
22482304
}
22492305
return q.db.InsertOAuth2ProviderAppSecret(ctx, arg)
22502306
}
22512307

2308+
func (q *querier) InsertOAuth2ProviderAppToken(ctx context.Context, arg database.InsertOAuth2ProviderAppTokenParams) (database.OAuth2ProviderAppToken, error) {
2309+
key, err := q.db.GetAPIKeyByID(ctx, arg.APIKeyID)
2310+
if err != nil {
2311+
return database.OAuth2ProviderAppToken{}, err
2312+
}
2313+
if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(key.UserID.String())); err != nil {
2314+
return database.OAuth2ProviderAppToken{}, err
2315+
}
2316+
return q.db.InsertOAuth2ProviderAppToken(ctx, arg)
2317+
}
2318+
22522319
func (q *querier) InsertOrganization(ctx context.Context, arg database.InsertOrganizationParams) (database.Organization, error) {
22532320
return insert(q.log, q.auth, rbac.ResourceOrganization, q.db.InsertOrganization)(ctx, arg)
22542321
}

coderd/database/dbauthz/dbauthz_test.go

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2316,6 +2316,34 @@ func (s *MethodTestSuite) TestOAuth2ProviderApps() {
23162316
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
23172317
check.Args(app.ID).Asserts(rbac.ResourceOAuth2ProviderApp, rbac.ActionRead).Returns(app)
23182318
}))
2319+
s.Run("GetOAuth2ProviderAppsByUserID", s.Subtest(func(db database.Store, check *expects) {
2320+
user := dbgen.User(s.T(), db, database.User{})
2321+
key, _ := dbgen.APIKey(s.T(), db, database.APIKey{
2322+
UserID: user.ID,
2323+
})
2324+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
2325+
_ = dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
2326+
secret := dbgen.OAuth2ProviderAppSecret(s.T(), db, database.OAuth2ProviderAppSecret{
2327+
AppID: app.ID,
2328+
})
2329+
for i := 0; i < 5; i++ {
2330+
_ = dbgen.OAuth2ProviderAppToken(s.T(), db, database.OAuth2ProviderAppToken{
2331+
AppSecretID: secret.ID,
2332+
APIKeyID: key.ID,
2333+
})
2334+
}
2335+
check.Args(user.ID).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionRead).Returns([]database.GetOAuth2ProviderAppsByUserIDRow{
2336+
{
2337+
OAuth2ProviderApp: database.OAuth2ProviderApp{
2338+
ID: app.ID,
2339+
CallbackURL: app.CallbackURL,
2340+
Icon: app.Icon,
2341+
Name: app.Name,
2342+
},
2343+
TokenCount: 5,
2344+
},
2345+
})
2346+
}))
23192347
s.Run("InsertOAuth2ProviderApp", s.Subtest(func(db database.Store, check *expects) {
23202348
check.Args(database.InsertOAuth2ProviderAppParams{}).Asserts(rbac.ResourceOAuth2ProviderApp, rbac.ActionCreate)
23212349
}))
@@ -2361,6 +2389,16 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppSecrets() {
23612389
})
23622390
check.Args(secret.ID).Asserts(rbac.ResourceOAuth2ProviderAppSecret, rbac.ActionRead).Returns(secret)
23632391
}))
2392+
s.Run("GetOAuth2ProviderAppSecretByAppIDAndSecret", s.Subtest(func(db database.Store, check *expects) {
2393+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
2394+
secret := dbgen.OAuth2ProviderAppSecret(s.T(), db, database.OAuth2ProviderAppSecret{
2395+
AppID: app.ID,
2396+
})
2397+
check.Args(database.GetOAuth2ProviderAppSecretByAppIDAndSecretParams{
2398+
AppID: app.ID,
2399+
HashedSecret: secret.HashedSecret,
2400+
}).Asserts(rbac.ResourceOAuth2ProviderAppSecret, rbac.ActionRead).Returns(secret)
2401+
}))
23642402
s.Run("InsertOAuth2ProviderAppSecret", s.Subtest(func(db database.Store, check *expects) {
23652403
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
23662404
check.Args(database.InsertOAuth2ProviderAppSecretParams{
@@ -2386,3 +2424,95 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppSecrets() {
23862424
check.Args(secret.ID).Asserts(rbac.ResourceOAuth2ProviderAppSecret, rbac.ActionDelete)
23872425
}))
23882426
}
2427+
2428+
func (s *MethodTestSuite) TestOAuth2ProviderAppCodes() {
2429+
s.Run("GetOAuth2ProviderAppCodeByID", s.Subtest(func(db database.Store, check *expects) {
2430+
user := dbgen.User(s.T(), db, database.User{})
2431+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
2432+
code := dbgen.OAuth2ProviderAppCode(s.T(), db, database.OAuth2ProviderAppCode{
2433+
AppID: app.ID,
2434+
UserID: user.ID,
2435+
})
2436+
check.Args(code.ID).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionRead).Returns(code)
2437+
}))
2438+
s.Run("GetOAuth2ProviderAppCodeByAppIDAndSecret", s.Subtest(func(db database.Store, check *expects) {
2439+
user := dbgen.User(s.T(), db, database.User{})
2440+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
2441+
code := dbgen.OAuth2ProviderAppCode(s.T(), db, database.OAuth2ProviderAppCode{
2442+
AppID: app.ID,
2443+
UserID: user.ID,
2444+
})
2445+
check.Args(database.GetOAuth2ProviderAppCodeByAppIDAndSecretParams{
2446+
AppID: app.ID,
2447+
HashedSecret: code.HashedSecret,
2448+
}).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionRead).Returns(code)
2449+
}))
2450+
s.Run("InsertOAuth2ProviderAppCode", s.Subtest(func(db database.Store, check *expects) {
2451+
user := dbgen.User(s.T(), db, database.User{})
2452+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
2453+
check.Args(database.InsertOAuth2ProviderAppCodeParams{
2454+
AppID: app.ID,
2455+
UserID: user.ID,
2456+
}).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionCreate)
2457+
}))
2458+
s.Run("DeleteOAuth2ProviderAppCodeByID", s.Subtest(func(db database.Store, check *expects) {
2459+
user := dbgen.User(s.T(), db, database.User{})
2460+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
2461+
code := dbgen.OAuth2ProviderAppCode(s.T(), db, database.OAuth2ProviderAppCode{
2462+
AppID: app.ID,
2463+
UserID: user.ID,
2464+
})
2465+
check.Args(code.ID).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionDelete)
2466+
}))
2467+
s.Run("DeleteOAuth2ProviderAppCodesByAppAndUserID", s.Subtest(func(db database.Store, check *expects) {
2468+
user := dbgen.User(s.T(), db, database.User{})
2469+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
2470+
for i := 0; i < 5; i++ {
2471+
_ = dbgen.OAuth2ProviderAppCode(s.T(), db, database.OAuth2ProviderAppCode{
2472+
AppID: app.ID,
2473+
UserID: user.ID,
2474+
})
2475+
}
2476+
check.Args(database.DeleteOAuth2ProviderAppCodesByAppAndUserIDParams{
2477+
AppID: app.ID,
2478+
UserID: user.ID,
2479+
}).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionDelete)
2480+
}))
2481+
}
2482+
2483+
func (s *MethodTestSuite) TestOAuth2ProviderAppTokens() {
2484+
s.Run("InsertOAuth2ProviderAppToken", s.Subtest(func(db database.Store, check *expects) {
2485+
user := dbgen.User(s.T(), db, database.User{})
2486+
key, _ := dbgen.APIKey(s.T(), db, database.APIKey{
2487+
UserID: user.ID,
2488+
})
2489+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
2490+
secret := dbgen.OAuth2ProviderAppSecret(s.T(), db, database.OAuth2ProviderAppSecret{
2491+
AppID: app.ID,
2492+
})
2493+
check.Args(database.InsertOAuth2ProviderAppTokenParams{
2494+
AppSecretID: secret.ID,
2495+
APIKeyID: key.ID,
2496+
}).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionCreate)
2497+
}))
2498+
s.Run("DeleteOAuth2ProviderAppTokensByAppAndUserID", s.Subtest(func(db database.Store, check *expects) {
2499+
user := dbgen.User(s.T(), db, database.User{})
2500+
key, _ := dbgen.APIKey(s.T(), db, database.APIKey{
2501+
UserID: user.ID,
2502+
})
2503+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
2504+
secret := dbgen.OAuth2ProviderAppSecret(s.T(), db, database.OAuth2ProviderAppSecret{
2505+
AppID: app.ID,
2506+
})
2507+
for i := 0; i < 5; i++ {
2508+
_ = dbgen.OAuth2ProviderAppToken(s.T(), db, database.OAuth2ProviderAppToken{
2509+
AppSecretID: secret.ID,
2510+
APIKeyID: key.ID,
2511+
})
2512+
}
2513+
check.Args(database.DeleteOAuth2ProviderAppTokensByAppAndUserIDParams{
2514+
AppID: app.ID,
2515+
UserID: user.ID,
2516+
}).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionDelete)
2517+
}))
2518+
}

coderd/database/dbgen/dbgen.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,32 @@ func OAuth2ProviderAppSecret(t testing.TB, db database.Store, seed database.OAut
715715
return app
716716
}
717717

718+
func OAuth2ProviderAppCode(t testing.TB, db database.Store, seed database.OAuth2ProviderAppCode) database.OAuth2ProviderAppCode {
719+
code, err := db.InsertOAuth2ProviderAppCode(genCtx, database.InsertOAuth2ProviderAppCodeParams{
720+
ID: takeFirst(seed.ID, uuid.New()),
721+
CreatedAt: takeFirst(seed.CreatedAt, dbtime.Now()),
722+
ExpiresAt: takeFirst(seed.CreatedAt, dbtime.Now()),
723+
HashedSecret: takeFirstSlice(seed.HashedSecret, []byte("hashed-secret")),
724+
AppID: takeFirst(seed.AppID, uuid.New()),
725+
UserID: takeFirst(seed.UserID, uuid.New()),
726+
})
727+
require.NoError(t, err, "insert oauth2 app code")
728+
return code
729+
}
730+
731+
func OAuth2ProviderAppToken(t testing.TB, db database.Store, seed database.OAuth2ProviderAppToken) database.OAuth2ProviderAppToken {
732+
token, err := db.InsertOAuth2ProviderAppToken(genCtx, database.InsertOAuth2ProviderAppTokenParams{
733+
ID: takeFirst(seed.ID, uuid.New()),
734+
CreatedAt: takeFirst(seed.CreatedAt, dbtime.Now()),
735+
ExpiresAt: takeFirst(seed.CreatedAt, dbtime.Now()),
736+
HashedSecret: takeFirstSlice(seed.HashedSecret, []byte("hashed-secret")),
737+
AppSecretID: takeFirst(seed.AppSecretID, uuid.New()),
738+
APIKeyID: takeFirst(seed.APIKeyID, uuid.New().String()),
739+
})
740+
require.NoError(t, err, "insert oauth2 app token")
741+
return token
742+
}
743+
718744
func must[V any](v V, err error) V {
719745
if err != nil {
720746
panic(err)

0 commit comments

Comments
 (0)