From f2983164f550be7bb4fa2bc8b0536e446913111d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=B1=E3=82=A4=E3=83=A9?= Date: Mon, 7 Jul 2025 11:01:17 -0600 Subject: [PATCH] chore: fix some small groups and acl typos (#18732) - Add `format:"uri"` to `Group.AvatarURL` (matches `User.AvatarURL` field) - `` and `` were backwards in the `example:` tags - The `@Success` annotation for `/acl [get]` had an incorrect type --- coderd/apidoc/docs.go | 85 +++++++++++++++-- coderd/apidoc/swagger.json | 82 ++++++++++++++-- codersdk/groups.go | 2 +- codersdk/templates.go | 4 +- docs/reference/api/enterprise.md | 156 +++++++++++++++---------------- docs/reference/api/schemas.md | 135 +++++++++++++++++++++++++- enterprise/coderd/templates.go | 2 +- 7 files changed, 362 insertions(+), 104 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index e102b6f22f..1ee6ea77af 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -5211,10 +5211,7 @@ const docTemplate = `{ "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/codersdk.TemplateUser" - } + "$ref": "#/definitions/codersdk.TemplateACL" } } } @@ -12868,7 +12865,8 @@ const docTemplate = `{ "type": "object", "properties": { "avatar_url": { - "type": "string" + "type": "string", + "format": "uri" }, "display_name": { "type": "string" @@ -16011,6 +16009,23 @@ const docTemplate = `{ } } }, + "codersdk.TemplateACL": { + "type": "object", + "properties": { + "group": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.TemplateGroup" + } + }, + "users": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.TemplateUser" + } + } + } + }, "codersdk.TemplateAppUsage": { "type": "object", "properties": { @@ -16143,6 +16158,62 @@ const docTemplate = `{ } } }, + "codersdk.TemplateGroup": { + "type": "object", + "properties": { + "avatar_url": { + "type": "string", + "format": "uri" + }, + "display_name": { + "type": "string" + }, + "id": { + "type": "string", + "format": "uuid" + }, + "members": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.ReducedUser" + } + }, + "name": { + "type": "string" + }, + "organization_display_name": { + "type": "string" + }, + "organization_id": { + "type": "string", + "format": "uuid" + }, + "organization_name": { + "type": "string" + }, + "quota_allowance": { + "type": "integer" + }, + "role": { + "enum": [ + "admin", + "use" + ], + "allOf": [ + { + "$ref": "#/definitions/codersdk.TemplateRole" + } + ] + }, + "source": { + "$ref": "#/definitions/codersdk.GroupSource" + }, + "total_member_count": { + "description": "How many members are in this group. Shows the total count,\neven if the user is not authorized to read group member details.\nMay be greater than ` + "`" + `len(Group.Members)` + "`" + `.", + "type": "integer" + } + } + }, "codersdk.TemplateInsightsIntervalReport": { "type": "object", "properties": { @@ -16764,7 +16835,7 @@ const docTemplate = `{ }, "example": { "8bd26b20-f3e8-48be-a903-46bb920cf671": "use", - "\u003cuser_id\u003e\u003e": "admin" + "\u003cgroup_id\u003e": "admin" } }, "user_perms": { @@ -16775,7 +16846,7 @@ const docTemplate = `{ }, "example": { "4df59e74-c027-470b-ab4d-cbba8963a5e9": "use", - "\u003cgroup_id\u003e": "admin" + "\u003cuser_id\u003e": "admin" } } } diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 95a08f2f53..b55a08caa8 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -4590,10 +4590,7 @@ "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/codersdk.TemplateUser" - } + "$ref": "#/definitions/codersdk.TemplateACL" } } } @@ -11549,7 +11546,8 @@ "type": "object", "properties": { "avatar_url": { - "type": "string" + "type": "string", + "format": "uri" }, "display_name": { "type": "string" @@ -14575,6 +14573,23 @@ } } }, + "codersdk.TemplateACL": { + "type": "object", + "properties": { + "group": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.TemplateGroup" + } + }, + "users": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.TemplateUser" + } + } + } + }, "codersdk.TemplateAppUsage": { "type": "object", "properties": { @@ -14701,6 +14716,59 @@ } } }, + "codersdk.TemplateGroup": { + "type": "object", + "properties": { + "avatar_url": { + "type": "string", + "format": "uri" + }, + "display_name": { + "type": "string" + }, + "id": { + "type": "string", + "format": "uuid" + }, + "members": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.ReducedUser" + } + }, + "name": { + "type": "string" + }, + "organization_display_name": { + "type": "string" + }, + "organization_id": { + "type": "string", + "format": "uuid" + }, + "organization_name": { + "type": "string" + }, + "quota_allowance": { + "type": "integer" + }, + "role": { + "enum": ["admin", "use"], + "allOf": [ + { + "$ref": "#/definitions/codersdk.TemplateRole" + } + ] + }, + "source": { + "$ref": "#/definitions/codersdk.GroupSource" + }, + "total_member_count": { + "description": "How many members are in this group. Shows the total count,\neven if the user is not authorized to read group member details.\nMay be greater than `len(Group.Members)`.", + "type": "integer" + } + } + }, "codersdk.TemplateInsightsIntervalReport": { "type": "object", "properties": { @@ -15287,7 +15355,7 @@ }, "example": { "8bd26b20-f3e8-48be-a903-46bb920cf671": "use", - "\u003cuser_id\u003e\u003e": "admin" + "\u003cgroup_id\u003e": "admin" } }, "user_perms": { @@ -15298,7 +15366,7 @@ }, "example": { "4df59e74-c027-470b-ab4d-cbba8963a5e9": "use", - "\u003cgroup_id\u003e": "admin" + "\u003cuser_id\u003e": "admin" } } } diff --git a/codersdk/groups.go b/codersdk/groups.go index 26ef7f829f..d458a67839 100644 --- a/codersdk/groups.go +++ b/codersdk/groups.go @@ -36,7 +36,7 @@ type Group struct { // even if the user is not authorized to read group member details. // May be greater than `len(Group.Members)`. TotalMemberCount int `json:"total_member_count"` - AvatarURL string `json:"avatar_url"` + AvatarURL string `json:"avatar_url" format:"uri"` QuotaAllowance int `json:"quota_allowance"` Source GroupSource `json:"source"` OrganizationName string `json:"organization_name"` diff --git a/codersdk/templates.go b/codersdk/templates.go index c0ea8c4137..a7d983bc1c 100644 --- a/codersdk/templates.go +++ b/codersdk/templates.go @@ -194,9 +194,9 @@ type TemplateUser struct { type UpdateTemplateACL struct { // UserPerms should be a mapping of user id to role. The user id must be the // uuid of the user, not a username or email address. - UserPerms map[string]TemplateRole `json:"user_perms,omitempty" example:":admin,4df59e74-c027-470b-ab4d-cbba8963a5e9:use"` + UserPerms map[string]TemplateRole `json:"user_perms,omitempty" example:":admin,4df59e74-c027-470b-ab4d-cbba8963a5e9:use"` // GroupPerms should be a mapping of group id to role. - GroupPerms map[string]TemplateRole `json:"group_perms,omitempty" example:">:admin,8bd26b20-f3e8-48be-a903-46bb920cf671:use"` + GroupPerms map[string]TemplateRole `json:"group_perms,omitempty" example:":admin,8bd26b20-f3e8-48be-a903-46bb920cf671:use"` } // ACLAvailable is a list of users and groups that can be added to a template diff --git a/docs/reference/api/enterprise.md b/docs/reference/api/enterprise.md index f1ff4a0bae..70821aa64f 100644 --- a/docs/reference/api/enterprise.md +++ b/docs/reference/api/enterprise.md @@ -289,7 +289,7 @@ curl -X GET http://coder-server:8080/api/v2/groups?organization=string&has_membe ```json [ { - "avatar_url": "string", + "avatar_url": "http://example.com", "display_name": "string", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "members": [ @@ -331,7 +331,7 @@ Status Code **200** | Name | Type | Required | Restrictions | Description | |-------------------------------|--------------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `[array item]` | array | false | | | -| `» avatar_url` | string | false | | | +| `» avatar_url` | string(uri) | false | | | | `» display_name` | string | false | | | | `» id` | string(uuid) | false | | | | `» members` | array | false | | | @@ -396,7 +396,7 @@ curl -X GET http://coder-server:8080/api/v2/groups/{group} \ ```json { - "avatar_url": "string", + "avatar_url": "http://example.com", "display_name": "string", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "members": [ @@ -457,7 +457,7 @@ curl -X DELETE http://coder-server:8080/api/v2/groups/{group} \ ```json { - "avatar_url": "string", + "avatar_url": "http://example.com", "display_name": "string", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "members": [ @@ -537,7 +537,7 @@ curl -X PATCH http://coder-server:8080/api/v2/groups/{group} \ ```json { - "avatar_url": "string", + "avatar_url": "http://example.com", "display_name": "string", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "members": [ @@ -1508,7 +1508,7 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/groups ```json [ { - "avatar_url": "string", + "avatar_url": "http://example.com", "display_name": "string", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "members": [ @@ -1550,7 +1550,7 @@ Status Code **200** | Name | Type | Required | Restrictions | Description | |-------------------------------|--------------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `[array item]` | array | false | | | -| `» avatar_url` | string | false | | | +| `» avatar_url` | string(uri) | false | | | | `» display_name` | string | false | | | | `» id` | string(uuid) | false | | | | `» members` | array | false | | | @@ -1628,7 +1628,7 @@ curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/groups ```json { - "avatar_url": "string", + "avatar_url": "http://example.com", "display_name": "string", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "members": [ @@ -1690,7 +1690,7 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/groups/ ```json { - "avatar_url": "string", + "avatar_url": "http://example.com", "display_name": "string", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "members": [ @@ -3379,79 +3379,71 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/acl \ > 200 Response ```json -[ - { - "avatar_url": "http://example.com", - "created_at": "2019-08-24T14:15:22Z", - "email": "user@example.com", - "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", - "last_seen_at": "2019-08-24T14:15:22Z", - "login_type": "", - "name": "string", - "organization_ids": [ - "497f6eca-6276-4993-bfeb-53cbbbba6f08" - ], - "role": "admin", - "roles": [ - { - "display_name": "string", - "name": "string", - "organization_id": "string" - } - ], - "status": "active", - "theme_preference": "string", - "updated_at": "2019-08-24T14:15:22Z", - "username": "string" - } -] +{ + "group": [ + { + "avatar_url": "http://example.com", + "display_name": "string", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "members": [ + { + "avatar_url": "http://example.com", + "created_at": "2019-08-24T14:15:22Z", + "email": "user@example.com", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "last_seen_at": "2019-08-24T14:15:22Z", + "login_type": "", + "name": "string", + "status": "active", + "theme_preference": "string", + "updated_at": "2019-08-24T14:15:22Z", + "username": "string" + } + ], + "name": "string", + "organization_display_name": "string", + "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6", + "organization_name": "string", + "quota_allowance": 0, + "role": "admin", + "source": "user", + "total_member_count": 0 + } + ], + "users": [ + { + "avatar_url": "http://example.com", + "created_at": "2019-08-24T14:15:22Z", + "email": "user@example.com", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "last_seen_at": "2019-08-24T14:15:22Z", + "login_type": "", + "name": "string", + "organization_ids": [ + "497f6eca-6276-4993-bfeb-53cbbbba6f08" + ], + "role": "admin", + "roles": [ + { + "display_name": "string", + "name": "string", + "organization_id": "string" + } + ], + "status": "active", + "theme_preference": "string", + "updated_at": "2019-08-24T14:15:22Z", + "username": "string" + } + ] +} ``` ### Responses -| Status | Meaning | Description | Schema | -|--------|---------------------------------------------------------|-------------|-------------------------------------------------------------------| -| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | array of [codersdk.TemplateUser](schemas.md#codersdktemplateuser) | - -

Response Schema

- -Status Code **200** - -| Name | Type | Required | Restrictions | Description | -|----------------------|----------------------------------------------------------|----------|--------------|--------------------------------------------------------------------------------------------| -| `[array item]` | array | false | | | -| `» avatar_url` | string(uri) | false | | | -| `» created_at` | string(date-time) | true | | | -| `» email` | string(email) | true | | | -| `» id` | string(uuid) | true | | | -| `» last_seen_at` | string(date-time) | false | | | -| `» login_type` | [codersdk.LoginType](schemas.md#codersdklogintype) | false | | | -| `» name` | string | false | | | -| `» organization_ids` | array | false | | | -| `» role` | [codersdk.TemplateRole](schemas.md#codersdktemplaterole) | false | | | -| `» roles` | array | false | | | -| `»» display_name` | string | false | | | -| `»» name` | string | false | | | -| `»» organization_id` | string | false | | | -| `» status` | [codersdk.UserStatus](schemas.md#codersdkuserstatus) | false | | | -| `» theme_preference` | string | false | | Deprecated: this value should be retrieved from `codersdk.UserPreferenceSettings` instead. | -| `» updated_at` | string(date-time) | false | | | -| `» username` | string | true | | | - -#### Enumerated Values - -| Property | Value | -|--------------|-------------| -| `login_type` | `` | -| `login_type` | `password` | -| `login_type` | `github` | -| `login_type` | `oidc` | -| `login_type` | `token` | -| `login_type` | `none` | -| `role` | `admin` | -| `role` | `use` | -| `status` | `active` | -| `status` | `suspended` | +| Status | Meaning | Description | Schema | +|--------|---------------------------------------------------------|-------------|--------------------------------------------------------| +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.TemplateACL](schemas.md#codersdktemplateacl) | To perform this operation, you must be authenticated. [Learn more](authentication.md). @@ -3475,11 +3467,11 @@ curl -X PATCH http://coder-server:8080/api/v2/templates/{template}/acl \ { "group_perms": { "8bd26b20-f3e8-48be-a903-46bb920cf671": "use", - ">": "admin" + "": "admin" }, "user_perms": { "4df59e74-c027-470b-ab4d-cbba8963a5e9": "use", - "": "admin" + "": "admin" } } ``` @@ -3544,7 +3536,7 @@ curl -X GET http://coder-server:8080/api/v2/templates/{template}/acl/available \ { "groups": [ { - "avatar_url": "string", + "avatar_url": "http://example.com", "display_name": "string", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "members": [ @@ -3604,7 +3596,7 @@ Status Code **200** |--------------------------------|--------------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| | `[array item]` | array | false | | | | `» groups` | array | false | | | -| `»» avatar_url` | string | false | | | +| `»» avatar_url` | string(uri) | false | | | | `»» display_name` | string | false | | | | `»» id` | string(uuid) | false | | | | `»» members` | array | false | | | diff --git a/docs/reference/api/schemas.md b/docs/reference/api/schemas.md index 281a3a8a19..973797d52d 100644 --- a/docs/reference/api/schemas.md +++ b/docs/reference/api/schemas.md @@ -283,7 +283,7 @@ { "groups": [ { - "avatar_url": "string", + "avatar_url": "http://example.com", "display_name": "string", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "members": [ @@ -3423,7 +3423,7 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith ```json { - "avatar_url": "string", + "avatar_url": "http://example.com", "display_name": "string", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "members": [ @@ -6760,6 +6760,76 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith |---------------|-------------| | `provisioner` | `terraform` | +## codersdk.TemplateACL + +```json +{ + "group": [ + { + "avatar_url": "http://example.com", + "display_name": "string", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "members": [ + { + "avatar_url": "http://example.com", + "created_at": "2019-08-24T14:15:22Z", + "email": "user@example.com", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "last_seen_at": "2019-08-24T14:15:22Z", + "login_type": "", + "name": "string", + "status": "active", + "theme_preference": "string", + "updated_at": "2019-08-24T14:15:22Z", + "username": "string" + } + ], + "name": "string", + "organization_display_name": "string", + "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6", + "organization_name": "string", + "quota_allowance": 0, + "role": "admin", + "source": "user", + "total_member_count": 0 + } + ], + "users": [ + { + "avatar_url": "http://example.com", + "created_at": "2019-08-24T14:15:22Z", + "email": "user@example.com", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "last_seen_at": "2019-08-24T14:15:22Z", + "login_type": "", + "name": "string", + "organization_ids": [ + "497f6eca-6276-4993-bfeb-53cbbbba6f08" + ], + "role": "admin", + "roles": [ + { + "display_name": "string", + "name": "string", + "organization_id": "string" + } + ], + "status": "active", + "theme_preference": "string", + "updated_at": "2019-08-24T14:15:22Z", + "username": "string" + } + ] +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +|---------|-----------------------------------------------------------|----------|--------------|-------------| +| `group` | array of [codersdk.TemplateGroup](#codersdktemplategroup) | false | | | +| `users` | array of [codersdk.TemplateUser](#codersdktemplateuser) | false | | | + ## codersdk.TemplateAppUsage ```json @@ -6887,6 +6957,63 @@ Restarts will only happen on weekdays in this list on weeks which line up with W | `tags` | array of string | false | | | | `url` | string | false | | | +## codersdk.TemplateGroup + +```json +{ + "avatar_url": "http://example.com", + "display_name": "string", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "members": [ + { + "avatar_url": "http://example.com", + "created_at": "2019-08-24T14:15:22Z", + "email": "user@example.com", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "last_seen_at": "2019-08-24T14:15:22Z", + "login_type": "", + "name": "string", + "status": "active", + "theme_preference": "string", + "updated_at": "2019-08-24T14:15:22Z", + "username": "string" + } + ], + "name": "string", + "organization_display_name": "string", + "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6", + "organization_name": "string", + "quota_allowance": 0, + "role": "admin", + "source": "user", + "total_member_count": 0 +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +|-----------------------------|-------------------------------------------------------|----------|--------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `avatar_url` | string | false | | | +| `display_name` | string | false | | | +| `id` | string | false | | | +| `members` | array of [codersdk.ReducedUser](#codersdkreduceduser) | false | | | +| `name` | string | false | | | +| `organization_display_name` | string | false | | | +| `organization_id` | string | false | | | +| `organization_name` | string | false | | | +| `quota_allowance` | integer | false | | | +| `role` | [codersdk.TemplateRole](#codersdktemplaterole) | false | | | +| `source` | [codersdk.GroupSource](#codersdkgroupsource) | false | | | +| `total_member_count` | integer | false | | How many members are in this group. Shows the total count, even if the user is not authorized to read group member details. May be greater than `len(Group.Members)`. | + +#### Enumerated Values + +| Property | Value | +|----------|---------| +| `role` | `admin` | +| `role` | `use` | + ## codersdk.TemplateInsightsIntervalReport ```json @@ -7620,11 +7747,11 @@ Restarts will only happen on weekdays in this list on weeks which line up with W { "group_perms": { "8bd26b20-f3e8-48be-a903-46bb920cf671": "use", - ">": "admin" + "": "admin" }, "user_perms": { "4df59e74-c027-470b-ab4d-cbba8963a5e9": "use", - "": "admin" + "": "admin" } } ``` diff --git a/enterprise/coderd/templates.go b/enterprise/coderd/templates.go index b1f3d2cac3..4514ba928e 100644 --- a/enterprise/coderd/templates.go +++ b/enterprise/coderd/templates.go @@ -99,7 +99,7 @@ func (api *API) templateAvailablePermissions(rw http.ResponseWriter, r *http.Req // @Produce json // @Tags Enterprise // @Param template path string true "Template ID" format(uuid) -// @Success 200 {array} codersdk.TemplateUser +// @Success 200 {object} codersdk.TemplateACL // @Router /templates/{template}/acl [get] func (api *API) templateACL(rw http.ResponseWriter, r *http.Request) { var (