feat: add REST API handlers and client methods for user secrets (#24107)

Add the five REST endpoints for managing user secrets, SDK client
methods, and handler tests.

Endpoints:
- `POST /api/v2/users/{user}/secrets`
- `GET /api/v2/users/{user}/secrets`
- `GET /api/v2/users/{user}/secrets/{name}`
- `PATCH /api/v2/users/{user}/secrets/{name}`
- `DELETE /api/v2/users/{user}/secrets/{name}`

Routes are registered under the existing `/{user}` group with
`ExtractUserParam`. The delete query was changed from `:exec` to
`:execrows` so the handler can distinguish "not found" from success
(DELETE with `:exec` silently returns nil for zero affected rows).
This commit is contained in:
Zach
2026-04-09 12:12:55 -06:00
committed by GitHub
parent ad2415ede7
commit 95cff8c5fb
17 changed files with 1631 additions and 17 deletions
+4
View File
@@ -1526,6 +1526,10 @@
"title": "Schemas",
"path": "./reference/api/schemas.md"
},
{
"title": "Secrets",
"path": "./reference/api/secrets.md"
},
{
"title": "Tasks",
"path": "./reference/api/tasks.md"
+68
View File
@@ -2706,6 +2706,28 @@ This is required on creation to enable a user-flow of validating a template work
| `user_status` | [codersdk.UserStatus](#codersdkuserstatus) | false | | User status defaults to UserStatusDormant. |
| `username` | string | true | | |
## codersdk.CreateUserSecretRequest
```json
{
"description": "string",
"env_name": "string",
"file_path": "string",
"name": "string",
"value": "string"
}
```
### Properties
| Name | Type | Required | Restrictions | Description |
|---------------|--------|----------|--------------|-------------|
| `description` | string | false | | |
| `env_name` | string | false | | |
| `file_path` | string | false | | |
| `name` | string | false | | |
| `value` | string | false | | |
## codersdk.CreateWorkspaceBuildReason
```json
@@ -10588,6 +10610,26 @@ Restarts will only happen on weekdays in this list on weeks which line up with W
The schedule must be daily with a single time, and should have a timezone specified via a CRON_TZ prefix (otherwise UTC will be used).
If the schedule is empty, the user will be updated to use the default schedule.|
## codersdk.UpdateUserSecretRequest
```json
{
"description": "string",
"env_name": "string",
"file_path": "string",
"value": "string"
}
```
### Properties
| Name | Type | Required | Restrictions | Description |
|---------------|--------|----------|--------------|-------------|
| `description` | string | false | | |
| `env_name` | string | false | | |
| `file_path` | string | false | | |
| `value` | string | false | | |
## codersdk.UpdateWorkspaceACL
```json
@@ -11146,6 +11188,32 @@ If the schedule is empty, the user will be updated to use the default schedule.|
| `user_can_set` | boolean | false | | User can set is true if the user is allowed to set their own quiet hours schedule. If false, the user cannot set a custom schedule and the default schedule will always be used. |
| `user_set` | boolean | false | | User set is true if the user has set their own quiet hours schedule. If false, the user is using the default schedule. |
## codersdk.UserSecret
```json
{
"created_at": "2019-08-24T14:15:22Z",
"description": "string",
"env_name": "string",
"file_path": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"name": "string",
"updated_at": "2019-08-24T14:15:22Z"
}
```
### Properties
| Name | Type | Required | Restrictions | Description |
|---------------|--------|----------|--------------|-------------|
| `created_at` | string | false | | |
| `description` | string | false | | |
| `env_name` | string | false | | |
| `file_path` | string | false | | |
| `id` | string | false | | |
| `name` | string | false | | |
| `updated_at` | string | false | | |
## codersdk.UserStatus
```json
+246
View File
@@ -0,0 +1,246 @@
# Secrets
## List user secrets
### Code samples
```shell
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/secrets \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
```
`GET /users/{user}/secrets`
### Parameters
| Name | In | Type | Required | Description |
|--------|------|--------|----------|--------------------------|
| `user` | path | string | true | User ID, username, or me |
### Example responses
> 200 Response
```json
[
{
"created_at": "2019-08-24T14:15:22Z",
"description": "string",
"env_name": "string",
"file_path": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"name": "string",
"updated_at": "2019-08-24T14:15:22Z"
}
]
```
### Responses
| Status | Meaning | Description | Schema |
|--------|---------------------------------------------------------|-------------|---------------------------------------------------------------|
| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | array of [codersdk.UserSecret](schemas.md#codersdkusersecret) |
<h3 id="list-user-secrets-responseschema">Response Schema</h3>
Status Code **200**
| Name | Type | Required | Restrictions | Description |
|-----------------|-------------------|----------|--------------|-------------|
| `[array item]` | array | false | | |
| `» created_at` | string(date-time) | false | | |
| `» description` | string | false | | |
| `» env_name` | string | false | | |
| `» file_path` | string | false | | |
| `» id` | string(uuid) | false | | |
| `» name` | string | false | | |
| `» updated_at` | string(date-time) | false | | |
To perform this operation, you must be authenticated. [Learn more](authentication.md).
## Create a new user secret
### Code samples
```shell
# Example request using curl
curl -X POST http://coder-server:8080/api/v2/users/{user}/secrets \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
```
`POST /users/{user}/secrets`
> Body parameter
```json
{
"description": "string",
"env_name": "string",
"file_path": "string",
"name": "string",
"value": "string"
}
```
### Parameters
| Name | In | Type | Required | Description |
|--------|------|--------------------------------------------------------------------------------|----------|--------------------------|
| `user` | path | string | true | User ID, username, or me |
| `body` | body | [codersdk.CreateUserSecretRequest](schemas.md#codersdkcreateusersecretrequest) | true | Create secret request |
### Example responses
> 201 Response
```json
{
"created_at": "2019-08-24T14:15:22Z",
"description": "string",
"env_name": "string",
"file_path": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"name": "string",
"updated_at": "2019-08-24T14:15:22Z"
}
```
### Responses
| Status | Meaning | Description | Schema |
|--------|--------------------------------------------------------------|-------------|------------------------------------------------------|
| 201 | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created | [codersdk.UserSecret](schemas.md#codersdkusersecret) |
To perform this operation, you must be authenticated. [Learn more](authentication.md).
## Get a user secret by name
### Code samples
```shell
# Example request using curl
curl -X GET http://coder-server:8080/api/v2/users/{user}/secrets/{name} \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
```
`GET /users/{user}/secrets/{name}`
### Parameters
| Name | In | Type | Required | Description |
|--------|------|--------|----------|--------------------------|
| `user` | path | string | true | User ID, username, or me |
| `name` | path | string | true | Secret name |
### Example responses
> 200 Response
```json
{
"created_at": "2019-08-24T14:15:22Z",
"description": "string",
"env_name": "string",
"file_path": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"name": "string",
"updated_at": "2019-08-24T14:15:22Z"
}
```
### Responses
| Status | Meaning | Description | Schema |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------|
| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.UserSecret](schemas.md#codersdkusersecret) |
To perform this operation, you must be authenticated. [Learn more](authentication.md).
## Delete a user secret
### Code samples
```shell
# Example request using curl
curl -X DELETE http://coder-server:8080/api/v2/users/{user}/secrets/{name} \
-H 'Coder-Session-Token: API_KEY'
```
`DELETE /users/{user}/secrets/{name}`
### Parameters
| Name | In | Type | Required | Description |
|--------|------|--------|----------|--------------------------|
| `user` | path | string | true | User ID, username, or me |
| `name` | path | string | true | Secret name |
### Responses
| Status | Meaning | Description | Schema |
|--------|-----------------------------------------------------------------|-------------|--------|
| 204 | [No Content](https://tools.ietf.org/html/rfc7231#section-6.3.5) | No Content | |
To perform this operation, you must be authenticated. [Learn more](authentication.md).
## Update a user secret
### Code samples
```shell
# Example request using curl
curl -X PATCH http://coder-server:8080/api/v2/users/{user}/secrets/{name} \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'Coder-Session-Token: API_KEY'
```
`PATCH /users/{user}/secrets/{name}`
> Body parameter
```json
{
"description": "string",
"env_name": "string",
"file_path": "string",
"value": "string"
}
```
### Parameters
| Name | In | Type | Required | Description |
|--------|------|--------------------------------------------------------------------------------|----------|--------------------------|
| `user` | path | string | true | User ID, username, or me |
| `name` | path | string | true | Secret name |
| `body` | body | [codersdk.UpdateUserSecretRequest](schemas.md#codersdkupdateusersecretrequest) | true | Update secret request |
### Example responses
> 200 Response
```json
{
"created_at": "2019-08-24T14:15:22Z",
"description": "string",
"env_name": "string",
"file_path": "string",
"id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
"name": "string",
"updated_at": "2019-08-24T14:15:22Z"
}
```
### Responses
| Status | Meaning | Description | Schema |
|--------|---------------------------------------------------------|-------------|------------------------------------------------------|
| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.UserSecret](schemas.md#codersdkusersecret) |
To perform this operation, you must be authenticated. [Learn more](authentication.md).