diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go
index bf44240fd0..6daf5f481a 100644
--- a/coderd/apidoc/docs.go
+++ b/coderd/apidoc/docs.go
@@ -11504,7 +11504,9 @@ const docTemplate = `{
"convert_login",
"health_settings",
"workspace_proxy",
- "organization"
+ "organization",
+ "oauth2_provider_app",
+ "oauth2_provider_app_secret"
],
"x-enum-varnames": [
"ResourceTypeTemplate",
@@ -11519,7 +11521,9 @@ const docTemplate = `{
"ResourceTypeConvertLogin",
"ResourceTypeHealthSettings",
"ResourceTypeWorkspaceProxy",
- "ResourceTypeOrganization"
+ "ResourceTypeOrganization",
+ "ResourceTypeOAuth2ProviderApp",
+ "ResourceTypeOAuth2ProviderAppSecret"
]
},
"codersdk.Response": {
diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json
index edae5dee2f..d911ecac28 100644
--- a/coderd/apidoc/swagger.json
+++ b/coderd/apidoc/swagger.json
@@ -10378,7 +10378,9 @@
"convert_login",
"health_settings",
"workspace_proxy",
- "organization"
+ "organization",
+ "oauth2_provider_app",
+ "oauth2_provider_app_secret"
],
"x-enum-varnames": [
"ResourceTypeTemplate",
@@ -10393,7 +10395,9 @@
"ResourceTypeConvertLogin",
"ResourceTypeHealthSettings",
"ResourceTypeWorkspaceProxy",
- "ResourceTypeOrganization"
+ "ResourceTypeOrganization",
+ "ResourceTypeOAuth2ProviderApp",
+ "ResourceTypeOAuth2ProviderAppSecret"
]
},
"codersdk.Response": {
diff --git a/coderd/audit.go b/coderd/audit.go
index d78fba6116..782c977afc 100644
--- a/coderd/audit.go
+++ b/coderd/audit.go
@@ -333,6 +333,22 @@ func (api *API) auditLogIsResourceDeleted(ctx context.Context, alog database.Get
api.Logger.Error(ctx, "unable to fetch workspace", slog.Error(err))
}
return workspace.Deleted
+ case database.ResourceTypeOauth2ProviderApp:
+ _, err := api.Database.GetOAuth2ProviderAppByID(ctx, alog.ResourceID)
+ if xerrors.Is(err, sql.ErrNoRows) {
+ return true
+ } else if err != nil {
+ api.Logger.Error(ctx, "unable to fetch oauth2 app", slog.Error(err))
+ }
+ return false
+ case database.ResourceTypeOauth2ProviderAppSecret:
+ _, err := api.Database.GetOAuth2ProviderAppSecretByID(ctx, alog.ResourceID)
+ if xerrors.Is(err, sql.ErrNoRows) {
+ return true
+ } else if err != nil {
+ api.Logger.Error(ctx, "unable to fetch oauth2 app secret", slog.Error(err))
+ }
+ return false
default:
return false
}
@@ -379,6 +395,16 @@ func (api *API) auditLogResourceLink(ctx context.Context, alog database.GetAudit
return fmt.Sprintf("/@%s/%s/builds/%s",
workspaceOwner.Username, additionalFields.WorkspaceName, additionalFields.BuildNumber)
+ case database.ResourceTypeOauth2ProviderApp:
+ return fmt.Sprintf("/deployment/oauth2-provider/apps/%s", alog.ResourceID)
+
+ case database.ResourceTypeOauth2ProviderAppSecret:
+ secret, err := api.Database.GetOAuth2ProviderAppSecretByID(ctx, alog.ResourceID)
+ if err != nil {
+ return ""
+ }
+ return fmt.Sprintf("/deployment/oauth2-provider/apps/%s", secret.AppID)
+
default:
return ""
}
diff --git a/coderd/audit/diff.go b/coderd/audit/diff.go
index bdaef00bb0..a6835014d4 100644
--- a/coderd/audit/diff.go
+++ b/coderd/audit/diff.go
@@ -19,7 +19,9 @@ type Auditable interface {
database.License |
database.WorkspaceProxy |
database.AuditOAuthConvertState |
- database.HealthSettings
+ database.HealthSettings |
+ database.OAuth2ProviderApp |
+ database.OAuth2ProviderAppSecret
}
// Map is a map of changed fields in an audited resource. It maps field names to
diff --git a/coderd/audit/request.go b/coderd/audit/request.go
index 130ce9dd56..e6d9d01fbf 100644
--- a/coderd/audit/request.go
+++ b/coderd/audit/request.go
@@ -99,6 +99,10 @@ func ResourceTarget[T Auditable](tgt T) string {
return string(typed.ToLoginType)
case database.HealthSettings:
return "" // no target?
+ case database.OAuth2ProviderApp:
+ return typed.Name
+ case database.OAuth2ProviderAppSecret:
+ return typed.DisplaySecret
default:
panic(fmt.Sprintf("unknown resource %T for ResourceTarget", tgt))
}
@@ -132,6 +136,10 @@ func ResourceID[T Auditable](tgt T) uuid.UUID {
case database.HealthSettings:
// Artificial ID for auditing purposes
return typed.ID
+ case database.OAuth2ProviderApp:
+ return typed.ID
+ case database.OAuth2ProviderAppSecret:
+ return typed.ID
default:
panic(fmt.Sprintf("unknown resource %T for ResourceID", tgt))
}
@@ -163,6 +171,10 @@ func ResourceType[T Auditable](tgt T) database.ResourceType {
return database.ResourceTypeConvertLogin
case database.HealthSettings:
return database.ResourceTypeHealthSettings
+ case database.OAuth2ProviderApp:
+ return database.ResourceTypeOauth2ProviderApp
+ case database.OAuth2ProviderAppSecret:
+ return database.ResourceTypeOauth2ProviderAppSecret
default:
panic(fmt.Sprintf("unknown resource %T for ResourceType", typed))
}
@@ -195,6 +207,10 @@ func ResourceRequiresOrgID[T Auditable]() bool {
case database.HealthSettings:
// Artificial ID for auditing purposes
return false
+ case database.OAuth2ProviderApp:
+ return false
+ case database.OAuth2ProviderAppSecret:
+ return false
default:
panic(fmt.Sprintf("unknown resource %T for ResourceRequiresOrgID", tgt))
}
diff --git a/coderd/database/dump.sql b/coderd/database/dump.sql
index 07b4da8ae5..b9f002d251 100644
--- a/coderd/database/dump.sql
+++ b/coderd/database/dump.sql
@@ -135,7 +135,9 @@ CREATE TYPE resource_type AS ENUM (
'license',
'workspace_proxy',
'convert_login',
- 'health_settings'
+ 'health_settings',
+ 'oauth2_provider_app',
+ 'oauth2_provider_app_secret'
);
CREATE TYPE startup_script_behavior AS ENUM (
diff --git a/coderd/database/migrations/000197_oauth2_provider_app_audit.down.sql b/coderd/database/migrations/000197_oauth2_provider_app_audit.down.sql
new file mode 100644
index 0000000000..8761aff760
--- /dev/null
+++ b/coderd/database/migrations/000197_oauth2_provider_app_audit.down.sql
@@ -0,0 +1,2 @@
+-- It is not possible to drop enum values from enum types, so the UPs on
+-- resource_type have "IF NOT EXISTS".
diff --git a/coderd/database/migrations/000197_oauth2_provider_app_audit.up.sql b/coderd/database/migrations/000197_oauth2_provider_app_audit.up.sql
new file mode 100644
index 0000000000..694e34b810
--- /dev/null
+++ b/coderd/database/migrations/000197_oauth2_provider_app_audit.up.sql
@@ -0,0 +1,2 @@
+ALTER TYPE resource_type ADD VALUE IF NOT EXISTS 'oauth2_provider_app';
+ALTER TYPE resource_type ADD VALUE IF NOT EXISTS 'oauth2_provider_app_secret';
diff --git a/coderd/database/models.go b/coderd/database/models.go
index 7336dea1f3..677d258105 100644
--- a/coderd/database/models.go
+++ b/coderd/database/models.go
@@ -1149,19 +1149,21 @@ func AllProvisionerTypeValues() []ProvisionerType {
type ResourceType string
const (
- ResourceTypeOrganization ResourceType = "organization"
- ResourceTypeTemplate ResourceType = "template"
- ResourceTypeTemplateVersion ResourceType = "template_version"
- ResourceTypeUser ResourceType = "user"
- ResourceTypeWorkspace ResourceType = "workspace"
- ResourceTypeGitSshKey ResourceType = "git_ssh_key"
- ResourceTypeApiKey ResourceType = "api_key"
- ResourceTypeGroup ResourceType = "group"
- ResourceTypeWorkspaceBuild ResourceType = "workspace_build"
- ResourceTypeLicense ResourceType = "license"
- ResourceTypeWorkspaceProxy ResourceType = "workspace_proxy"
- ResourceTypeConvertLogin ResourceType = "convert_login"
- ResourceTypeHealthSettings ResourceType = "health_settings"
+ ResourceTypeOrganization ResourceType = "organization"
+ ResourceTypeTemplate ResourceType = "template"
+ ResourceTypeTemplateVersion ResourceType = "template_version"
+ ResourceTypeUser ResourceType = "user"
+ ResourceTypeWorkspace ResourceType = "workspace"
+ ResourceTypeGitSshKey ResourceType = "git_ssh_key"
+ ResourceTypeApiKey ResourceType = "api_key"
+ ResourceTypeGroup ResourceType = "group"
+ ResourceTypeWorkspaceBuild ResourceType = "workspace_build"
+ ResourceTypeLicense ResourceType = "license"
+ ResourceTypeWorkspaceProxy ResourceType = "workspace_proxy"
+ ResourceTypeConvertLogin ResourceType = "convert_login"
+ ResourceTypeHealthSettings ResourceType = "health_settings"
+ ResourceTypeOauth2ProviderApp ResourceType = "oauth2_provider_app"
+ ResourceTypeOauth2ProviderAppSecret ResourceType = "oauth2_provider_app_secret"
)
func (e *ResourceType) Scan(src interface{}) error {
@@ -1213,7 +1215,9 @@ func (e ResourceType) Valid() bool {
ResourceTypeLicense,
ResourceTypeWorkspaceProxy,
ResourceTypeConvertLogin,
- ResourceTypeHealthSettings:
+ ResourceTypeHealthSettings,
+ ResourceTypeOauth2ProviderApp,
+ ResourceTypeOauth2ProviderAppSecret:
return true
}
return false
@@ -1234,6 +1238,8 @@ func AllResourceTypeValues() []ResourceType {
ResourceTypeWorkspaceProxy,
ResourceTypeConvertLogin,
ResourceTypeHealthSettings,
+ ResourceTypeOauth2ProviderApp,
+ ResourceTypeOauth2ProviderAppSecret,
}
}
diff --git a/codersdk/audit.go b/codersdk/audit.go
index c1ea077ec0..553bd9cc2d 100644
--- a/codersdk/audit.go
+++ b/codersdk/audit.go
@@ -14,19 +14,22 @@ import (
type ResourceType string
const (
- ResourceTypeTemplate ResourceType = "template"
- ResourceTypeTemplateVersion ResourceType = "template_version"
- ResourceTypeUser ResourceType = "user"
- ResourceTypeWorkspace ResourceType = "workspace"
- ResourceTypeWorkspaceBuild ResourceType = "workspace_build"
- ResourceTypeGitSSHKey ResourceType = "git_ssh_key"
- ResourceTypeAPIKey ResourceType = "api_key"
- ResourceTypeGroup ResourceType = "group"
- ResourceTypeLicense ResourceType = "license"
- ResourceTypeConvertLogin ResourceType = "convert_login"
- ResourceTypeHealthSettings ResourceType = "health_settings"
- ResourceTypeWorkspaceProxy ResourceType = "workspace_proxy"
- ResourceTypeOrganization ResourceType = "organization"
+ ResourceTypeTemplate ResourceType = "template"
+ ResourceTypeTemplateVersion ResourceType = "template_version"
+ ResourceTypeUser ResourceType = "user"
+ ResourceTypeWorkspace ResourceType = "workspace"
+ ResourceTypeWorkspaceBuild ResourceType = "workspace_build"
+ ResourceTypeGitSSHKey ResourceType = "git_ssh_key"
+ ResourceTypeAPIKey ResourceType = "api_key"
+ ResourceTypeGroup ResourceType = "group"
+ ResourceTypeLicense ResourceType = "license"
+ ResourceTypeConvertLogin ResourceType = "convert_login"
+ ResourceTypeHealthSettings ResourceType = "health_settings"
+ ResourceTypeWorkspaceProxy ResourceType = "workspace_proxy"
+ ResourceTypeOrganization ResourceType = "organization"
+ ResourceTypeOAuth2ProviderApp ResourceType = "oauth2_provider_app"
+ // nolint:gosec // This is not a secret.
+ ResourceTypeOAuth2ProviderAppSecret ResourceType = "oauth2_provider_app_secret"
)
func (r ResourceType) FriendlyString() string {
@@ -59,6 +62,10 @@ func (r ResourceType) FriendlyString() string {
return "organization"
case ResourceTypeHealthSettings:
return "health_settings"
+ case ResourceTypeOAuth2ProviderApp:
+ return "oauth2 app"
+ case ResourceTypeOAuth2ProviderAppSecret:
+ return "oauth2 app secret"
default:
return "unknown"
}
diff --git a/codersdk/oauth2.go b/codersdk/oauth2.go
index 74f12bd303..726a50907e 100644
--- a/codersdk/oauth2.go
+++ b/codersdk/oauth2.go
@@ -159,7 +159,7 @@ func (c *Client) PostOAuth2ProviderAppSecret(ctx context.Context, appID uuid.UUI
return OAuth2ProviderAppSecretFull{}, err
}
defer res.Body.Close()
- if res.StatusCode != http.StatusOK {
+ if res.StatusCode != http.StatusCreated {
return OAuth2ProviderAppSecretFull{}, ReadBodyAsError(res)
}
var resp OAuth2ProviderAppSecretFull
diff --git a/docs/admin/audit-logs.md b/docs/admin/audit-logs.md
index 8d7f638dca..666b8d3d3f 100644
--- a/docs/admin/audit-logs.md
+++ b/docs/admin/audit-logs.md
@@ -16,6 +16,8 @@ We track the following resources:
| GitSSHKey
create |
Field | Tracked |
---|
created_at | false |
private_key | true |
public_key | true |
updated_at | false |
user_id | true |
|
| HealthSettings
| Field | Tracked |
---|
dismissed_healthchecks | true |
id | false |
|
| License
create, delete | Field | Tracked |
---|
exp | true |
id | false |
jwt | false |
uploaded_at | true |
uuid | true |
|
+| OAuth2ProviderApp
| Field | Tracked |
---|
callback_url | true |
created_at | false |
icon | true |
id | false |
name | true |
updated_at | false |
|
+| OAuth2ProviderAppSecret
| Field | Tracked |
---|
app_id | false |
created_at | false |
display_secret | false |
hashed_secret | false |
id | false |
last_used_at | false |
secret_prefix | false |
|
| Template
write, delete | Field | Tracked |
---|
active_version_id | true |
activity_bump | true |
allow_user_autostart | true |
allow_user_autostop | true |
allow_user_cancel_workspace_jobs | true |
autostart_block_days_of_week | true |
autostop_requirement_days_of_week | true |
autostop_requirement_weeks | true |
created_at | false |
created_by | true |
created_by_avatar_url | false |
created_by_username | false |
default_ttl | true |
deleted | false |
deprecated | true |
description | true |
display_name | true |
failure_ttl | true |
group_acl | true |
icon | true |
id | true |
max_port_sharing_level | true |
max_ttl | true |
name | true |
organization_id | false |
provisioner | true |
require_active_version | true |
time_til_dormant | true |
time_til_dormant_autodelete | true |
updated_at | false |
use_max_ttl | true |
user_acl | true |
|
| TemplateVersion
create, write | Field | Tracked |
---|
archived | true |
created_at | false |
created_by | true |
created_by_avatar_url | false |
created_by_username | false |
external_auth_providers | false |
id | true |
job_id | false |
message | false |
name | true |
organization_id | false |
readme | true |
template_id | true |
updated_at | false |
|
| User
create, write, delete | Field | Tracked |
---|
avatar_url | false |
created_at | false |
deleted | true |
email | true |
hashed_password | true |
id | true |
last_seen_at | false |
login_type | true |
name | true |
quiet_hours_schedule | true |
rbac_roles | true |
status | true |
theme_preference | false |
updated_at | false |
username | true |
|
diff --git a/docs/api/schemas.md b/docs/api/schemas.md
index b383a707c6..406eb9202d 100644
--- a/docs/api/schemas.md
+++ b/docs/api/schemas.md
@@ -5367,21 +5367,23 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in
#### Enumerated Values
-| Value |
-| ------------------ |
-| `template` |
-| `template_version` |
-| `user` |
-| `workspace` |
-| `workspace_build` |
-| `git_ssh_key` |
-| `api_key` |
-| `group` |
-| `license` |
-| `convert_login` |
-| `health_settings` |
-| `workspace_proxy` |
-| `organization` |
+| Value |
+| ---------------------------- |
+| `template` |
+| `template_version` |
+| `user` |
+| `workspace` |
+| `workspace_build` |
+| `git_ssh_key` |
+| `api_key` |
+| `group` |
+| `license` |
+| `convert_login` |
+| `health_settings` |
+| `workspace_proxy` |
+| `organization` |
+| `oauth2_provider_app` |
+| `oauth2_provider_app_secret` |
## codersdk.Response
diff --git a/enterprise/audit/table.go b/enterprise/audit/table.go
index 821fcd3878..f557ded214 100644
--- a/enterprise/audit/table.go
+++ b/enterprise/audit/table.go
@@ -219,6 +219,23 @@ var auditableResourcesTypes = map[any]map[string]Action{
"region_id": ActionTrack,
"version": ActionTrack,
},
+ &database.OAuth2ProviderApp{}: {
+ "id": ActionIgnore,
+ "created_at": ActionIgnore,
+ "updated_at": ActionIgnore,
+ "name": ActionTrack,
+ "icon": ActionTrack,
+ "callback_url": ActionTrack,
+ },
+ &database.OAuth2ProviderAppSecret{}: {
+ "id": ActionIgnore,
+ "created_at": ActionIgnore,
+ "last_used_at": ActionIgnore,
+ "hashed_secret": ActionIgnore,
+ "display_secret": ActionIgnore,
+ "app_id": ActionIgnore,
+ "secret_prefix": ActionIgnore,
+ },
}
// auditMap converts a map of struct pointers to a map of struct names as
diff --git a/enterprise/coderd/oauth2.go b/enterprise/coderd/oauth2.go
index 9c75b0b7a6..26b9555bf3 100644
--- a/enterprise/coderd/oauth2.go
+++ b/enterprise/coderd/oauth2.go
@@ -7,6 +7,7 @@ import (
"github.com/google/uuid"
"github.com/coder/coder/v2/buildinfo"
+ "github.com/coder/coder/v2/coderd/audit"
"github.com/coder/coder/v2/coderd/database"
"github.com/coder/coder/v2/coderd/database/db2sdk"
"github.com/coder/coder/v2/coderd/database/dbtime"
@@ -108,7 +109,17 @@ func (api *API) oAuth2ProviderApp(rw http.ResponseWriter, r *http.Request) {
// @Success 200 {object} codersdk.OAuth2ProviderApp
// @Router /oauth2-provider/apps [post]
func (api *API) postOAuth2ProviderApp(rw http.ResponseWriter, r *http.Request) {
- ctx := r.Context()
+ var (
+ ctx = r.Context()
+ auditor = api.AGPL.Auditor.Load()
+ aReq, commitAudit = audit.InitRequest[database.OAuth2ProviderApp](rw, &audit.RequestParams{
+ Audit: *auditor,
+ Log: api.Logger,
+ Request: r,
+ Action: database.AuditActionCreate,
+ })
+ )
+ defer commitAudit()
var req codersdk.PostOAuth2ProviderAppRequest
if !httpapi.Read(ctx, rw, r, &req) {
return
@@ -128,6 +139,7 @@ func (api *API) postOAuth2ProviderApp(rw http.ResponseWriter, r *http.Request) {
})
return
}
+ aReq.New = app
httpapi.Write(ctx, rw, http.StatusCreated, db2sdk.OAuth2ProviderApp(api.AccessURL, app))
}
@@ -142,8 +154,19 @@ func (api *API) postOAuth2ProviderApp(rw http.ResponseWriter, r *http.Request) {
// @Success 200 {object} codersdk.OAuth2ProviderApp
// @Router /oauth2-provider/apps/{app} [put]
func (api *API) putOAuth2ProviderApp(rw http.ResponseWriter, r *http.Request) {
- ctx := r.Context()
- app := httpmw.OAuth2ProviderApp(r)
+ var (
+ ctx = r.Context()
+ app = httpmw.OAuth2ProviderApp(r)
+ auditor = api.AGPL.Auditor.Load()
+ aReq, commitAudit = audit.InitRequest[database.OAuth2ProviderApp](rw, &audit.RequestParams{
+ Audit: *auditor,
+ Log: api.Logger,
+ Request: r,
+ Action: database.AuditActionWrite,
+ })
+ )
+ aReq.Old = app
+ defer commitAudit()
var req codersdk.PutOAuth2ProviderAppRequest
if !httpapi.Read(ctx, rw, r, &req) {
return
@@ -162,6 +185,7 @@ func (api *API) putOAuth2ProviderApp(rw http.ResponseWriter, r *http.Request) {
})
return
}
+ aReq.New = app
httpapi.Write(ctx, rw, http.StatusOK, db2sdk.OAuth2ProviderApp(api.AccessURL, app))
}
@@ -173,8 +197,19 @@ func (api *API) putOAuth2ProviderApp(rw http.ResponseWriter, r *http.Request) {
// @Success 204
// @Router /oauth2-provider/apps/{app} [delete]
func (api *API) deleteOAuth2ProviderApp(rw http.ResponseWriter, r *http.Request) {
- ctx := r.Context()
- app := httpmw.OAuth2ProviderApp(r)
+ var (
+ ctx = r.Context()
+ app = httpmw.OAuth2ProviderApp(r)
+ auditor = api.AGPL.Auditor.Load()
+ aReq, commitAudit = audit.InitRequest[database.OAuth2ProviderApp](rw, &audit.RequestParams{
+ Audit: *auditor,
+ Log: api.Logger,
+ Request: r,
+ Action: database.AuditActionDelete,
+ })
+ )
+ aReq.Old = app
+ defer commitAudit()
err := api.Database.DeleteOAuth2ProviderAppByID(ctx, app.ID)
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
@@ -225,8 +260,18 @@ func (api *API) oAuth2ProviderAppSecrets(rw http.ResponseWriter, r *http.Request
// @Success 200 {array} codersdk.OAuth2ProviderAppSecretFull
// @Router /oauth2-provider/apps/{app}/secrets [post]
func (api *API) postOAuth2ProviderAppSecret(rw http.ResponseWriter, r *http.Request) {
- ctx := r.Context()
- app := httpmw.OAuth2ProviderApp(r)
+ var (
+ ctx = r.Context()
+ app = httpmw.OAuth2ProviderApp(r)
+ auditor = api.AGPL.Auditor.Load()
+ aReq, commitAudit = audit.InitRequest[database.OAuth2ProviderAppSecret](rw, &audit.RequestParams{
+ Audit: *auditor,
+ Log: api.Logger,
+ Request: r,
+ Action: database.AuditActionCreate,
+ })
+ )
+ defer commitAudit()
secret, err := identityprovider.GenerateSecret()
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
@@ -253,7 +298,8 @@ func (api *API) postOAuth2ProviderAppSecret(rw http.ResponseWriter, r *http.Requ
})
return
}
- httpapi.Write(ctx, rw, http.StatusOK, codersdk.OAuth2ProviderAppSecretFull{
+ aReq.New = dbSecret
+ httpapi.Write(ctx, rw, http.StatusCreated, codersdk.OAuth2ProviderAppSecretFull{
ID: dbSecret.ID,
ClientSecretFull: secret.Formatted,
})
@@ -268,8 +314,19 @@ func (api *API) postOAuth2ProviderAppSecret(rw http.ResponseWriter, r *http.Requ
// @Success 204
// @Router /oauth2-provider/apps/{app}/secrets/{secretID} [delete]
func (api *API) deleteOAuth2ProviderAppSecret(rw http.ResponseWriter, r *http.Request) {
- ctx := r.Context()
- secret := httpmw.OAuth2ProviderAppSecret(r)
+ var (
+ ctx = r.Context()
+ secret = httpmw.OAuth2ProviderAppSecret(r)
+ auditor = api.AGPL.Auditor.Load()
+ aReq, commitAudit = audit.InitRequest[database.OAuth2ProviderAppSecret](rw, &audit.RequestParams{
+ Audit: *auditor,
+ Log: api.Logger,
+ Request: r,
+ Action: database.AuditActionDelete,
+ })
+ )
+ aReq.Old = secret
+ defer commitAudit()
err := api.Database.DeleteOAuth2ProviderAppSecretByID(ctx, secret.ID)
if err != nil {
httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{
diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts
index 1e27e3c980..7b0f21a3fa 100644
--- a/site/src/api/typesGenerated.ts
+++ b/site/src/api/typesGenerated.ts
@@ -2251,6 +2251,8 @@ export type ResourceType =
| "group"
| "health_settings"
| "license"
+ | "oauth2_provider_app"
+ | "oauth2_provider_app_secret"
| "organization"
| "template"
| "template_version"
@@ -2265,6 +2267,8 @@ export const ResourceTypes: ResourceType[] = [
"group",
"health_settings",
"license",
+ "oauth2_provider_app",
+ "oauth2_provider_app_secret",
"organization",
"template",
"template_version",