Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitd7eadee

Browse files
authored
chore: insert audit log entries for organization CRUD (#13660)
* chore: insert audit log entries for organization CRUD
1 parent9c1a6a2 commitd7eadee

File tree

6 files changed

+71
-9
lines changed

6 files changed

+71
-9
lines changed

‎coderd/audit/diff.go‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ type Auditable interface {
2323
database.OAuth2ProviderApp|
2424
database.OAuth2ProviderAppSecret|
2525
database.CustomRole|
26-
database.AuditableOrganizationMember
26+
database.AuditableOrganizationMember|
27+
database.Organization
2728
}
2829

2930
// Map is a map of changed fields in an audited resource. It maps field names to

‎coderd/audit/request.go‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ func ResourceTarget[T Auditable](tgt T) string {
107107
returntyped.Name
108108
case database.AuditableOrganizationMember:
109109
returntyped.Username
110+
case database.Organization:
111+
returntyped.Name
110112
default:
111113
panic(fmt.Sprintf("unknown resource %T for ResourceTarget",tgt))
112114
}
@@ -148,6 +150,8 @@ func ResourceID[T Auditable](tgt T) uuid.UUID {
148150
returntyped.ID
149151
case database.AuditableOrganizationMember:
150152
returntyped.UserID
153+
case database.Organization:
154+
returntyped.ID
151155
default:
152156
panic(fmt.Sprintf("unknown resource %T for ResourceID",tgt))
153157
}
@@ -187,6 +191,8 @@ func ResourceType[T Auditable](tgt T) database.ResourceType {
187191
returndatabase.ResourceTypeCustomRole
188192
case database.AuditableOrganizationMember:
189193
returndatabase.ResourceTypeOrganizationMember
194+
case database.Organization:
195+
returndatabase.ResourceTypeOrganization
190196
default:
191197
panic(fmt.Sprintf("unknown resource %T for ResourceType",typed))
192198
}
@@ -227,6 +233,8 @@ func ResourceRequiresOrgID[T Auditable]() bool {
227233
returntrue
228234
case database.AuditableOrganizationMember:
229235
returntrue
236+
case database.Organization:
237+
returntrue
230238
default:
231239
panic(fmt.Sprintf("unknown resource %T for ResourceRequiresOrgID",tgt))
232240
}

‎coderd/organizations.go‎

Lines changed: 49 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/google/uuid"
1010
"golang.org/x/xerrors"
1111

12+
"github.com/coder/coder/v2/coderd/audit"
1213
"github.com/coder/coder/v2/coderd/database"
1314
"github.com/coder/coder/v2/coderd/database/dbtime"
1415
"github.com/coder/coder/v2/coderd/httpapi"
@@ -41,8 +42,22 @@ func (*API) organization(rw http.ResponseWriter, r *http.Request) {
4142
// @Success 201 {object} codersdk.Organization
4243
// @Router /organizations [post]
4344
func (api*API)postOrganizations(rw http.ResponseWriter,r*http.Request) {
44-
ctx:=r.Context()
45-
apiKey:=httpmw.APIKey(r)
45+
var (
46+
// organizationID is required before the audit log entry is created.
47+
organizationID=uuid.New()
48+
ctx=r.Context()
49+
apiKey=httpmw.APIKey(r)
50+
auditor=api.Auditor.Load()
51+
aReq,commitAudit=audit.InitRequest[database.Organization](rw,&audit.RequestParams{
52+
Audit:*auditor,
53+
Log:api.Logger,
54+
Request:r,
55+
Action:database.AuditActionCreate,
56+
OrganizationID:organizationID,
57+
})
58+
)
59+
aReq.Old= database.Organization{}
60+
defercommitAudit()
4661

4762
varreq codersdk.CreateOrganizationRequest
4863
if!httpapi.Read(ctx,rw,r,&req) {
@@ -78,7 +93,7 @@ func (api *API) postOrganizations(rw http.ResponseWriter, r *http.Request) {
7893
}
7994

8095
organization,err=tx.InsertOrganization(ctx, database.InsertOrganizationParams{
81-
ID:uuid.New(),
96+
ID:organizationID,
8297
Name:req.Name,
8398
DisplayName:req.DisplayName,
8499
Description:req.Description,
@@ -119,6 +134,7 @@ func (api *API) postOrganizations(rw http.ResponseWriter, r *http.Request) {
119134
return
120135
}
121136

137+
aReq.New=organization
122138
httpapi.Write(ctx,rw,http.StatusCreated,convertOrganization(organization))
123139
}
124140

@@ -133,8 +149,20 @@ func (api *API) postOrganizations(rw http.ResponseWriter, r *http.Request) {
133149
// @Success 200 {object} codersdk.Organization
134150
// @Router /organizations/{organization} [patch]
135151
func (api*API)patchOrganization(rw http.ResponseWriter,r*http.Request) {
136-
ctx:=r.Context()
137-
organization:=httpmw.OrganizationParam(r)
152+
var (
153+
ctx=r.Context()
154+
organization=httpmw.OrganizationParam(r)
155+
auditor=api.Auditor.Load()
156+
aReq,commitAudit=audit.InitRequest[database.Organization](rw,&audit.RequestParams{
157+
Audit:*auditor,
158+
Log:api.Logger,
159+
Request:r,
160+
Action:database.AuditActionWrite,
161+
OrganizationID:organization.ID,
162+
})
163+
)
164+
aReq.Old=organization
165+
defercommitAudit()
138166

139167
varreq codersdk.UpdateOrganizationRequest
140168
if!httpapi.Read(ctx,rw,r,&req) {
@@ -208,6 +236,7 @@ func (api *API) patchOrganization(rw http.ResponseWriter, r *http.Request) {
208236
return
209237
}
210238

239+
aReq.New=organization
211240
httpapi.Write(ctx,rw,http.StatusOK,convertOrganization(organization))
212241
}
213242

@@ -220,8 +249,20 @@ func (api *API) patchOrganization(rw http.ResponseWriter, r *http.Request) {
220249
// @Success 200 {object} codersdk.Response
221250
// @Router /organizations/{organization} [delete]
222251
func (api*API)deleteOrganization(rw http.ResponseWriter,r*http.Request) {
223-
ctx:=r.Context()
224-
organization:=httpmw.OrganizationParam(r)
252+
var (
253+
ctx=r.Context()
254+
organization=httpmw.OrganizationParam(r)
255+
auditor=api.Auditor.Load()
256+
aReq,commitAudit=audit.InitRequest[database.Organization](rw,&audit.RequestParams{
257+
Audit:*auditor,
258+
Log:api.Logger,
259+
Request:r,
260+
Action:database.AuditActionDelete,
261+
OrganizationID:organization.ID,
262+
})
263+
)
264+
aReq.Old=organization
265+
defercommitAudit()
225266

226267
iforganization.IsDefault {
227268
httpapi.Write(ctx,rw,http.StatusBadRequest, codersdk.Response{
@@ -239,6 +280,7 @@ func (api *API) deleteOrganization(rw http.ResponseWriter, r *http.Request) {
239280
return
240281
}
241282

283+
aReq.New= database.Organization{}
242284
httpapi.Write(ctx,rw,http.StatusOK, codersdk.Response{
243285
Message:"Organization has been deleted.",
244286
})

‎coderd/users_test.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ func TestPostUsers(t *testing.T) {
525525

526526
require.Len(t,auditor.AuditLogs(),numLogs)
527527
require.Equal(t,database.AuditActionCreate,auditor.AuditLogs()[numLogs-1].Action)
528-
require.Equal(t,database.AuditActionLogin,auditor.AuditLogs()[numLogs-2].Action)
528+
require.Equal(t,database.AuditActionLogin,auditor.AuditLogs()[numLogs-3].Action)
529529

530530
require.Len(t,user.OrganizationIDs,1)
531531
assert.Equal(t,firstUser.OrganizationID,user.OrganizationIDs[0])

‎docs/admin/audit-logs.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ We track the following resources:
2020
| 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> |
2121
| 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> |
2222
| 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> |
23+
| Organization<br><i></i> | <table><thead><tr><th>Field</th><th>Tracked</th></tr></thead><tbody><tr><td>created_at</td><td>false</td></tr><tr><td>description</td><td>true</td></tr><tr><td>display_name</td><td>true</td></tr><tr><td>icon</td><td>true</td></tr><tr><td>id</td><td>false</td></tr><tr><td>is_default</td><td>true</td></tr><tr><td>name</td><td>true</td></tr><tr><td>updated_at</td><td>true</td></tr></tbody></table> |
2324
| 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>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>user_acl</td><td>true</td></tr></tbody></table> |
2425
| 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> |
2526
| 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> |

‎enterprise/audit/table.go‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,16 @@ var auditableResourcesTypes = map[any]map[string]Action{
254254
"app_id":ActionIgnore,
255255
"secret_prefix":ActionIgnore,
256256
},
257+
&database.Organization{}: {
258+
"id":ActionIgnore,
259+
"name":ActionTrack,
260+
"description":ActionTrack,
261+
"created_at":ActionIgnore,
262+
"updated_at":ActionTrack,
263+
"is_default":ActionTrack,
264+
"display_name":ActionTrack,
265+
"icon":ActionTrack,
266+
},
257267
}
258268

259269
// auditMap converts a map of struct pointers to a map of struct names as

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp