mirror of
https://github.com/coder/coder.git
synced 2026-06-02 20:48:20 +00:00
5a8d0016a5
> Mux updated this PR on behalf of Mike. ## Stack Context This PR is the storage, permissions, API, and SDK layer for experimental personal skills. #25362 has landed on `main`, so this branch is restacked directly on `main`. Stack order: 1. #25363 storage, permissions, API, and SDK 2. #25365 API test coverage 3. #25366 chattool and chatd integration 4. #25066 settings UI and docs 5. #25386 personal skills slash menu ## What? Adds the `user_skills` database table, generated queries, RBAC resources and scopes, audit resource handling, experimental user-scoped CRUD endpoints, SDK types, and generated API/site types. Follow-up review and restack fixes: - Enforce a bounded personal skill description in parser and database constraints. - Return `403 Forbidden` for unauthorized create and update attempts. - Return explicit conflict responses when soft-deleted users are targeted. - Keep user admins out of personal skills, while site owners can read and delete but not create or update. - Document trigger-raised constraint names and keep schema constants covered by tests. - Reuse `UserSkillMetadata` in the full `UserSkill` SDK response type. - Generate user skill IDs in Go instead of relying on a database default. - Rebase on latest `main` and renumber the user skills migration to `000502_user_skills`. ## Why? Personal skills need durable user-owned storage with owner authorization, limited site-owner moderation, and a hidden API surface before chatd can consume them. ## Validation - `make gen` - `go test ./coderd/database -run '^TestUserSkillSchemaConstants$' -count=1` - `go test ./coderd/database/dbauthz -run '^TestMethodTestSuite/TestUserSkills$' -count=1` - `go test ./coderd -run '^TestPatchUserSkill$' -count=1` - `go test ./codersdk ./coderd/database/db2sdk` - `make lint` - pre-commit hook on `97fd58108d`
77 lines
2.1 KiB
Go
77 lines
2.1 KiB
Go
package audit
|
|
|
|
import (
|
|
"github.com/coder/coder/v2/coderd/database"
|
|
"github.com/coder/coder/v2/coderd/idpsync"
|
|
)
|
|
|
|
// Auditable is mostly a marker interface. It contains a definitive list of all
|
|
// auditable types. If you want to audit a new type, first define it in
|
|
// AuditableResources, then add it to this interface.
|
|
type Auditable interface {
|
|
database.APIKey |
|
|
database.Template |
|
|
database.TemplateVersion |
|
|
database.User |
|
|
database.WorkspaceTable |
|
|
database.GitSSHKey |
|
|
database.WorkspaceBuild |
|
|
database.AuditableGroup |
|
|
database.License |
|
|
database.WorkspaceProxy |
|
|
database.AuditOAuthConvertState |
|
|
database.HealthSettings |
|
|
database.NotificationsSettings |
|
|
database.OAuth2ProviderApp |
|
|
database.OAuth2ProviderAppSecret |
|
|
database.PrebuildsSettings |
|
|
database.CustomRole |
|
|
database.AuditableOrganizationMember |
|
|
database.Organization |
|
|
database.NotificationTemplate |
|
|
idpsync.OrganizationSyncSettings |
|
|
idpsync.GroupSyncSettings |
|
|
idpsync.RoleSyncSettings |
|
|
database.TaskTable |
|
|
database.AiSeatState |
|
|
database.AIProvider |
|
|
database.AIProviderKey |
|
|
database.Chat |
|
|
database.AuditableGroupAiBudget |
|
|
database.UserSecret |
|
|
database.UserSkill
|
|
}
|
|
|
|
// Map is a map of changed fields in an audited resource. It maps field names to
|
|
// the old and new value for that field.
|
|
type Map map[string]OldNew
|
|
|
|
// OldNew is a pair of values representing the old value and the new value.
|
|
type OldNew struct {
|
|
Old any
|
|
New any
|
|
Secret bool
|
|
}
|
|
|
|
// Empty returns a default value of type T.
|
|
func Empty[T Auditable]() T {
|
|
var t T
|
|
return t
|
|
}
|
|
|
|
// Diff compares two auditable resources and produces a Map of the changed
|
|
// values.
|
|
func Diff[T Auditable](a Auditor, left, right T) Map { return a.diff(left, right) }
|
|
|
|
// Differ is used so the enterprise version can implement the diff function in
|
|
// the Auditor feature interface. Only types in the same package as the
|
|
// interface can implement unexported methods.
|
|
type Differ struct {
|
|
DiffFn func(old, newVal any) Map
|
|
}
|
|
|
|
//nolint:unused
|
|
func (d Differ) diff(old, newVal any) Map {
|
|
return d.DiffFn(old, newVal)
|
|
}
|