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
+272
View File
@@ -9514,6 +9514,212 @@ const docTemplate = `{
]
}
},
"/users/{user}/secrets": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Secrets"
],
"summary": "List user secrets",
"operationId": "list-user-secrets",
"parameters": [
{
"type": "string",
"description": "User ID, username, or me",
"name": "user",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/codersdk.UserSecret"
}
}
}
},
"security": [
{
"CoderSessionToken": []
}
]
},
"post": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Secrets"
],
"summary": "Create a new user secret",
"operationId": "create-a-new-user-secret",
"parameters": [
{
"type": "string",
"description": "User ID, username, or me",
"name": "user",
"in": "path",
"required": true
},
{
"description": "Create secret request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/codersdk.CreateUserSecretRequest"
}
}
],
"responses": {
"201": {
"description": "Created",
"schema": {
"$ref": "#/definitions/codersdk.UserSecret"
}
}
},
"security": [
{
"CoderSessionToken": []
}
]
}
},
"/users/{user}/secrets/{name}": {
"get": {
"produces": [
"application/json"
],
"tags": [
"Secrets"
],
"summary": "Get a user secret by name",
"operationId": "get-a-user-secret-by-name",
"parameters": [
{
"type": "string",
"description": "User ID, username, or me",
"name": "user",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Secret name",
"name": "name",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/codersdk.UserSecret"
}
}
},
"security": [
{
"CoderSessionToken": []
}
]
},
"delete": {
"tags": [
"Secrets"
],
"summary": "Delete a user secret",
"operationId": "delete-a-user-secret",
"parameters": [
{
"type": "string",
"description": "User ID, username, or me",
"name": "user",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Secret name",
"name": "name",
"in": "path",
"required": true
}
],
"responses": {
"204": {
"description": "No Content"
}
},
"security": [
{
"CoderSessionToken": []
}
]
},
"patch": {
"consumes": [
"application/json"
],
"produces": [
"application/json"
],
"tags": [
"Secrets"
],
"summary": "Update a user secret",
"operationId": "update-a-user-secret",
"parameters": [
{
"type": "string",
"description": "User ID, username, or me",
"name": "user",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Secret name",
"name": "name",
"in": "path",
"required": true
},
{
"description": "Update secret request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/codersdk.UpdateUserSecretRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/codersdk.UserSecret"
}
}
},
"security": [
{
"CoderSessionToken": []
}
]
}
},
"/users/{user}/status/activate": {
"put": {
"produces": [
@@ -15148,6 +15354,26 @@ const docTemplate = `{
}
}
},
"codersdk.CreateUserSecretRequest": {
"type": "object",
"properties": {
"description": {
"type": "string"
},
"env_name": {
"type": "string"
},
"file_path": {
"type": "string"
},
"name": {
"type": "string"
},
"value": {
"type": "string"
}
}
},
"codersdk.CreateWorkspaceBuildReason": {
"type": "string",
"enum": [
@@ -21277,6 +21503,23 @@ const docTemplate = `{
}
}
},
"codersdk.UpdateUserSecretRequest": {
"type": "object",
"properties": {
"description": {
"type": "string"
},
"env_name": {
"type": "string"
},
"file_path": {
"type": "string"
},
"value": {
"type": "string"
}
}
},
"codersdk.UpdateWorkspaceACL": {
"type": "object",
"properties": {
@@ -21732,6 +21975,35 @@ const docTemplate = `{
}
}
},
"codersdk.UserSecret": {
"type": "object",
"properties": {
"created_at": {
"type": "string",
"format": "date-time"
},
"description": {
"type": "string"
},
"env_name": {
"type": "string"
},
"file_path": {
"type": "string"
},
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
},
"codersdk.UserStatus": {
"type": "string",
"enum": [
+250
View File
@@ -8431,6 +8431,190 @@
]
}
},
"/users/{user}/secrets": {
"get": {
"produces": ["application/json"],
"tags": ["Secrets"],
"summary": "List user secrets",
"operationId": "list-user-secrets",
"parameters": [
{
"type": "string",
"description": "User ID, username, or me",
"name": "user",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"type": "array",
"items": {
"$ref": "#/definitions/codersdk.UserSecret"
}
}
}
},
"security": [
{
"CoderSessionToken": []
}
]
},
"post": {
"consumes": ["application/json"],
"produces": ["application/json"],
"tags": ["Secrets"],
"summary": "Create a new user secret",
"operationId": "create-a-new-user-secret",
"parameters": [
{
"type": "string",
"description": "User ID, username, or me",
"name": "user",
"in": "path",
"required": true
},
{
"description": "Create secret request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/codersdk.CreateUserSecretRequest"
}
}
],
"responses": {
"201": {
"description": "Created",
"schema": {
"$ref": "#/definitions/codersdk.UserSecret"
}
}
},
"security": [
{
"CoderSessionToken": []
}
]
}
},
"/users/{user}/secrets/{name}": {
"get": {
"produces": ["application/json"],
"tags": ["Secrets"],
"summary": "Get a user secret by name",
"operationId": "get-a-user-secret-by-name",
"parameters": [
{
"type": "string",
"description": "User ID, username, or me",
"name": "user",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Secret name",
"name": "name",
"in": "path",
"required": true
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/codersdk.UserSecret"
}
}
},
"security": [
{
"CoderSessionToken": []
}
]
},
"delete": {
"tags": ["Secrets"],
"summary": "Delete a user secret",
"operationId": "delete-a-user-secret",
"parameters": [
{
"type": "string",
"description": "User ID, username, or me",
"name": "user",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Secret name",
"name": "name",
"in": "path",
"required": true
}
],
"responses": {
"204": {
"description": "No Content"
}
},
"security": [
{
"CoderSessionToken": []
}
]
},
"patch": {
"consumes": ["application/json"],
"produces": ["application/json"],
"tags": ["Secrets"],
"summary": "Update a user secret",
"operationId": "update-a-user-secret",
"parameters": [
{
"type": "string",
"description": "User ID, username, or me",
"name": "user",
"in": "path",
"required": true
},
{
"type": "string",
"description": "Secret name",
"name": "name",
"in": "path",
"required": true
},
{
"description": "Update secret request",
"name": "request",
"in": "body",
"required": true,
"schema": {
"$ref": "#/definitions/codersdk.UpdateUserSecretRequest"
}
}
],
"responses": {
"200": {
"description": "OK",
"schema": {
"$ref": "#/definitions/codersdk.UserSecret"
}
}
},
"security": [
{
"CoderSessionToken": []
}
]
}
},
"/users/{user}/status/activate": {
"put": {
"produces": ["application/json"],
@@ -13649,6 +13833,26 @@
}
}
},
"codersdk.CreateUserSecretRequest": {
"type": "object",
"properties": {
"description": {
"type": "string"
},
"env_name": {
"type": "string"
},
"file_path": {
"type": "string"
},
"name": {
"type": "string"
},
"value": {
"type": "string"
}
}
},
"codersdk.CreateWorkspaceBuildReason": {
"type": "string",
"enum": [
@@ -19551,6 +19755,23 @@
}
}
},
"codersdk.UpdateUserSecretRequest": {
"type": "object",
"properties": {
"description": {
"type": "string"
},
"env_name": {
"type": "string"
},
"file_path": {
"type": "string"
},
"value": {
"type": "string"
}
}
},
"codersdk.UpdateWorkspaceACL": {
"type": "object",
"properties": {
@@ -19981,6 +20202,35 @@
}
}
},
"codersdk.UserSecret": {
"type": "object",
"properties": {
"created_at": {
"type": "string",
"format": "date-time"
},
"description": {
"type": "string"
},
"env_name": {
"type": "string"
},
"file_path": {
"type": "string"
},
"id": {
"type": "string",
"format": "uuid"
},
"name": {
"type": "string"
},
"updated_at": {
"type": "string",
"format": "date-time"
}
}
},
"codersdk.UserStatus": {
"type": "string",
"enum": ["active", "dormant", "suspended"],