mirror of https://github.com/coder/coder.git
feat: audit oauth2 app management (#12275)
* Audit oauth2 app management * Use 201 for creating secrets
This commit is contained in:
parent
6b866b3f48
commit
f74532ff50
|
@ -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": {
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -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 ""
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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 (
|
||||
|
|
|
@ -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".
|
|
@ -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';
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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"
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -16,6 +16,8 @@ We track the following resources:
|
|||
| GitSSHKey<br><i>create</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>created_at</td><td>false</td></tr><tr><td>private_key</td><td>true</td></tr><tr><td>public_key</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>user_id</td><td>true</td></tr></tbody></table> |
|
||||
| HealthSettings<br><i></i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>dismissed_healthchecks</td><td>true</td></tr><tr><td>id</td><td>false</td></tr></tbody></table> |
|
||||
| License<br><i>create, delete</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>exp</td><td>true</td></tr><tr><td>id</td><td>false</td></tr><tr><td>jwt</td><td>false</td></tr><tr><td>uploaded_at</td><td>true</td></tr><tr><td>uuid</td><td>true</td></tr></tbody></table> |
|
||||
| OAuth2ProviderApp<br><i></i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>callback_url</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>icon</td><td>true</td></tr><tr><td>id</td><td>false</td></tr><tr><td>name</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr></tbody></table> |
|
||||
| OAuth2ProviderAppSecret<br><i></i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>app_id</td><td>false</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>display_secret</td><td>false</td></tr><tr><td>hashed_secret</td><td>false</td></tr><tr><td>id</td><td>false</td></tr><tr><td>last_used_at</td><td>false</td></tr><tr><td>secret_prefix</td><td>false</td></tr></tbody></table> |
|
||||
| Template<br><i>write, delete</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>active_version_id</td><td>true</td></tr><tr><td>activity_bump</td><td>true</td></tr><tr><td>allow_user_autostart</td><td>true</td></tr><tr><td>allow_user_autostop</td><td>true</td></tr><tr><td>allow_user_cancel_workspace_jobs</td><td>true</td></tr><tr><td>autostart_block_days_of_week</td><td>true</td></tr><tr><td>autostop_requirement_days_of_week</td><td>true</td></tr><tr><td>autostop_requirement_weeks</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>created_by</td><td>true</td></tr><tr><td>created_by_avatar_url</td><td>false</td></tr><tr><td>created_by_username</td><td>false</td></tr><tr><td>default_ttl</td><td>true</td></tr><tr><td>deleted</td><td>false</td></tr><tr><td>deprecated</td><td>true</td></tr><tr><td>description</td><td>true</td></tr><tr><td>display_name</td><td>true</td></tr><tr><td>failure_ttl</td><td>true</td></tr><tr><td>group_acl</td><td>true</td></tr><tr><td>icon</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>max_port_sharing_level</td><td>true</td></tr><tr><td>max_ttl</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>provisioner</td><td>true</td></tr><tr><td>require_active_version</td><td>true</td></tr><tr><td>time_til_dormant</td><td>true</td></tr><tr><td>time_til_dormant_autodelete</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>use_max_ttl</td><td>true</td></tr><tr><td>user_acl</td><td>true</td></tr></tbody></table> |
|
||||
| TemplateVersion<br><i>create, write</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>archived</td><td>true</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>created_by</td><td>true</td></tr><tr><td>created_by_avatar_url</td><td>false</td></tr><tr><td>created_by_username</td><td>false</td></tr><tr><td>external_auth_providers</td><td>false</td></tr><tr><td>id</td><td>true</td></tr><tr><td>job_id</td><td>false</td></tr><tr><td>message</td><td>false</td></tr><tr><td>name</td><td>true</td></tr><tr><td>organization_id</td><td>false</td></tr><tr><td>readme</td><td>true</td></tr><tr><td>template_id</td><td>true</td></tr><tr><td>updated_at</td><td>false</td></tr></tbody></table> |
|
||||
| User<br><i>create, write, delete</i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>avatar_url</td><td>false</td></tr><tr><td>created_at</td><td>false</td></tr><tr><td>deleted</td><td>true</td></tr><tr><td>email</td><td>true</td></tr><tr><td>hashed_password</td><td>true</td></tr><tr><td>id</td><td>true</td></tr><tr><td>last_seen_at</td><td>false</td></tr><tr><td>login_type</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>quiet_hours_schedule</td><td>true</td></tr><tr><td>rbac_roles</td><td>true</td></tr><tr><td>status</td><td>true</td></tr><tr><td>theme_preference</td><td>false</td></tr><tr><td>updated_at</td><td>false</td></tr><tr><td>username</td><td>true</td></tr></tbody></table> |
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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{
|
||||
|
|
|
@ -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",
|
||||
|
|
Loading…
Reference in New Issue