Skip to content

Commit 65b1054

Browse files
committed
feat(oauth2): add frontend UI for client credentials applications
- Add ClientCredentialsAppForm and ClientCredentialsAppRow components - Update API schemas to include created_at, grant_types, and user_id fields - Add dedicated pages for creating and managing client credentials apps - Update sidebar navigation and routing for OAuth2 client credentials - Enhance OAuth2AppPageView with user ownership information display Change-Id: I3271c7fb995d7225dd6cc830066fa2c8cb29720a Signed-off-by: Thomas Kosiewski <tk@coder.com>
1 parent ac0d1f6 commit 65b1054

File tree

31 files changed

+1400
-86
lines changed

31 files changed

+1400
-86
lines changed

coderd/apidoc/docs.go

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/apidoc/swagger.json

Lines changed: 24 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/db2sdk/db2sdk.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,11 +354,19 @@ func TemplateVersionParameterOptionFromPreview(option *previewtypes.ParameterOpt
354354
}
355355

356356
func OAuth2ProviderApp(accessURL *url.URL, dbApp database.OAuth2ProviderApp) codersdk.OAuth2ProviderApp {
357+
var userID uuid.UUID
358+
if dbApp.UserID.Valid {
359+
userID = dbApp.UserID.UUID
360+
}
361+
357362
return codersdk.OAuth2ProviderApp{
358363
ID: dbApp.ID,
359364
Name: dbApp.Name,
360365
RedirectURIs: dbApp.RedirectUris,
361366
Icon: dbApp.Icon,
367+
CreatedAt: dbApp.CreatedAt,
368+
GrantTypes: dbApp.GrantTypes,
369+
UserID: userID,
362370
Endpoints: codersdk.OAuth2AppEndpoints{
363371
Authorization: accessURL.ResolveReference(&url.URL{
364372
Path: "/oauth2/authorize",
@@ -369,6 +377,9 @@ func OAuth2ProviderApp(accessURL *url.URL, dbApp database.OAuth2ProviderApp) cod
369377
DeviceAuth: accessURL.ResolveReference(&url.URL{
370378
Path: "/oauth2/device/authorize",
371379
}).String(),
380+
Revocation: accessURL.ResolveReference(&url.URL{
381+
Path: "/oauth2/revoke",
382+
}).String(),
372383
},
373384
}
374385
}

coderd/database/dbauthz/dbauthz.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2304,6 +2304,10 @@ func (q *querier) GetOAuth2ProviderApps(ctx context.Context) ([]database.OAuth2P
23042304
return q.db.GetOAuth2ProviderApps(ctx)
23052305
}
23062306

2307+
func (q *querier) GetOAuth2ProviderAppsByOwnerID(ctx context.Context, userID uuid.NullUUID) ([]database.OAuth2ProviderApp, error) {
2308+
return fetchWithPostFilter(q.auth, policy.ActionRead, q.db.GetOAuth2ProviderAppsByOwnerID)(ctx, userID)
2309+
}
2310+
23072311
func (q *querier) GetOAuth2ProviderAppsByUserID(ctx context.Context, userID uuid.UUID) ([]database.GetOAuth2ProviderAppsByUserIDRow, error) {
23082312
// This authz check is to make sure the caller can read all their own tokens.
23092313
if err := q.authorizeContext(ctx, policy.ActionRead,

coderd/database/dbauthz/dbauthz_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5288,6 +5288,28 @@ func (s *MethodTestSuite) TestOAuth2ProviderApps() {
52885288
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
52895289
check.Args(app.ID).Asserts(rbac.ResourceOauth2App, policy.ActionDelete)
52905290
}))
5291+
s.Run("GetOAuth2ProviderAppsByOwnerID", s.Subtest(func(db database.Store, check *expects) {
5292+
owner := dbgen.User(s.T(), db, database.User{})
5293+
// Create multiple apps with the same owner
5294+
app1 := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{
5295+
UserID: uuid.NullUUID{UUID: owner.ID, Valid: true},
5296+
})
5297+
app2 := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{
5298+
UserID: uuid.NullUUID{UUID: owner.ID, Valid: true},
5299+
})
5300+
// Create an app with a different owner to ensure filtering works
5301+
differentOwner := dbgen.User(s.T(), db, database.User{})
5302+
_ = dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{
5303+
UserID: uuid.NullUUID{UUID: differentOwner.ID, Valid: true},
5304+
})
5305+
// fetchWithPostFilter will check each individual app, so we need to assert those checks
5306+
check.Args(uuid.NullUUID{UUID: owner.ID, Valid: true}).
5307+
Asserts(
5308+
app1, policy.ActionRead, // Check for first app (includes owner)
5309+
app2, policy.ActionRead, // Check for second app (includes owner)
5310+
).
5311+
Returns([]database.OAuth2ProviderApp{app1, app2})
5312+
}))
52915313
s.Run("GetOAuth2ProviderAppByClientID", s.Subtest(func(db database.Store, check *expects) {
52925314
app := dbgen.OAuth2ProviderApp(s.T(), db, database.OAuth2ProviderApp{})
52935315
check.Args(app.ID).Asserts(rbac.ResourceOauth2App, policy.ActionRead).Returns(app)

coderd/database/dbmetrics/querymetrics.go

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/dbmock/dbmock.go

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/modelmethods.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,10 @@ func (OAuth2ProviderAppSecret) RBACObject() rbac.Object {
391391
return rbac.ResourceOauth2AppSecret
392392
}
393393

394-
func (OAuth2ProviderApp) RBACObject() rbac.Object {
394+
func (app OAuth2ProviderApp) RBACObject() rbac.Object {
395+
if app.UserID.Valid {
396+
return rbac.ResourceOauth2App.WithOwner(app.UserID.UUID.String())
397+
}
395398
return rbac.ResourceOauth2App
396399
}
397400

coderd/database/querier.go

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

coderd/database/queries.sql.go

Lines changed: 54 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)