Skip to content

Commit d54e56a

Browse files
committed
Add OAuth2 provider codes and tokens to database
1 parent e828dab commit d54e56a

21 files changed

+1287
-82
lines changed

coderd/database/dbauthz/dbauthz.go

+67
Original file line numberDiff line numberDiff line change
@@ -821,13 +821,40 @@ func (q *querier) DeleteOAuth2ProviderAppByID(ctx context.Context, id uuid.UUID)
821821
return q.db.DeleteOAuth2ProviderAppByID(ctx, id)
822822
}
823823

824+
func (q *querier) DeleteOAuth2ProviderAppCodeByID(ctx context.Context, id uuid.UUID) error {
825+
code, err := q.db.GetOAuth2ProviderAppCodeByID(ctx, id)
826+
if err != nil {
827+
return err
828+
}
829+
if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(code.UserID.String())); err != nil {
830+
return err
831+
}
832+
return q.db.DeleteOAuth2ProviderAppCodeByID(ctx, id)
833+
}
834+
835+
func (q *querier) DeleteOAuth2ProviderAppCodesByAppAndUserID(ctx context.Context, arg database.DeleteOAuth2ProviderAppCodesByAppAndUserIDParams) error {
836+
if err := q.authorizeContext(ctx, rbac.ActionDelete,
837+
rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(arg.UserID.String())); err != nil {
838+
return err
839+
}
840+
return q.db.DeleteOAuth2ProviderAppCodesByAppAndUserID(ctx, arg)
841+
}
842+
824843
func (q *querier) DeleteOAuth2ProviderAppSecretByID(ctx context.Context, id uuid.UUID) error {
825844
if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceOAuth2ProviderAppSecret); err != nil {
826845
return err
827846
}
828847
return q.db.DeleteOAuth2ProviderAppSecretByID(ctx, id)
829848
}
830849

850+
func (q *querier) DeleteOAuth2ProviderAppTokensByAppAndUserID(ctx context.Context, arg database.DeleteOAuth2ProviderAppTokensByAppAndUserIDParams) error {
851+
if err := q.authorizeContext(ctx, rbac.ActionDelete,
852+
rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(arg.UserID.String())); err != nil {
853+
return err
854+
}
855+
return q.db.DeleteOAuth2ProviderAppTokensByAppAndUserID(ctx, arg)
856+
}
857+
831858
func (q *querier) DeleteOldProvisionerDaemons(ctx context.Context) error {
832859
if err := q.authorizeContext(ctx, rbac.ActionDelete, rbac.ResourceSystem); err != nil {
833860
return err
@@ -1161,6 +1188,18 @@ func (q *querier) GetOAuth2ProviderAppByID(ctx context.Context, id uuid.UUID) (d
11611188
return q.db.GetOAuth2ProviderAppByID(ctx, id)
11621189
}
11631190

1191+
func (q *querier) GetOAuth2ProviderAppCodeByAppIDAndSecret(ctx context.Context, arg database.GetOAuth2ProviderAppCodeByAppIDAndSecretParams) (database.OAuth2ProviderAppCode, error) {
1192+
return fetch(q.log, q.auth, q.db.GetOAuth2ProviderAppCodeByAppIDAndSecret)(ctx, arg)
1193+
}
1194+
1195+
func (q *querier) GetOAuth2ProviderAppCodeByID(ctx context.Context, id uuid.UUID) (database.OAuth2ProviderAppCode, error) {
1196+
return fetch(q.log, q.auth, q.db.GetOAuth2ProviderAppCodeByID)(ctx, id)
1197+
}
1198+
1199+
func (q *querier) GetOAuth2ProviderAppSecretByAppIDAndSecret(ctx context.Context, arg database.GetOAuth2ProviderAppSecretByAppIDAndSecretParams) (database.OAuth2ProviderAppSecret, error) {
1200+
return fetch(q.log, q.auth, q.db.GetOAuth2ProviderAppSecretByAppIDAndSecret)(ctx, arg)
1201+
}
1202+
11641203
func (q *querier) GetOAuth2ProviderAppSecretByID(ctx context.Context, id uuid.UUID) (database.OAuth2ProviderAppSecret, error) {
11651204
if err := q.authorizeContext(ctx, rbac.ActionRead, rbac.ResourceOAuth2ProviderAppSecret); err != nil {
11661205
return database.OAuth2ProviderAppSecret{}, err
@@ -1182,6 +1221,15 @@ func (q *querier) GetOAuth2ProviderApps(ctx context.Context) ([]database.OAuth2P
11821221
return q.db.GetOAuth2ProviderApps(ctx)
11831222
}
11841223

1224+
func (q *querier) GetOAuth2ProviderAppsByUserID(ctx context.Context, userID uuid.UUID) ([]database.GetOAuth2ProviderAppsByUserIDRow, error) {
1225+
// These two authz checks make sure the caller can read all their own tokens.
1226+
if err := q.authorizeContext(ctx, rbac.ActionRead,
1227+
rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(userID.String())); err != nil {
1228+
return []database.GetOAuth2ProviderAppsByUserIDRow{}, err
1229+
}
1230+
return q.db.GetOAuth2ProviderAppsByUserID(ctx, userID)
1231+
}
1232+
11851233
func (q *querier) GetOAuthSigningKey(ctx context.Context) (string, error) {
11861234
if err := q.authorizeContext(ctx, rbac.ActionUpdate, rbac.ResourceSystem); err != nil {
11871235
return "", err
@@ -2203,13 +2251,32 @@ func (q *querier) InsertOAuth2ProviderApp(ctx context.Context, arg database.Inse
22032251
return q.db.InsertOAuth2ProviderApp(ctx, arg)
22042252
}
22052253

2254+
func (q *querier) InsertOAuth2ProviderAppCode(ctx context.Context, arg database.InsertOAuth2ProviderAppCodeParams) (database.OAuth2ProviderAppCode, error) {
2255+
if err := q.authorizeContext(ctx, rbac.ActionCreate,
2256+
rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(arg.UserID.String())); err != nil {
2257+
return database.OAuth2ProviderAppCode{}, err
2258+
}
2259+
return q.db.InsertOAuth2ProviderAppCode(ctx, arg)
2260+
}
2261+
22062262
func (q *querier) InsertOAuth2ProviderAppSecret(ctx context.Context, arg database.InsertOAuth2ProviderAppSecretParams) (database.OAuth2ProviderAppSecret, error) {
22072263
if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceOAuth2ProviderAppSecret); err != nil {
22082264
return database.OAuth2ProviderAppSecret{}, err
22092265
}
22102266
return q.db.InsertOAuth2ProviderAppSecret(ctx, arg)
22112267
}
22122268

2269+
func (q *querier) InsertOAuth2ProviderAppToken(ctx context.Context, arg database.InsertOAuth2ProviderAppTokenParams) (database.OAuth2ProviderAppToken, error) {
2270+
key, err := q.db.GetAPIKeyByID(ctx, arg.APIKeyID)
2271+
if err != nil {
2272+
return database.OAuth2ProviderAppToken{}, err
2273+
}
2274+
if err := q.authorizeContext(ctx, rbac.ActionCreate, rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(key.UserID.String())); err != nil {
2275+
return database.OAuth2ProviderAppToken{}, err
2276+
}
2277+
return q.db.InsertOAuth2ProviderAppToken(ctx, arg)
2278+
}
2279+
22132280
func (q *querier) InsertOrganization(ctx context.Context, arg database.InsertOrganizationParams) (database.Organization, error) {
22142281
return insert(q.log, q.auth, rbac.ResourceOrganization, q.db.InsertOrganization)(ctx, arg)
22152282
}

coderd/database/dbauthz/dbauthz_test.go

+130
Original file line numberDiff line numberDiff line change
@@ -2220,6 +2220,34 @@ func (s *MethodTestSuite) TestOAuth2ProviderApps() {
22202220
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
22212221
check.Args(app.ID).Asserts(rbac.ResourceOAuth2ProviderApp, rbac.ActionRead).Returns(app)
22222222
}))
2223+
s.Run("GetOAuth2ProviderAppsByUserID", s.Subtest(func(db database.Store, check *expects) {
2224+
user := dbgen.User(s.T(), db, database.User{})
2225+
key, _ := dbgen.APIKey(s.T(), db, database.APIKey{
2226+
UserID: user.ID,
2227+
})
2228+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
2229+
_ = dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
2230+
secret := dbgen.OAuth2ProviderAppSecret(s.T(), db, database.OAuth2ProviderAppSecret{
2231+
AppID: app.ID,
2232+
})
2233+
for i := 0; i < 5; i++ {
2234+
_ = dbgen.OAuth2ProviderAppToken(s.T(), db, database.OAuth2ProviderAppToken{
2235+
AppSecretID: secret.ID,
2236+
APIKeyID: key.ID,
2237+
})
2238+
}
2239+
check.Args(user.ID).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionRead).Returns([]database.GetOAuth2ProviderAppsByUserIDRow{
2240+
{
2241+
OAuth2ProviderApp: database.OAuth2ProviderApp{
2242+
ID: app.ID,
2243+
CallbackURL: app.CallbackURL,
2244+
Icon: app.Icon,
2245+
Name: app.Name,
2246+
},
2247+
TokenCount: 5,
2248+
},
2249+
})
2250+
}))
22232251
s.Run("InsertOAuth2ProviderApp", s.Subtest(func(db database.Store, check *expects) {
22242252
check.Args(database.InsertOAuth2ProviderAppParams{}).Asserts(rbac.ResourceOAuth2ProviderApp, rbac.ActionCreate)
22252253
}))
@@ -2265,6 +2293,16 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppSecrets() {
22652293
})
22662294
check.Args(secret.ID).Asserts(rbac.ResourceOAuth2ProviderAppSecret, rbac.ActionRead).Returns(secret)
22672295
}))
2296+
s.Run("GetOAuth2ProviderAppSecretByAppIDAndSecret", s.Subtest(func(db database.Store, check *expects) {
2297+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
2298+
secret := dbgen.OAuth2ProviderAppSecret(s.T(), db, database.OAuth2ProviderAppSecret{
2299+
AppID: app.ID,
2300+
})
2301+
check.Args(database.GetOAuth2ProviderAppSecretByAppIDAndSecretParams{
2302+
AppID: app.ID,
2303+
HashedSecret: secret.HashedSecret,
2304+
}).Asserts(rbac.ResourceOAuth2ProviderAppSecret, rbac.ActionRead).Returns(secret)
2305+
}))
22682306
s.Run("InsertOAuth2ProviderAppSecret", s.Subtest(func(db database.Store, check *expects) {
22692307
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
22702308
check.Args(database.InsertOAuth2ProviderAppSecretParams{
@@ -2290,3 +2328,95 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppSecrets() {
22902328
check.Args(secret.ID).Asserts(rbac.ResourceOAuth2ProviderAppSecret, rbac.ActionDelete)
22912329
}))
22922330
}
2331+
2332+
func (s *MethodTestSuite) TestOAuth2ProviderAppCodes() {
2333+
s.Run("GetOAuth2ProviderAppCodeByID", s.Subtest(func(db database.Store, check *expects) {
2334+
user := dbgen.User(s.T(), db, database.User{})
2335+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
2336+
code := dbgen.OAuth2ProviderAppCode(s.T(), db, database.OAuth2ProviderAppCode{
2337+
AppID: app.ID,
2338+
UserID: user.ID,
2339+
})
2340+
check.Args(code.ID).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionRead).Returns(code)
2341+
}))
2342+
s.Run("GetOAuth2ProviderAppCodeByAppIDAndSecret", s.Subtest(func(db database.Store, check *expects) {
2343+
user := dbgen.User(s.T(), db, database.User{})
2344+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
2345+
code := dbgen.OAuth2ProviderAppCode(s.T(), db, database.OAuth2ProviderAppCode{
2346+
AppID: app.ID,
2347+
UserID: user.ID,
2348+
})
2349+
check.Args(database.GetOAuth2ProviderAppCodeByAppIDAndSecretParams{
2350+
AppID: app.ID,
2351+
HashedSecret: code.HashedSecret,
2352+
}).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionRead).Returns(code)
2353+
}))
2354+
s.Run("InsertOAuth2ProviderAppCode", s.Subtest(func(db database.Store, check *expects) {
2355+
user := dbgen.User(s.T(), db, database.User{})
2356+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
2357+
check.Args(database.InsertOAuth2ProviderAppCodeParams{
2358+
AppID: app.ID,
2359+
UserID: user.ID,
2360+
}).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionCreate)
2361+
}))
2362+
s.Run("DeleteOAuth2ProviderAppCodeByID", s.Subtest(func(db database.Store, check *expects) {
2363+
user := dbgen.User(s.T(), db, database.User{})
2364+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
2365+
code := dbgen.OAuth2ProviderAppCode(s.T(), db, database.OAuth2ProviderAppCode{
2366+
AppID: app.ID,
2367+
UserID: user.ID,
2368+
})
2369+
check.Args(code.ID).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionDelete)
2370+
}))
2371+
s.Run("DeleteOAuth2ProviderAppCodesByAppAndUserID", s.Subtest(func(db database.Store, check *expects) {
2372+
user := dbgen.User(s.T(), db, database.User{})
2373+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
2374+
for i := 0; i < 5; i++ {
2375+
_ = dbgen.OAuth2ProviderAppCode(s.T(), db, database.OAuth2ProviderAppCode{
2376+
AppID: app.ID,
2377+
UserID: user.ID,
2378+
})
2379+
}
2380+
check.Args(database.DeleteOAuth2ProviderAppCodesByAppAndUserIDParams{
2381+
AppID: app.ID,
2382+
UserID: user.ID,
2383+
}).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionDelete)
2384+
}))
2385+
}
2386+
2387+
func (s *MethodTestSuite) TestOAuth2ProviderAppTokens() {
2388+
s.Run("InsertOAuth2ProviderAppToken", s.Subtest(func(db database.Store, check *expects) {
2389+
user := dbgen.User(s.T(), db, database.User{})
2390+
key, _ := dbgen.APIKey(s.T(), db, database.APIKey{
2391+
UserID: user.ID,
2392+
})
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.InsertOAuth2ProviderAppTokenParams{
2398+
AppSecretID: secret.ID,
2399+
APIKeyID: key.ID,
2400+
}).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionCreate)
2401+
}))
2402+
s.Run("DeleteOAuth2ProviderAppTokensByAppAndUserID", s.Subtest(func(db database.Store, check *expects) {
2403+
user := dbgen.User(s.T(), db, database.User{})
2404+
key, _ := dbgen.APIKey(s.T(), db, database.APIKey{
2405+
UserID: user.ID,
2406+
})
2407+
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
2408+
secret := dbgen.OAuth2ProviderAppSecret(s.T(), db, database.OAuth2ProviderAppSecret{
2409+
AppID: app.ID,
2410+
})
2411+
for i := 0; i < 5; i++ {
2412+
_ = dbgen.OAuth2ProviderAppToken(s.T(), db, database.OAuth2ProviderAppToken{
2413+
AppSecretID: secret.ID,
2414+
APIKeyID: key.ID,
2415+
})
2416+
}
2417+
check.Args(database.DeleteOAuth2ProviderAppTokensByAppAndUserIDParams{
2418+
AppID: app.ID,
2419+
UserID: user.ID,
2420+
}).Asserts(rbac.ResourceOAuth2ProviderAppCodeToken.WithOwner(user.ID.String()), rbac.ActionDelete)
2421+
}))
2422+
}

coderd/database/dbgen/dbgen.go

+26
Original file line numberDiff line numberDiff line change
@@ -704,6 +704,32 @@ func OAuth2ProviderAppSecret(t testing.TB, db database.Store, seed database.OAut
704704
return app
705705
}
706706

707+
func OAuth2ProviderAppCode(t testing.TB, db database.Store, seed database.OAuth2ProviderAppCode) database.OAuth2ProviderAppCode {
708+
code, err := db.InsertOAuth2ProviderAppCode(genCtx, database.InsertOAuth2ProviderAppCodeParams{
709+
ID: takeFirst(seed.ID, uuid.New()),
710+
CreatedAt: takeFirst(seed.CreatedAt, dbtime.Now()),
711+
ExpiresAt: takeFirst(seed.CreatedAt, dbtime.Now()),
712+
HashedSecret: takeFirstSlice(seed.HashedSecret, []byte("hashed-secret")),
713+
AppID: takeFirst(seed.AppID, uuid.New()),
714+
UserID: takeFirst(seed.UserID, uuid.New()),
715+
})
716+
require.NoError(t, err, "insert oauth2 app code")
717+
return code
718+
}
719+
720+
func OAuth2ProviderAppToken(t testing.TB, db database.Store, seed database.OAuth2ProviderAppToken) database.OAuth2ProviderAppToken {
721+
token, err := db.InsertOAuth2ProviderAppToken(genCtx, database.InsertOAuth2ProviderAppTokenParams{
722+
ID: takeFirst(seed.ID, uuid.New()),
723+
CreatedAt: takeFirst(seed.CreatedAt, dbtime.Now()),
724+
ExpiresAt: takeFirst(seed.CreatedAt, dbtime.Now()),
725+
HashedSecret: takeFirstSlice(seed.HashedSecret, []byte("hashed-secret")),
726+
AppSecretID: takeFirst(seed.AppSecretID, uuid.New()),
727+
APIKeyID: takeFirst(seed.APIKeyID, uuid.New().String()),
728+
})
729+
require.NoError(t, err, "insert oauth2 app token")
730+
return token
731+
}
732+
707733
func must[V any](v V, err error) V {
708734
if err != nil {
709735
panic(err)

0 commit comments

Comments
 (0)