From 8e9cbdd71ba7554bc498d0fccbaf27167d5a2c56 Mon Sep 17 00:00:00 2001 From: Marcin Tojek Date: Wed, 11 Jan 2023 14:08:04 +0100 Subject: [PATCH] docs: API users (#5620) * docs: audit, deploymentconfig, files, parameters * Swagger comments in workspacebuilds.go * structs in workspacebuilds.go * workspaceagents: instance identity * workspaceagents.go in progress * workspaceagents.go in progress * Agents * workspacebuilds.go * /workspaces * templates.go, templateversions.go * templateversion.go in progress * cancel * templateversions * wip * Merge * x-apidocgen * NullTime hack not needed anymore * Fix: x-apidocgen * Members * Fixes * Fix * WIP * WIP * Users * Logout * User profile * Status suspend activate * User roles * User tokens * Keys * SSH key * All * Typo * Fix * Fix * Fix: LoginWithPasswordRequest --- cli/userstatus_test.go | 6 +- coderd/apidoc/docs.go | 1365 +++++++++++++++++++++++++++++++++++- coderd/apidoc/swagger.json | 1215 ++++++++++++++++++++++++++++++-- coderd/apikey.go | 47 +- coderd/coderd.go | 4 +- coderd/gitsshkey.go | 16 + coderd/members.go | 4 +- coderd/roles.go | 12 +- coderd/templateversions.go | 3 + coderd/userauth.go | 21 + coderd/users.go | 151 ++++ coderd/workspacebuilds.go | 10 + coderd/workspaces.go | 6 +- codersdk/apikey.go | 16 +- codersdk/gitsshkey.go | 6 +- codersdk/organizations.go | 6 +- codersdk/templates.go | 6 +- codersdk/users.go | 6 +- docs/api/audit.md | 2 +- docs/api/authorization.md | 47 ++ docs/api/builds.md | 144 ++++ docs/api/members.md | 56 +- docs/api/schemas.md | 311 +++++++- docs/api/templates.md | 61 +- docs/api/users.md | 1137 ++++++++++++++++++++++++++++++ docs/api/workspaces.md | 4 +- docs/manifest.json | 8 +- 27 files changed, 4513 insertions(+), 157 deletions(-) create mode 100644 docs/api/users.md diff --git a/cli/userstatus_test.go b/cli/userstatus_test.go index aea26f8387228..05fe8898c82e6 100644 --- a/cli/userstatus_test.go +++ b/cli/userstatus_test.go @@ -33,7 +33,7 @@ func TestUserStatus(t *testing.T) { }) t.Run("StatusOther", func(t *testing.T) { - require.Equal(t, otherUser.Status, codersdk.UserStatusActive, "start as active") + require.Equal(t, codersdk.UserStatusActive, otherUser.Status, "start as active") cmd, root := clitest.New(t, "users", "suspend", otherUser.Username) clitest.SetupConfig(t, client, root) @@ -45,7 +45,7 @@ func TestUserStatus(t *testing.T) { // Check the user status otherUser, err = client.User(context.Background(), otherUser.Username) require.NoError(t, err, "fetch suspended user") - require.Equal(t, otherUser.Status, codersdk.UserStatusSuspended, "suspended user") + require.Equal(t, codersdk.UserStatusSuspended, otherUser.Status, "suspended user") // Set back to active. Try using a uuid as well cmd, root = clitest.New(t, "users", "activate", otherUser.ID.String()) @@ -58,6 +58,6 @@ func TestUserStatus(t *testing.T) { // Check the user status otherUser, err = client.User(context.Background(), otherUser.ID.String()) require.NoError(t, err, "fetch active user") - require.Equal(t, otherUser.Status, codersdk.UserStatusActive, "active user") + require.Equal(t, codersdk.UserStatusActive, otherUser.Status, "active user") }) } diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 8c74f2680154b..17fac114fc91b 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -506,15 +506,6 @@ const docTemplate = `{ "summary": "Assign role to organization member", "operationId": "assign-role-to-organization-member", "parameters": [ - { - "description": "Update roles request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/codersdk.UpdateRoles" - } - }, { "type": "string", "description": "Organization ID", @@ -524,10 +515,19 @@ const docTemplate = `{ }, { "type": "string", - "description": "Username, UUID, or me", + "description": "User ID, name, or me", "name": "user", "in": "path", "required": true + }, + { + "description": "Update roles request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.UpdateRoles" + } } ], "responses": { @@ -1195,6 +1195,25 @@ const docTemplate = `{ "name": "id", "in": "path", "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "After ID", + "name": "after_id", + "in": "query" + }, + { + "type": "integer", + "description": "Page limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Page offset", + "name": "offset", + "in": "query" } ], "responses": { @@ -1775,30 +1794,1016 @@ const docTemplate = `{ } } } - } - } - }, - "/updatecheck": { - "get": { - "produces": [ - "application/json" - ], - "tags": [ - "General" + } + } + }, + "/updatecheck": { + "get": { + "produces": [ + "application/json" + ], + "tags": [ + "General" + ], + "summary": "Update check", + "operationId": "update-check", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.UpdateCheckResponse" + } + } + } + } + }, + "/users": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get users", + "operationId": "get-users", + "parameters": [ + { + "type": "string", + "description": "Search query", + "name": "q", + "in": "query" + }, + { + "type": "string", + "format": "uuid", + "description": "After ID", + "name": "after_id", + "in": "query" + }, + { + "type": "integer", + "description": "Page limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Page offset", + "name": "offset", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.GetUsersResponse" + } + } + } + }, + "post": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Create new user", + "operationId": "create-new-user", + "parameters": [ + { + "description": "Create user request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.CreateUserRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/codersdk.User" + } + } + } + } + }, + "/users/authmethods": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get authentication methods", + "operationId": "get-authentication-methods", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.AuthMethods" + } + } + } + } + }, + "/users/first": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Check initial user created", + "operationId": "check-initial-user-created", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.Response" + } + } + } + }, + "post": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Create initial user", + "operationId": "create-initial-user", + "parameters": [ + { + "description": "First user request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.CreateFirstUserRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/codersdk.CreateFirstUserResponse" + } + } + } + } + }, + "/users/login": { + "post": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Authorization" + ], + "summary": "Log in user", + "operationId": "log-in-user", + "parameters": [ + { + "description": "Login request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.LoginWithPasswordRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/codersdk.LoginWithPasswordResponse" + } + } + } + } + }, + "/users/logout": { + "post": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Log out user", + "operationId": "log-out-user", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.Response" + } + } + } + } + }, + "/users/oauth2/github/callback": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "OAuth 2.0 GitHub Callback", + "operationId": "oauth2-github-callback", + "responses": { + "307": { + "description": "Temporary Redirect" + } + } + } + }, + "/users/oidc/callback": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "OpenID Connect Callback", + "operationId": "oidc-callback", + "responses": { + "307": { + "description": "Temporary Redirect" + } + } + } + }, + "/users/roles": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Members" + ], + "summary": "Get site member roles", + "operationId": "get-site-member-roles", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.AssignableRoles" + } + } + } + } + } + }, + "/users/{user}": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get user by name", + "operationId": "get-user-by-name", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.User" + } + } + } + }, + "delete": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Delete user", + "operationId": "delete-user", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.User" + } + } + } + } + }, + "/users/{user}/gitsshkey": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get user Git SSH key", + "operationId": "get-user-git-ssh-key", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.GitSSHKey" + } + } + } + }, + "put": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Regenerate user SSH key", + "operationId": "regenerate-user-ssh-key", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.GitSSHKey" + } + } + } + } + }, + "/users/{user}/keys": { + "post": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Create new session key", + "operationId": "create-new-session-key", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/codersdk.GenerateAPIKeyResponse" + } + } + } + } + }, + "/users/{user}/keys/tokens": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get user tokens", + "operationId": "get-user-tokens", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.APIKey" + } + } + } + } + }, + "post": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Create token API key", + "operationId": "create-token-api-key", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + }, + { + "description": "Create token request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.CreateTokenRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/codersdk.GenerateAPIKeyResponse" + } + } + } + } + }, + "/users/{user}/keys/{keyid}": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get API key", + "operationId": "get-api-key", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Key ID", + "name": "keyid", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.APIKey" + } + } + } + }, + "delete": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Delete API key", + "operationId": "delete-user-tokens", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Key ID", + "name": "keyid", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + } + } + } + }, + "/users/{user}/organizations": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get organizations by user", + "operationId": "get-organizations-by-users", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.Organization" + } + } + } + } + } + }, + "/users/{user}/organizations/{organizationname}": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get organization by user and organization name", + "operationId": "get-organization-by-user-and-organization-name", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Organization name", + "name": "organizationname", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.Organization" + } + } + } + } + }, + "/users/{user}/password": { + "put": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Update user password", + "operationId": "update-user-password", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + }, + { + "description": "Update password request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.UpdateUserPasswordRequest" + } + } + ], + "responses": { + "204": { + "description": "No Content" + } + } + } + }, + "/users/{user}/profile": { + "put": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Update user profile", + "operationId": "update-user-profile", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + }, + { + "description": "Updated profile", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.UpdateUserProfileRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.User" + } + } + } + } + }, + "/users/{user}/roles": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Get user roles", + "operationId": "get-user-roles", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.User" + } + } + } + }, + "put": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Assign role to user", + "operationId": "assign-role-to-user", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + }, + { + "description": "Update roles request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.UpdateRoles" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.User" + } + } + } + } + }, + "/users/{user}/status/activate": { + "put": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Activate user account", + "operationId": "activate-user-account", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.User" + } + } + } + } + }, + "/users/{user}/status/suspend": { + "put": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Users" + ], + "summary": "Suspend user account", + "operationId": "suspend-user-account", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.User" + } + } + } + } + }, + "/users/{user}/workspace/{workspacename}": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": [ + "application/json" + ], + "tags": [ + "Workspaces" + ], + "summary": "Get workspace metadata by user and workspace name", + "operationId": "get-workspace-metadata-by-user-and-workspace-name", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Workspace name", + "name": "workspacename", + "in": "path", + "required": true + }, + { + "type": "boolean", + "description": "Return data instead of HTTP 404 if the workspace is deleted", + "name": "include_deleted", + "in": "query" + } ], - "summary": "Update check", - "operationId": "update-check", "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/codersdk.UpdateCheckResponse" + "$ref": "#/definitions/codersdk.Workspace" } } } } }, - "/users/{user}/workspace/{workspacename}": { + "/users/{user}/workspace/{workspacename}/builds/{buildnumber}": { "get": { "security": [ { @@ -1809,14 +2814,14 @@ const docTemplate = `{ "application/json" ], "tags": [ - "Workspaces" + "Builds" ], - "summary": "Get workspace metadata by owner and workspace name", - "operationId": "get-workspace-metadata-by-owner-and-workspace-name", + "summary": "Get workspace build by user, workspace name, and build number", + "operationId": "get-workspace-build-by-user-workspace-name-and-build-number", "parameters": [ { "type": "string", - "description": "Owner username", + "description": "User ID, name, or me", "name": "user", "in": "path", "required": true @@ -1829,17 +2834,19 @@ const docTemplate = `{ "required": true }, { - "type": "boolean", - "description": "Return data instead of HTTP 404 if the workspace is deleted", - "name": "include_deleted", - "in": "query" + "type": "string", + "format": "number", + "description": "Build number", + "name": "buildnumber", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/codersdk.Workspace" + "$ref": "#/definitions/codersdk.WorkspaceBuild" } } } @@ -2821,6 +3828,84 @@ const docTemplate = `{ } } }, + "codersdk.APIKey": { + "type": "object", + "required": [ + "created_at", + "expires_at", + "id", + "last_used", + "lifetime_seconds", + "login_type", + "scope", + "updated_at", + "user_id" + ], + "properties": { + "created_at": { + "type": "string", + "format": "date-time" + }, + "expires_at": { + "type": "string", + "format": "date-time" + }, + "id": { + "type": "string" + }, + "last_used": { + "type": "string", + "format": "date-time" + }, + "lifetime_seconds": { + "type": "integer" + }, + "login_type": { + "enum": [ + "password", + "github", + "oidc", + "token" + ], + "allOf": [ + { + "$ref": "#/definitions/codersdk.LoginType" + } + ] + }, + "scope": { + "enum": [ + "all", + "application_connect" + ], + "allOf": [ + { + "$ref": "#/definitions/codersdk.APIKeyScope" + } + ] + }, + "updated_at": { + "type": "string", + "format": "date-time" + }, + "user_id": { + "description": "NOTE: do not ever return the HashedSecret", + "type": "string", + "format": "uuid" + } + } + }, + "codersdk.APIKeyScope": { + "type": "string", + "enum": [ + "all", + "application_connect" + ], + "x-enum-varnames": [ + "APIKeyScopeAll", + "APIKeyScopeApplicationConnect" + ] + }, "codersdk.AWSInstanceIdentityToken": { "type": "object", "required": [ @@ -3012,6 +4097,20 @@ const docTemplate = `{ } } }, + "codersdk.AuthMethods": { + "type": "object", + "properties": { + "github": { + "type": "boolean" + }, + "oidc": { + "type": "boolean" + }, + "password": { + "type": "boolean" + } + } + }, "codersdk.AuthorizationCheck": { "description": "AuthorizationCheck is used to check if the currently authenticated user (or the specified user) can do a given action to a given set of objects.", "type": "object", @@ -3116,6 +4215,41 @@ const docTemplate = `{ "BuildReasonAutostop" ] }, + "codersdk.CreateFirstUserRequest": { + "type": "object", + "required": [ + "email", + "password", + "username" + ], + "properties": { + "email": { + "type": "string" + }, + "password": { + "type": "string" + }, + "trial": { + "type": "boolean" + }, + "username": { + "type": "string" + } + } + }, + "codersdk.CreateFirstUserResponse": { + "type": "object", + "properties": { + "organization_id": { + "type": "string", + "format": "uuid" + }, + "user_id": { + "type": "string", + "format": "uuid" + } + } + }, "codersdk.CreateOrganizationRequest": { "type": "object", "required": [ @@ -3273,6 +4407,50 @@ const docTemplate = `{ } } }, + "codersdk.CreateTokenRequest": { + "type": "object", + "properties": { + "lifetime": { + "type": "integer" + }, + "scope": { + "enum": [ + "all", + "application_connect" + ], + "allOf": [ + { + "$ref": "#/definitions/codersdk.APIKeyScope" + } + ] + } + } + }, + "codersdk.CreateUserRequest": { + "type": "object", + "required": [ + "email", + "organization_id", + "password", + "username" + ], + "properties": { + "email": { + "type": "string", + "format": "email" + }, + "organization_id": { + "type": "string", + "format": "uuid" + }, + "password": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, "codersdk.CreateWorkspaceBuildRequest": { "type": "object", "required": [ @@ -3697,6 +4875,14 @@ const docTemplate = `{ } } }, + "codersdk.GenerateAPIKeyResponse": { + "type": "object", + "properties": { + "key": { + "type": "string" + } + } + }, "codersdk.GetAppHostResponse": { "type": "object", "properties": { @@ -3706,6 +4892,20 @@ const docTemplate = `{ } } }, + "codersdk.GetUsersResponse": { + "type": "object", + "properties": { + "count": { + "type": "integer" + }, + "users": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.User" + } + } + } + }, "codersdk.GitAuthConfig": { "type": "object", "properties": { @@ -3741,6 +4941,26 @@ const docTemplate = `{ } } }, + "codersdk.GitSSHKey": { + "type": "object", + "properties": { + "created_at": { + "type": "string", + "format": "date-time" + }, + "public_key": { + "type": "string" + }, + "updated_at": { + "type": "string", + "format": "date-time" + }, + "user_id": { + "type": "string", + "format": "uuid" + } + } + }, "codersdk.GoogleInstanceIdentityToken": { "type": "object", "required": [ @@ -3797,6 +5017,48 @@ const docTemplate = `{ "LogSourceProvisioner" ] }, + "codersdk.LoginType": { + "type": "string", + "enum": [ + "password", + "github", + "oidc", + "token" + ], + "x-enum-varnames": [ + "LoginTypePassword", + "LoginTypeGithub", + "LoginTypeOIDC", + "LoginTypeToken" + ] + }, + "codersdk.LoginWithPasswordRequest": { + "type": "object", + "required": [ + "email", + "password" + ], + "properties": { + "email": { + "type": "string", + "format": "email" + }, + "password": { + "type": "string" + } + } + }, + "codersdk.LoginWithPasswordResponse": { + "type": "object", + "required": [ + "session_token" + ], + "properties": { + "session_token": { + "type": "string" + } + } + }, "codersdk.OAuth2Config": { "type": "object", "properties": { @@ -4404,7 +5666,8 @@ const docTemplate = `{ "type": "integer" }, "active_version_id": { - "type": "string" + "type": "string", + "format": "uuid" }, "allow_user_cancel_workspace_jobs": { "type": "boolean" @@ -4488,7 +5751,8 @@ const docTemplate = `{ "type": "string" }, "id": { - "type": "string" + "type": "string", + "format": "uuid" }, "markdown": { "type": "string" @@ -4578,7 +5842,8 @@ const docTemplate = `{ ], "properties": { "id": { - "type": "string" + "type": "string", + "format": "uuid" } } }, @@ -4610,6 +5875,31 @@ const docTemplate = `{ } } }, + "codersdk.UpdateUserPasswordRequest": { + "type": "object", + "required": [ + "password" + ], + "properties": { + "old_password": { + "type": "string" + }, + "password": { + "type": "string" + } + } + }, + "codersdk.UpdateUserProfileRequest": { + "type": "object", + "required": [ + "username" + ], + "properties": { + "username": { + "type": "string" + } + } + }, "codersdk.UpdateWorkspaceAutostartRequest": { "type": "object", "properties": { @@ -4661,7 +5951,8 @@ const docTemplate = `{ "format": "date-time" }, "email": { - "type": "string" + "type": "string", + "format": "email" }, "id": { "type": "string", diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 13a0b54bc458b..1e823c2ef136e 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -434,15 +434,6 @@ "summary": "Assign role to organization member", "operationId": "assign-role-to-organization-member", "parameters": [ - { - "description": "Update roles request", - "name": "request", - "in": "body", - "required": true, - "schema": { - "$ref": "#/definitions/codersdk.UpdateRoles" - } - }, { "type": "string", "description": "Organization ID", @@ -452,10 +443,19 @@ }, { "type": "string", - "description": "Username, UUID, or me", + "description": "User ID, name, or me", "name": "user", "in": "path", "required": true + }, + { + "description": "Update roles request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.UpdateRoles" + } } ], "responses": { @@ -1041,6 +1041,25 @@ "name": "id", "in": "path", "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "After ID", + "name": "after_id", + "in": "query" + }, + { + "type": "integer", + "description": "Page limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Page offset", + "name": "offset", + "in": "query" } ], "responses": { @@ -1532,23 +1551,867 @@ } } }, - "/templateversions/{templateversion}/schema": { - "get": { + "/templateversions/{templateversion}/schema": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Templates"], + "summary": "Get schema by template version", + "operationId": "get-schema-by-template-version", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "Template version ID", + "name": "templateversion", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.ParameterSchema" + } + } + } + } + } + }, + "/updatecheck": { + "get": { + "produces": ["application/json"], + "tags": ["General"], + "summary": "Update check", + "operationId": "update-check", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.UpdateCheckResponse" + } + } + } + } + }, + "/users": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Get users", + "operationId": "get-users", + "parameters": [ + { + "type": "string", + "description": "Search query", + "name": "q", + "in": "query" + }, + { + "type": "string", + "format": "uuid", + "description": "After ID", + "name": "after_id", + "in": "query" + }, + { + "type": "integer", + "description": "Page limit", + "name": "limit", + "in": "query" + }, + { + "type": "integer", + "description": "Page offset", + "name": "offset", + "in": "query" + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.GetUsersResponse" + } + } + } + }, + "post": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Create new user", + "operationId": "create-new-user", + "parameters": [ + { + "description": "Create user request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.CreateUserRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/codersdk.User" + } + } + } + } + }, + "/users/authmethods": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Get authentication methods", + "operationId": "get-authentication-methods", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.AuthMethods" + } + } + } + } + }, + "/users/first": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Check initial user created", + "operationId": "check-initial-user-created", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.Response" + } + } + } + }, + "post": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Create initial user", + "operationId": "create-initial-user", + "parameters": [ + { + "description": "First user request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.CreateFirstUserRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/codersdk.CreateFirstUserResponse" + } + } + } + } + }, + "/users/login": { + "post": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Authorization"], + "summary": "Log in user", + "operationId": "log-in-user", + "parameters": [ + { + "description": "Login request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.LoginWithPasswordRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/codersdk.LoginWithPasswordResponse" + } + } + } + } + }, + "/users/logout": { + "post": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Log out user", + "operationId": "log-out-user", + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.Response" + } + } + } + } + }, + "/users/oauth2/github/callback": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "OAuth 2.0 GitHub Callback", + "operationId": "oauth2-github-callback", + "responses": { + "307": { + "description": "Temporary Redirect" + } + } + } + }, + "/users/oidc/callback": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "OpenID Connect Callback", + "operationId": "oidc-callback", + "responses": { + "307": { + "description": "Temporary Redirect" + } + } + } + }, + "/users/roles": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Members"], + "summary": "Get site member roles", + "operationId": "get-site-member-roles", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.AssignableRoles" + } + } + } + } + } + }, + "/users/{user}": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Get user by name", + "operationId": "get-user-by-name", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.User" + } + } + } + }, + "delete": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Delete user", + "operationId": "delete-user", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.User" + } + } + } + } + }, + "/users/{user}/gitsshkey": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Get user Git SSH key", + "operationId": "get-user-git-ssh-key", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.GitSSHKey" + } + } + } + }, + "put": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Regenerate user SSH key", + "operationId": "regenerate-user-ssh-key", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.GitSSHKey" + } + } + } + } + }, + "/users/{user}/keys": { + "post": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Create new session key", + "operationId": "create-new-session-key", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/codersdk.GenerateAPIKeyResponse" + } + } + } + } + }, + "/users/{user}/keys/tokens": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Get user tokens", + "operationId": "get-user-tokens", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.APIKey" + } + } + } + } + }, + "post": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Create token API key", + "operationId": "create-token-api-key", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + }, + { + "description": "Create token request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.CreateTokenRequest" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/codersdk.GenerateAPIKeyResponse" + } + } + } + } + }, + "/users/{user}/keys/{keyid}": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Get API key", + "operationId": "get-api-key", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Key ID", + "name": "keyid", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.APIKey" + } + } + } + }, + "delete": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Delete API key", + "operationId": "delete-user-tokens", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "Key ID", + "name": "keyid", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + } + } + } + }, + "/users/{user}/organizations": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Get organizations by user", + "operationId": "get-organizations-by-users", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.Organization" + } + } + } + } + } + }, + "/users/{user}/organizations/{organizationname}": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Get organization by user and organization name", + "operationId": "get-organization-by-user-and-organization-name", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Organization name", + "name": "organizationname", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.Organization" + } + } + } + } + }, + "/users/{user}/password": { + "put": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Update user password", + "operationId": "update-user-password", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + }, + { + "description": "Update password request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.UpdateUserPasswordRequest" + } + } + ], + "responses": { + "204": { + "description": "No Content" + } + } + } + }, + "/users/{user}/profile": { + "put": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Update user profile", + "operationId": "update-user-profile", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + }, + { + "description": "Updated profile", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.UpdateUserProfileRequest" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.User" + } + } + } + } + }, + "/users/{user}/roles": { + "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Get user roles", + "operationId": "get-user-roles", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.User" + } + } + } + }, + "put": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "consumes": ["application/json"], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Assign role to user", + "operationId": "assign-role-to-user", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + }, + { + "description": "Update roles request", + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/codersdk.UpdateRoles" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.User" + } + } + } + } + }, + "/users/{user}/status/activate": { + "put": { + "security": [ + { + "CoderSessionToken": [] + } + ], + "produces": ["application/json"], + "tags": ["Users"], + "summary": "Activate user account", + "operationId": "activate-user-account", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.User" + } + } + } + } + }, + "/users/{user}/status/suspend": { + "put": { "security": [ { "CoderSessionToken": [] } ], "produces": ["application/json"], - "tags": ["Templates"], - "summary": "Get schema by template version", - "operationId": "get-schema-by-template-version", + "tags": ["Users"], + "summary": "Suspend user account", + "operationId": "suspend-user-account", "parameters": [ { "type": "string", - "format": "uuid", - "description": "Template version ID", - "name": "templateversion", + "description": "User ID, name, or me", + "name": "user", "in": "path", "required": true } @@ -1557,32 +2420,56 @@ "200": { "description": "OK", "schema": { - "type": "array", - "items": { - "$ref": "#/definitions/codersdk.ParameterSchema" - } + "$ref": "#/definitions/codersdk.User" } } } } }, - "/updatecheck": { + "/users/{user}/workspace/{workspacename}": { "get": { + "security": [ + { + "CoderSessionToken": [] + } + ], "produces": ["application/json"], - "tags": ["General"], - "summary": "Update check", - "operationId": "update-check", + "tags": ["Workspaces"], + "summary": "Get workspace metadata by user and workspace name", + "operationId": "get-workspace-metadata-by-user-and-workspace-name", + "parameters": [ + { + "type": "string", + "description": "User ID, name, or me", + "name": "user", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Workspace name", + "name": "workspacename", + "in": "path", + "required": true + }, + { + "type": "boolean", + "description": "Return data instead of HTTP 404 if the workspace is deleted", + "name": "include_deleted", + "in": "query" + } + ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/codersdk.UpdateCheckResponse" + "$ref": "#/definitions/codersdk.Workspace" } } } } }, - "/users/{user}/workspace/{workspacename}": { + "/users/{user}/workspace/{workspacename}/builds/{buildnumber}": { "get": { "security": [ { @@ -1590,13 +2477,13 @@ } ], "produces": ["application/json"], - "tags": ["Workspaces"], - "summary": "Get workspace metadata by owner and workspace name", - "operationId": "get-workspace-metadata-by-owner-and-workspace-name", + "tags": ["Builds"], + "summary": "Get workspace build by user, workspace name, and build number", + "operationId": "get-workspace-build-by-user-workspace-name-and-build-number", "parameters": [ { "type": "string", - "description": "Owner username", + "description": "User ID, name, or me", "name": "user", "in": "path", "required": true @@ -1609,17 +2496,19 @@ "required": true }, { - "type": "boolean", - "description": "Return data instead of HTTP 404 if the workspace is deleted", - "name": "include_deleted", - "in": "query" + "type": "string", + "format": "number", + "description": "Build number", + "name": "buildnumber", + "in": "path", + "required": true } ], "responses": { "200": { "description": "OK", "schema": { - "$ref": "#/definitions/codersdk.Workspace" + "$ref": "#/definitions/codersdk.WorkspaceBuild" } } } @@ -2486,6 +3375,70 @@ } } }, + "codersdk.APIKey": { + "type": "object", + "required": [ + "created_at", + "expires_at", + "id", + "last_used", + "lifetime_seconds", + "login_type", + "scope", + "updated_at", + "user_id" + ], + "properties": { + "created_at": { + "type": "string", + "format": "date-time" + }, + "expires_at": { + "type": "string", + "format": "date-time" + }, + "id": { + "type": "string" + }, + "last_used": { + "type": "string", + "format": "date-time" + }, + "lifetime_seconds": { + "type": "integer" + }, + "login_type": { + "enum": ["password", "github", "oidc", "token"], + "allOf": [ + { + "$ref": "#/definitions/codersdk.LoginType" + } + ] + }, + "scope": { + "enum": ["all", "application_connect"], + "allOf": [ + { + "$ref": "#/definitions/codersdk.APIKeyScope" + } + ] + }, + "updated_at": { + "type": "string", + "format": "date-time" + }, + "user_id": { + "description": "NOTE: do not ever return the HashedSecret", + "type": "string", + "format": "uuid" + } + } + }, + "codersdk.APIKeyScope": { + "type": "string", + "enum": ["all", "application_connect"], + "x-enum-varnames": ["APIKeyScopeAll", "APIKeyScopeApplicationConnect"] + }, "codersdk.AWSInstanceIdentityToken": { "type": "object", "required": ["document", "signature"], @@ -2668,6 +3621,20 @@ } } }, + "codersdk.AuthMethods": { + "type": "object", + "properties": { + "github": { + "type": "boolean" + }, + "oidc": { + "type": "boolean" + }, + "password": { + "type": "boolean" + } + } + }, "codersdk.AuthorizationCheck": { "description": "AuthorizationCheck is used to check if the currently authenticated user (or the specified user) can do a given action to a given set of objects.", "type": "object", @@ -2760,6 +3727,37 @@ "BuildReasonAutostop" ] }, + "codersdk.CreateFirstUserRequest": { + "type": "object", + "required": ["email", "password", "username"], + "properties": { + "email": { + "type": "string" + }, + "password": { + "type": "string" + }, + "trial": { + "type": "boolean" + }, + "username": { + "type": "string" + } + } + }, + "codersdk.CreateFirstUserResponse": { + "type": "object", + "properties": { + "organization_id": { + "type": "string", + "format": "uuid" + }, + "user_id": { + "type": "string", + "format": "uuid" + } + } + }, "codersdk.CreateOrganizationRequest": { "type": "object", "required": ["name"], @@ -2899,6 +3897,42 @@ } } }, + "codersdk.CreateTokenRequest": { + "type": "object", + "properties": { + "lifetime": { + "type": "integer" + }, + "scope": { + "enum": ["all", "application_connect"], + "allOf": [ + { + "$ref": "#/definitions/codersdk.APIKeyScope" + } + ] + } + } + }, + "codersdk.CreateUserRequest": { + "type": "object", + "required": ["email", "organization_id", "password", "username"], + "properties": { + "email": { + "type": "string", + "format": "email" + }, + "organization_id": { + "type": "string", + "format": "uuid" + }, + "password": { + "type": "string" + }, + "username": { + "type": "string" + } + } + }, "codersdk.CreateWorkspaceBuildRequest": { "type": "object", "required": ["transition"], @@ -3316,6 +4350,14 @@ } } }, + "codersdk.GenerateAPIKeyResponse": { + "type": "object", + "properties": { + "key": { + "type": "string" + } + } + }, "codersdk.GetAppHostResponse": { "type": "object", "properties": { @@ -3325,6 +4367,20 @@ } } }, + "codersdk.GetUsersResponse": { + "type": "object", + "properties": { + "count": { + "type": "integer" + }, + "users": { + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.User" + } + } + } + }, "codersdk.GitAuthConfig": { "type": "object", "properties": { @@ -3360,6 +4416,26 @@ } } }, + "codersdk.GitSSHKey": { + "type": "object", + "properties": { + "created_at": { + "type": "string", + "format": "date-time" + }, + "public_key": { + "type": "string" + }, + "updated_at": { + "type": "string", + "format": "date-time" + }, + "user_id": { + "type": "string", + "format": "uuid" + } + } + }, "codersdk.GoogleInstanceIdentityToken": { "type": "object", "required": ["json_web_token"], @@ -3402,6 +4478,38 @@ "enum": ["provisioner_daemon", "provisioner"], "x-enum-varnames": ["LogSourceProvisionerDaemon", "LogSourceProvisioner"] }, + "codersdk.LoginType": { + "type": "string", + "enum": ["password", "github", "oidc", "token"], + "x-enum-varnames": [ + "LoginTypePassword", + "LoginTypeGithub", + "LoginTypeOIDC", + "LoginTypeToken" + ] + }, + "codersdk.LoginWithPasswordRequest": { + "type": "object", + "required": ["email", "password"], + "properties": { + "email": { + "type": "string", + "format": "email" + }, + "password": { + "type": "string" + } + } + }, + "codersdk.LoginWithPasswordResponse": { + "type": "object", + "required": ["session_token"], + "properties": { + "session_token": { + "type": "string" + } + } + }, "codersdk.OAuth2Config": { "type": "object", "properties": { @@ -3967,7 +5075,8 @@ "type": "integer" }, "active_version_id": { - "type": "string" + "type": "string", + "format": "uuid" }, "allow_user_cancel_workspace_jobs": { "type": "boolean" @@ -4049,7 +5158,8 @@ "type": "string" }, "id": { - "type": "string" + "type": "string", + "format": "uuid" }, "markdown": { "type": "string" @@ -4137,7 +5247,8 @@ "required": ["id"], "properties": { "id": { - "type": "string" + "type": "string", + "format": "uuid" } } }, @@ -4169,6 +5280,27 @@ } } }, + "codersdk.UpdateUserPasswordRequest": { + "type": "object", + "required": ["password"], + "properties": { + "old_password": { + "type": "string" + }, + "password": { + "type": "string" + } + } + }, + "codersdk.UpdateUserProfileRequest": { + "type": "object", + "required": ["username"], + "properties": { + "username": { + "type": "string" + } + } + }, "codersdk.UpdateWorkspaceAutostartRequest": { "type": "object", "properties": { @@ -4215,7 +5347,8 @@ "format": "date-time" }, "email": { - "type": "string" + "type": "string", + "format": "email" }, "id": { "type": "string", diff --git a/coderd/apikey.go b/coderd/apikey.go index 2900f8e4abe62..e4cbd7552c2cc 100644 --- a/coderd/apikey.go +++ b/coderd/apikey.go @@ -25,6 +25,16 @@ import ( ) // Creates a new token API key that effectively doesn't expire. +// +// @Summary Create token API key +// @ID create-token-api-key +// @Security CoderSessionToken +// @Produce json +// @Tags Users +// @Param user path string true "User ID, name, or me" +// @Param request body codersdk.CreateTokenRequest true "Create token request" +// @Success 201 {object} codersdk.GenerateAPIKeyResponse +// @Router /users/{user}/keys/tokens [post] func (api *API) postToken(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() user := httpmw.UserParam(r) @@ -78,6 +88,15 @@ func (api *API) postToken(rw http.ResponseWriter, r *http.Request) { } // Creates a new session key, used for logging in via the CLI. +// +// @Summary Create new session key +// @ID create-new-session-key +// @Security CoderSessionToken +// @Produce json +// @Tags Users +// @Param user path string true "User ID, name, or me" +// @Success 201 {object} codersdk.GenerateAPIKeyResponse +// @Router /users/{user}/keys [post] func (api *API) postAPIKey(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() user := httpmw.UserParam(r) @@ -106,12 +125,21 @@ func (api *API) postAPIKey(rw http.ResponseWriter, r *http.Request) { } // We intentionally do not set the cookie on the response here. - // Setting the cookie will couple the browser sesion to the API + // Setting the cookie will couple the browser session to the API // key we return here, meaning logging out of the website would // invalid your CLI key. httpapi.Write(ctx, rw, http.StatusCreated, codersdk.GenerateAPIKeyResponse{Key: cookie.Value}) } +// @Summary Get API key +// @ID get-api-key +// @Security CoderSessionToken +// @Produce json +// @Tags Users +// @Param user path string true "User ID, name, or me" +// @Param keyid path string true "Key ID" format(uuid) +// @Success 200 {object} codersdk.APIKey +// @Router /users/{user}/keys/{keyid} [get] func (api *API) apiKey(rw http.ResponseWriter, r *http.Request) { var ( ctx = r.Context() @@ -140,6 +168,14 @@ func (api *API) apiKey(rw http.ResponseWriter, r *http.Request) { httpapi.Write(ctx, rw, http.StatusOK, convertAPIKey(key)) } +// @Summary Get user tokens +// @ID get-user-tokens +// @Security CoderSessionToken +// @Produce json +// @Tags Users +// @Param user path string true "User ID, name, or me" +// @Success 200 {array} codersdk.APIKey +// @Router /users/{user}/keys/tokens [get] func (api *API) tokens(rw http.ResponseWriter, r *http.Request) { var ( ctx = r.Context() @@ -172,6 +208,15 @@ func (api *API) tokens(rw http.ResponseWriter, r *http.Request) { httpapi.Write(ctx, rw, http.StatusOK, apiKeys) } +// @Summary Delete API key +// @ID delete-user-tokens +// @Security CoderSessionToken +// @Produce json +// @Tags Users +// @Param user path string true "User ID, name, or me" +// @Param keyid path string true "Key ID" format(uuid) +// @Success 204 +// @Router /users/{user}/keys/{keyid} [delete] func (api *API) deleteAPIKey(rw http.ResponseWriter, r *http.Request) { var ( ctx = r.Context() diff --git a/coderd/coderd.go b/coderd/coderd.go index d45dd599afea2..e957314bc81fb 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -485,8 +485,8 @@ func New(options *Options) *API { r.Get("/", api.userByName) r.Put("/profile", api.putUserProfile) r.Route("/status", func(r chi.Router) { - r.Put("/suspend", api.putUserStatus(database.UserStatusSuspended)) - r.Put("/activate", api.putUserStatus(database.UserStatusActive)) + r.Put("/suspend", api.putSuspendUserAccount()) + r.Put("/activate", api.putActivateUserAccount()) }) r.Route("/password", func(r chi.Router) { r.Put("/", api.putUserPassword) diff --git a/coderd/gitsshkey.go b/coderd/gitsshkey.go index a0f15da2e9e0c..9e68d7a64283d 100644 --- a/coderd/gitsshkey.go +++ b/coderd/gitsshkey.go @@ -12,6 +12,14 @@ import ( "github.com/coder/coder/codersdk" ) +// @Summary Regenerate user SSH key +// @ID regenerate-user-ssh-key +// @Security CoderSessionToken +// @Produce json +// @Tags Users +// @Param user path string true "User ID, name, or me" +// @Success 200 {object} codersdk.GitSSHKey +// @Router /users/{user}/gitsshkey [put] func (api *API) regenerateGitSSHKey(rw http.ResponseWriter, r *http.Request) { var ( ctx = r.Context() @@ -73,6 +81,14 @@ func (api *API) regenerateGitSSHKey(rw http.ResponseWriter, r *http.Request) { }) } +// @Summary Get user Git SSH key +// @ID get-user-git-ssh-key +// @Security CoderSessionToken +// @Produce json +// @Tags Users +// @Param user path string true "User ID, name, or me" +// @Success 200 {object} codersdk.GitSSHKey +// @Router /users/{user}/gitsshkey [get] func (api *API) gitSSHKey(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() user := httpmw.UserParam(r) diff --git a/coderd/members.go b/coderd/members.go index 9141cadb6a0b3..aaf839e987be3 100644 --- a/coderd/members.go +++ b/coderd/members.go @@ -22,9 +22,9 @@ import ( // @Accept json // @Produce json // @Tags Members -// @Param request body codersdk.UpdateRoles true "Update roles request" // @Param organization path string true "Organization ID" -// @Param user path string true "Username, UUID, or me" +// @Param user path string true "User ID, name, or me" +// @Param request body codersdk.UpdateRoles true "Update roles request" // @Success 200 {object} codersdk.OrganizationMember // @Router /organizations/{organization}/members/{user}/roles [put] func (api *API) putMemberRoles(rw http.ResponseWriter, r *http.Request) { diff --git a/coderd/roles.go b/coderd/roles.go index 9eb1518d9ec6e..29be9c4a49172 100644 --- a/coderd/roles.go +++ b/coderd/roles.go @@ -11,6 +11,14 @@ import ( ) // assignableSiteRoles returns all site wide roles that can be assigned. +// +// @Summary Get site member roles +// @ID get-site-member-roles +// @Security CoderSessionToken +// @Produce json +// @Tags Members +// @Success 200 {array} codersdk.AssignableRoles +// @Router /users/roles [get] func (api *API) assignableSiteRoles(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() actorRoles := httpmw.UserAuthorization(r) @@ -23,6 +31,8 @@ func (api *API) assignableSiteRoles(rw http.ResponseWriter, r *http.Request) { httpapi.Write(ctx, rw, http.StatusOK, assignableRoles(actorRoles.Roles, roles)) } +// assignableSiteRoles returns all org wide roles that can be assigned. +// // @Summary Get member roles by organization // @ID get-member-roles-by-organization // @Security CoderSessionToken @@ -31,8 +41,6 @@ func (api *API) assignableSiteRoles(rw http.ResponseWriter, r *http.Request) { // @Param organization path string true "Organization ID" format(uuid) // @Success 200 {array} codersdk.AssignableRoles // @Router /organizations/{organization}/members/roles [get] -// -// assignableSiteRoles returns all site wide roles that can be assigned. func (api *API) assignableOrgRoles(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() organization := httpmw.OrganizationParam(r) diff --git a/coderd/templateversions.go b/coderd/templateversions.go index 46c0973cbb47a..15ac9a502711b 100644 --- a/coderd/templateversions.go +++ b/coderd/templateversions.go @@ -541,6 +541,9 @@ func (api *API) fetchTemplateVersionDryRunJob(rw http.ResponseWriter, r *http.Re // @Produce json // @Tags Templates // @Param id path string true "Template ID" format(uuid) +// @Param after_id query string false "After ID" format(uuid) +// @Param limit query int false "Page limit" +// @Param offset query int false "Page offset" // @Success 200 {array} codersdk.TemplateVersion // @Router /templates/{id}/versions [get] func (api *API) templateVersionsByTemplate(rw http.ResponseWriter, r *http.Request) { diff --git a/coderd/userauth.go b/coderd/userauth.go index 5a23b86c8de71..e1ee92d0eb822 100644 --- a/coderd/userauth.go +++ b/coderd/userauth.go @@ -43,6 +43,13 @@ type GithubOAuth2Config struct { AllowTeams []GithubOAuth2Team } +// @Summary Get authentication methods +// @ID get-authentication-methods +// @Security CoderSessionToken +// @Produce json +// @Tags Users +// @Success 200 {object} codersdk.AuthMethods +// @Router /users/authmethods [get] func (api *API) userAuthMethods(rw http.ResponseWriter, r *http.Request) { httpapi.Write(r.Context(), rw, http.StatusOK, codersdk.AuthMethods{ Password: true, @@ -51,6 +58,13 @@ func (api *API) userAuthMethods(rw http.ResponseWriter, r *http.Request) { }) } +// @Summary OAuth 2.0 GitHub Callback +// @ID oauth2-github-callback +// @Security CoderSessionToken +// @Produce json +// @Tags Users +// @Success 307 +// @Router /users/oauth2/github/callback [get] func (api *API) userOAuth2Github(rw http.ResponseWriter, r *http.Request) { var ( ctx = r.Context() @@ -203,6 +217,13 @@ type OIDCConfig struct { UsernameField string } +// @Summary OpenID Connect Callback +// @ID oidc-callback +// @Security CoderSessionToken +// @Produce json +// @Tags Users +// @Success 307 +// @Router /users/oidc/callback [get] func (api *API) userOIDC(rw http.ResponseWriter, r *http.Request) { var ( ctx = r.Context() diff --git a/coderd/users.go b/coderd/users.go index e1300d17c6302..0485a1e3ec1ed 100644 --- a/coderd/users.go +++ b/coderd/users.go @@ -28,6 +28,14 @@ import ( ) // Returns whether the initial user has been created or not. +// +// @Summary Check initial user created +// @ID check-initial-user-created +// @Security CoderSessionToken +// @Produce json +// @Tags Users +// @Success 200 {object} codersdk.Response +// @Router /users/first [get] func (api *API) firstUser(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() userCount, err := api.Database.GetUserCount(ctx) @@ -52,6 +60,16 @@ func (api *API) firstUser(rw http.ResponseWriter, r *http.Request) { } // Creates the initial user for a Coder deployment. +// +// @Summary Create initial user +// @ID create-initial-user +// @Security CoderSessionToken +// @Accept json +// @Produce json +// @Tags Users +// @Param request body codersdk.CreateFirstUserRequest true "First user request" +// @Success 201 {object} codersdk.CreateFirstUserResponse +// @Router /users/first [post] func (api *API) postFirstUser(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() var createUser codersdk.CreateFirstUserRequest @@ -135,6 +153,17 @@ func (api *API) postFirstUser(rw http.ResponseWriter, r *http.Request) { }) } +// @Summary Get users +// @ID get-users +// @Security CoderSessionToken +// @Produce json +// @Tags Users +// @Param q query string false "Search query" +// @Param after_id query string false "After ID" format(uuid) +// @Param limit query int false "Page limit" +// @Param offset query int false "Page offset" +// @Success 200 {object} codersdk.GetUsersResponse +// @Router /users [get] func (api *API) users(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() query := r.URL.Query().Get("q") @@ -214,6 +243,16 @@ func (api *API) users(rw http.ResponseWriter, r *http.Request) { } // Creates a new user. +// +// @Summary Create new user +// @ID create-new-user +// @Security CoderSessionToken +// @Accept json +// @Produce json +// @Tags Users +// @Param request body codersdk.CreateUserRequest true "Create user request" +// @Success 201 {object} codersdk.User +// @Router /users [post] func (api *API) postUser(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() auditor := *api.Auditor.Load() @@ -300,6 +339,14 @@ func (api *API) postUser(rw http.ResponseWriter, r *http.Request) { httpapi.Write(ctx, rw, http.StatusCreated, convertUser(user, []uuid.UUID{req.OrganizationID})) } +// @Summary Delete user +// @ID delete-user +// @Security CoderSessionToken +// @Produce json +// @Tags Users +// @Param user path string true "User ID, name, or me" +// @Success 200 {object} codersdk.User +// @Router /users/{user} [delete] func (api *API) deleteUser(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() auditor := *api.Auditor.Load() @@ -355,6 +402,15 @@ func (api *API) deleteUser(rw http.ResponseWriter, r *http.Request) { // Returns the parameterized user requested. All validation // is completed in the middleware for this route. +// +// @Summary Get user by name +// @ID get-user-by-name +// @Security CoderSessionToken +// @Produce json +// @Tags Users +// @Param user path string true "User ID, name, or me" +// @Success 200 {object} codersdk.User +// @Router /users/{user} [get] func (api *API) userByName(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() user := httpmw.UserParam(r) @@ -376,6 +432,15 @@ func (api *API) userByName(rw http.ResponseWriter, r *http.Request) { httpapi.Write(ctx, rw, http.StatusOK, convertUser(user, organizationIDs)) } +// @Summary Update user profile +// @ID update-user-profile +// @Security CoderSessionToken +// @Produce json +// @Tags Users +// @Param user path string true "User ID, name, or me" +// @Param request body codersdk.UpdateUserProfileRequest true "Updated profile" +// @Success 200 {object} codersdk.User +// @Router /users/{user}/profile [put] func (api *API) putUserProfile(rw http.ResponseWriter, r *http.Request) { var ( ctx = r.Context() @@ -456,6 +521,30 @@ func (api *API) putUserProfile(rw http.ResponseWriter, r *http.Request) { httpapi.Write(ctx, rw, http.StatusOK, convertUser(updatedUserProfile, organizationIDs)) } +// @Summary Suspend user account +// @ID suspend-user-account +// @Security CoderSessionToken +// @Produce json +// @Tags Users +// @Param user path string true "User ID, name, or me" +// @Success 200 {object} codersdk.User +// @Router /users/{user}/status/suspend [put] +func (api *API) putSuspendUserAccount() func(rw http.ResponseWriter, r *http.Request) { + return api.putUserStatus(database.UserStatusSuspended) +} + +// @Summary Activate user account +// @ID activate-user-account +// @Security CoderSessionToken +// @Produce json +// @Tags Users +// @Param user path string true "User ID, name, or me" +// @Success 200 {object} codersdk.User +// @Router /users/{user}/status/activate [put] +func (api *API) putActivateUserAccount() func(rw http.ResponseWriter, r *http.Request) { + return api.putUserStatus(database.UserStatusActive) +} + func (api *API) putUserStatus(status database.UserStatus) func(rw http.ResponseWriter, r *http.Request) { return func(rw http.ResponseWriter, r *http.Request) { var ( @@ -525,6 +614,15 @@ func (api *API) putUserStatus(status database.UserStatus) func(rw http.ResponseW } } +// @Summary Update user password +// @ID update-user-password +// @Security CoderSessionToken +// @Produce json +// @Tags Users +// @Param user path string true "User ID, name, or me" +// @Param request body codersdk.UpdateUserPasswordRequest true "Update password request" +// @Success 204 +// @Router /users/{user}/password [put] func (api *API) putUserPassword(rw http.ResponseWriter, r *http.Request) { var ( ctx = r.Context() @@ -642,6 +740,14 @@ func (api *API) putUserPassword(rw http.ResponseWriter, r *http.Request) { httpapi.Write(ctx, rw, http.StatusNoContent, nil) } +// @Summary Get user roles +// @ID get-user-roles +// @Security CoderSessionToken +// @Produce json +// @Tags Users +// @Param user path string true "User ID, name, or me" +// @Success 200 {object} codersdk.User +// @Router /users/{user}/roles [get] func (api *API) userRoles(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() user := httpmw.UserParam(r) @@ -685,6 +791,16 @@ func (api *API) userRoles(rw http.ResponseWriter, r *http.Request) { httpapi.Write(ctx, rw, http.StatusOK, resp) } +// @Summary Assign role to user +// @ID assign-role-to-user +// @Security CoderSessionToken +// @Accept json +// @Produce json +// @Tags Users +// @Param user path string true "User ID, name, or me" +// @Param request body codersdk.UpdateRoles true "Update roles request" +// @Success 200 {object} codersdk.User +// @Router /users/{user}/roles [put] func (api *API) putUserRoles(rw http.ResponseWriter, r *http.Request) { var ( ctx = r.Context() @@ -790,6 +906,15 @@ func (api *API) updateSiteUserRoles(ctx context.Context, args database.UpdateUse } // Returns organizations the parameterized user has access to. +// +// @Summary Get organizations by user +// @ID get-organizations-by-users +// @Security CoderSessionToken +// @Produce json +// @Tags Users +// @Param user path string true "User ID, name, or me" +// @Success 200 {array} codersdk.Organization +// @Router /users/{user}/organizations [get] func (api *API) organizationsByUser(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() user := httpmw.UserParam(r) @@ -825,6 +950,15 @@ func (api *API) organizationsByUser(rw http.ResponseWriter, r *http.Request) { httpapi.Write(ctx, rw, http.StatusOK, publicOrganizations) } +// @Summary Get organization by user and organization name +// @ID get-organization-by-user-and-organization-name +// @Security CoderSessionToken +// @Produce json +// @Tags Users +// @Param user path string true "User ID, name, or me" +// @Param organizationname path string true "Organization name" +// @Success 200 {object} codersdk.Organization +// @Router /users/{user}/organizations/{organizationname} [get] func (api *API) organizationByUserAndName(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() organizationName := chi.URLParam(r, "organizationname") @@ -852,6 +986,15 @@ func (api *API) organizationByUserAndName(rw http.ResponseWriter, r *http.Reques } // Authenticates the user with an email and password. +// +// @Summary Log in user +// @ID log-in-user +// @Security CoderSessionToken +// @Produce json +// @Tags Authorization +// @Param request body codersdk.LoginWithPasswordRequest true "Login request" +// @Success 201 {object} codersdk.LoginWithPasswordResponse +// @Router /users/login [post] func (api *API) postLogin(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() var loginWithPassword codersdk.LoginWithPasswordRequest @@ -922,6 +1065,14 @@ func (api *API) postLogin(rw http.ResponseWriter, r *http.Request) { } // Clear the user's session cookie. +// +// @Summary Log out user +// @ID log-out-user +// @Security CoderSessionToken +// @Produce json +// @Tags Users +// @Success 200 {object} codersdk.Response +// @Router /users/logout [post] func (api *API) postLogout(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() // Get a blank token cookie. diff --git a/coderd/workspacebuilds.go b/coderd/workspacebuilds.go index 4f057786ddfe1..3d3d42b7ea2a1 100644 --- a/coderd/workspacebuilds.go +++ b/coderd/workspacebuilds.go @@ -191,6 +191,16 @@ func (api *API) workspaceBuilds(rw http.ResponseWriter, r *http.Request) { httpapi.Write(ctx, rw, http.StatusOK, apiBuilds) } +// @Summary Get workspace build by user, workspace name, and build number +// @ID get-workspace-build-by-user-workspace-name-and-build-number +// @Security CoderSessionToken +// @Produce json +// @Tags Builds +// @Param user path string true "User ID, name, or me" +// @Param workspacename path string true "Workspace name" +// @Param buildnumber path string true "Build number" format(number) +// @Success 200 {object} codersdk.WorkspaceBuild +// @Router /users/{user}/workspace/{workspacename}/builds/{buildnumber} [get] func (api *API) workspaceBuildByBuildNumber(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() owner := httpmw.UserParam(r) diff --git a/coderd/workspaces.go b/coderd/workspaces.go index 6edd0d13c629b..6ef629fe47bd0 100644 --- a/coderd/workspaces.go +++ b/coderd/workspaces.go @@ -192,12 +192,12 @@ func (api *API) workspaces(rw http.ResponseWriter, r *http.Request) { }) } -// @Summary Get workspace metadata by owner and workspace name -// @ID get-workspace-metadata-by-owner-and-workspace-name +// @Summary Get workspace metadata by user and workspace name +// @ID get-workspace-metadata-by-user-and-workspace-name // @Security CoderSessionToken // @Produce json // @Tags Workspaces -// @Param user path string true "Owner username" +// @Param user path string true "User ID, name, or me" // @Param workspacename path string true "Workspace name" // @Param include_deleted query bool false "Return data instead of HTTP 404 if the workspace is deleted" // @Success 200 {object} codersdk.Workspace diff --git a/codersdk/apikey.go b/codersdk/apikey.go index 8fa0180e7b2b8..fd896a0d29b4a 100644 --- a/codersdk/apikey.go +++ b/codersdk/apikey.go @@ -13,13 +13,13 @@ import ( type APIKey struct { ID string `json:"id" validate:"required"` // NOTE: do not ever return the HashedSecret - UserID uuid.UUID `json:"user_id" validate:"required"` - LastUsed time.Time `json:"last_used" validate:"required"` - ExpiresAt time.Time `json:"expires_at" validate:"required"` - CreatedAt time.Time `json:"created_at" validate:"required"` - UpdatedAt time.Time `json:"updated_at" validate:"required"` - LoginType LoginType `json:"login_type" validate:"required"` - Scope APIKeyScope `json:"scope" validate:"required"` + UserID uuid.UUID `json:"user_id" validate:"required" format:"uuid"` + LastUsed time.Time `json:"last_used" validate:"required" format:"date-time"` + ExpiresAt time.Time `json:"expires_at" validate:"required" format:"date-time"` + CreatedAt time.Time `json:"created_at" validate:"required" format:"date-time"` + UpdatedAt time.Time `json:"updated_at" validate:"required" format:"date-time"` + LoginType LoginType `json:"login_type" validate:"required" enums:"password,github,oidc,token"` + Scope APIKeyScope `json:"scope" validate:"required" enums:"all,application_connect"` LifetimeSeconds int64 `json:"lifetime_seconds" validate:"required"` } @@ -41,7 +41,7 @@ const ( type CreateTokenRequest struct { Lifetime time.Duration `json:"lifetime"` - Scope APIKeyScope `json:"scope"` + Scope APIKeyScope `json:"scope" enums:"all,application_connect"` } // GenerateAPIKeyResponse contains an API key for a user. diff --git a/codersdk/gitsshkey.go b/codersdk/gitsshkey.go index e345a2733ab02..4a19110b5bb90 100644 --- a/codersdk/gitsshkey.go +++ b/codersdk/gitsshkey.go @@ -12,9 +12,9 @@ import ( ) type GitSSHKey struct { - UserID uuid.UUID `json:"user_id"` - CreatedAt time.Time `json:"created_at"` - UpdatedAt time.Time `json:"updated_at"` + UserID uuid.UUID `json:"user_id" format:"uuid"` + CreatedAt time.Time `json:"created_at" format:"date-time"` + UpdatedAt time.Time `json:"updated_at" format:"date-time"` PublicKey string `json:"public_key"` } diff --git a/codersdk/organizations.go b/codersdk/organizations.go index 39b50da013ec5..27a30f8a14583 100644 --- a/codersdk/organizations.go +++ b/codersdk/organizations.go @@ -36,9 +36,9 @@ type Organization struct { type CreateTemplateVersionRequest struct { Name string `json:"name,omitempty" validate:"omitempty,template_name"` // TemplateID optionally associates a version with a template. - TemplateID uuid.UUID `json:"template_id,omitempty"` - StorageMethod ProvisionerStorageMethod `json:"storage_method" validate:"oneof=file,required"` - FileID uuid.UUID `json:"file_id,omitempty" validate:"required_without=ExampleID"` + TemplateID uuid.UUID `json:"template_id,omitempty" format:"uuid"` + StorageMethod ProvisionerStorageMethod `json:"storage_method" validate:"oneof=file,required" enums:"file"` + FileID uuid.UUID `json:"file_id,omitempty" validate:"required_without=ExampleID" format:"uuid"` ExampleID string `json:"example_id,omitempty" validate:"required_without=FileID"` Provisioner ProvisionerType `json:"provisioner" validate:"oneof=terraform echo,required"` ProvisionerTags map[string]string `json:"tags"` diff --git a/codersdk/templates.go b/codersdk/templates.go index a2a232a48e50d..fce8b6f4c4f5c 100644 --- a/codersdk/templates.go +++ b/codersdk/templates.go @@ -21,7 +21,7 @@ type Template struct { Name string `json:"name"` DisplayName string `json:"display_name"` Provisioner ProvisionerType `json:"provisioner" enums:"terraform"` - ActiveVersionID uuid.UUID `json:"active_version_id"` + ActiveVersionID uuid.UUID `json:"active_version_id" format:"uuid"` WorkspaceOwnerCount uint32 `json:"workspace_owner_count"` // ActiveUserCount is set to -1 when loading. ActiveUserCount int `json:"active_user_count"` @@ -42,7 +42,7 @@ type TransitionStats struct { type TemplateBuildTimeStats map[WorkspaceTransition]TransitionStats type UpdateActiveTemplateVersion struct { - ID uuid.UUID `json:"id" validate:"required"` + ID uuid.UUID `json:"id" validate:"required" format:"uuid"` } type TemplateRole string @@ -83,7 +83,7 @@ type UpdateTemplateMeta struct { } type TemplateExample struct { - ID string `json:"id"` + ID string `json:"id" format:"uuid"` URL string `json:"url"` Name string `json:"name"` Description string `json:"description"` diff --git a/codersdk/users.go b/codersdk/users.go index 4b1f24afac933..b940b0bc48d9b 100644 --- a/codersdk/users.go +++ b/codersdk/users.go @@ -37,7 +37,7 @@ type UsersRequest struct { type User struct { ID uuid.UUID `json:"id" validate:"required" table:"id" format:"uuid"` Username string `json:"username" validate:"required" table:"username"` - Email string `json:"email" validate:"required" table:"email"` + Email string `json:"email" validate:"required" table:"email" format:"email"` CreatedAt time.Time `json:"created_at" validate:"required" table:"created at" format:"date-time"` LastSeenAt time.Time `json:"last_seen_at" format:"date-time"` @@ -66,7 +66,7 @@ type CreateFirstUserResponse struct { } type CreateUserRequest struct { - Email string `json:"email" validate:"required,email"` + Email string `json:"email" validate:"required,email" format:"email"` Username string `json:"username" validate:"required,username"` Password string `json:"password" validate:"required"` OrganizationID uuid.UUID `json:"organization_id" validate:"required" format:"uuid"` @@ -92,7 +92,7 @@ type UserRoles struct { // LoginWithPasswordRequest enables callers to authenticate with email and password. type LoginWithPasswordRequest struct { - Email string `json:"email" validate:"required,email"` + Email string `json:"email" validate:"required,email" format:"email"` Password string `json:"password" validate:"required"` } diff --git a/docs/api/audit.md b/docs/api/audit.md index 7fc76e15e0a0e..743807ee328a3 100644 --- a/docs/api/audit.md +++ b/docs/api/audit.md @@ -62,7 +62,7 @@ curl -X GET http://coder-server:8080/api/v2/audit?q=string \ "user": { "avatar_url": "http://example.com", "created_at": "2019-08-24T14:15:22Z", - "email": "string", + "email": "user@example.com", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "last_seen_at": "2019-08-24T14:15:22Z", "organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], diff --git a/docs/api/authorization.md b/docs/api/authorization.md index 884b3fa3c5c41..d6f16913e0371 100644 --- a/docs/api/authorization.md +++ b/docs/api/authorization.md @@ -67,3 +67,50 @@ curl -X POST http://coder-server:8080/api/v2/authcheck \ | 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.AuthorizationResponse](schemas.md#codersdkauthorizationresponse) | To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Log in user + +### Code samples + +```shell +# Example request using curl +curl -X POST http://coder-server:8080/api/v2/users/login \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`POST /users/login` + +> Body parameter + +```json +{ + "email": "user@example.com", + "password": "string" +} +``` + +### Parameters + +| Name | In | Type | Required | Description | +| ------ | ---- | -------------------------------------------------------------------------------- | -------- | ------------- | +| `body` | body | [codersdk.LoginWithPasswordRequest](schemas.md#codersdkloginwithpasswordrequest) | true | Login request | + +### Example responses + +> 201 Response + +```json +{ + "session_token": "string" +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------------ | ----------- | ---------------------------------------------------------------------------------- | +| 201 | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created | [codersdk.LoginWithPasswordResponse](schemas.md#codersdkloginwithpasswordresponse) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). diff --git a/docs/api/builds.md b/docs/api/builds.md index a2828d0642ffa..cf904167770a6 100644 --- a/docs/api/builds.md +++ b/docs/api/builds.md @@ -2,6 +2,150 @@ > This page is incomplete, stay tuned. +## Get workspace build by user, workspace name, and build number + +### Code samples + +```shell +# Example request using curl +curl -X GET http://coder-server:8080/api/v2/users/{user}/workspace/{workspacename}/builds/{buildnumber} \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`GET /users/{user}/workspace/{workspacename}/builds/{buildnumber}` + +### Parameters + +| Name | In | Type | Required | Description | +| --------------- | ---- | -------------- | -------- | -------------------- | +| `user` | path | string | true | User ID, name, or me | +| `workspacename` | path | string | true | Workspace name | +| `buildnumber` | path | string(number) | true | Build number | + +### Example responses + +> 200 Response + +```json +{ + "build_number": 0, + "created_at": "2019-08-24T14:15:22Z", + "daily_cost": 0, + "deadline": "2019-08-24T14:15:22Z", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "initiator_id": "06588898-9a84-4b35-ba8f-f9cbd64946f3", + "initiator_name": "string", + "job": { + "canceled_at": "2019-08-24T14:15:22Z", + "completed_at": "2019-08-24T14:15:22Z", + "created_at": "2019-08-24T14:15:22Z", + "error": "string", + "file_id": "8a0cfb4f-ddc9-436d-91bb-75133c583767", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "started_at": "2019-08-24T14:15:22Z", + "status": "pending", + "tags": { + "property1": "string", + "property2": "string" + }, + "worker_id": "ae5fa6f7-c55b-40c1-b40a-b36ac467652b" + }, + "reason": "initiator", + "resources": [ + { + "agents": [ + { + "apps": [ + { + "command": "string", + "display_name": "string", + "external": true, + "health": "disabled", + "healthcheck": { + "interval": 0, + "threshold": 0, + "url": "string" + }, + "icon": "string", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "sharing_level": "owner", + "slug": "string", + "subdomain": true, + "url": "string" + } + ], + "architecture": "string", + "connection_timeout_seconds": 0, + "created_at": "2019-08-24T14:15:22Z", + "directory": "string", + "disconnected_at": "2019-08-24T14:15:22Z", + "environment_variables": { + "property1": "string", + "property2": "string" + }, + "first_connected_at": "2019-08-24T14:15:22Z", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "instance_id": "string", + "last_connected_at": "2019-08-24T14:15:22Z", + "latency": { + "property1": { + "latency_ms": 0, + "preferred": true + }, + "property2": { + "latency_ms": 0, + "preferred": true + } + }, + "name": "string", + "operating_system": "string", + "resource_id": "4d5215ed-38bb-48ed-879a-fdb9ca58522f", + "startup_script": "string", + "status": "connecting", + "troubleshooting_url": "string", + "updated_at": "2019-08-24T14:15:22Z", + "version": "string" + } + ], + "created_at": "2019-08-24T14:15:22Z", + "daily_cost": 0, + "hide": true, + "icon": "string", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", + "job_id": "453bd7d7-5355-4d6d-a38e-d9e7eb218c3f", + "metadata": [ + { + "key": "string", + "sensitive": true, + "value": "string" + } + ], + "name": "string", + "type": "string", + "workspace_transition": "start" + } + ], + "status": "pending", + "template_version_id": "0ba39c92-1f1b-4c32-aa3e-9925d7713eb1", + "template_version_name": "string", + "transition": "start", + "updated_at": "2019-08-24T14:15:22Z", + "workspace_id": "0967198e-ec7b-4c6b-b4d3-f71244cadbe9", + "workspace_name": "string", + "workspace_owner_id": "e7078695-5279-4c86-8774-3ac2367a2fc7", + "workspace_owner_name": "string" +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------- | ----------- | ------------------------------------------------------------ | +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.WorkspaceBuild](schemas.md#codersdkworkspacebuild) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + ## Get workspace build ### Code samples diff --git a/docs/api/members.md b/docs/api/members.md index 389c6dcdba0e9..7595c00ac0240 100644 --- a/docs/api/members.md +++ b/docs/api/members.md @@ -78,11 +78,11 @@ curl -X PUT http://coder-server:8080/api/v2/organizations/{organization}/members ### Parameters -| Name | In | Type | Required | Description | -| -------------- | ---- | ------------------------------------------------------ | -------- | --------------------- | -| `organization` | path | string | true | Organization ID | -| `user` | path | string | true | Username, UUID, or me | -| `body` | body | [codersdk.UpdateRoles](schemas.md#codersdkupdateroles) | true | Update roles request | +| Name | In | Type | Required | Description | +| -------------- | ---- | ------------------------------------------------------ | -------- | -------------------- | +| `organization` | path | string | true | Organization ID | +| `user` | path | string | true | User ID, name, or me | +| `body` | body | [codersdk.UpdateRoles](schemas.md#codersdkupdateroles) | true | Update roles request | ### Example responses @@ -110,3 +110,49 @@ curl -X PUT http://coder-server:8080/api/v2/organizations/{organization}/members | 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.OrganizationMember](schemas.md#codersdkorganizationmember) | To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Get site member roles + +### Code samples + +```shell +# Example request using curl +curl -X GET http://coder-server:8080/api/v2/users/roles \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`GET /users/roles` + +### Example responses + +> 200 Response + +```json +[ + { + "assignable": true, + "display_name": "string", + "name": "string" + } +] +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------- | ----------- | ----------------------------------------------------------------------- | +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | array of [codersdk.AssignableRoles](schemas.md#codersdkassignableroles) | + +

Response Schema

+ +Status Code **200** + +| Name | Type | Required | Restrictions | Description | +| ---------------- | ------- | -------- | ------------ | ----------- | +| `[array item]` | array | false | | | +| `» assignable` | boolean | false | | | +| `» display_name` | string | false | | | +| `» name` | string | false | | | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). diff --git a/docs/api/schemas.md b/docs/api/schemas.md index ae540089802fa..edb3d95035093 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -16,6 +16,62 @@ | ------------ | ------ | -------- | ------------ | ----------- | | `csp-report` | object | false | | | +## codersdk.APIKey + +```json +{ + "created_at": "2019-08-24T14:15:22Z", + "expires_at": "2019-08-24T14:15:22Z", + "id": "string", + "last_used": "2019-08-24T14:15:22Z", + "lifetime_seconds": 0, + "login_type": "password", + "scope": "all", + "updated_at": "2019-08-24T14:15:22Z", + "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| ------------------ | -------------------------------------------- | -------- | ------------ | ------------------------------------------- | +| `created_at` | string | true | | | +| `expires_at` | string | true | | | +| `id` | string | true | | | +| `last_used` | string | true | | | +| `lifetime_seconds` | integer | true | | | +| `login_type` | [codersdk.LoginType](#codersdklogintype) | true | | | +| `scope` | [codersdk.APIKeyScope](#codersdkapikeyscope) | true | | | +| `updated_at` | string | true | | | +| `user_id` | string | true | | User ID do not ever return the HashedSecret | + +#### Enumerated Values + +| Property | Value | +| ------------ | --------------------- | +| `login_type` | `password` | +| `login_type` | `github` | +| `login_type` | `oidc` | +| `login_type` | `token` | +| `scope` | `all` | +| `scope` | `application_connect` | + +## codersdk.APIKeyScope + +```json +"all" +``` + +### Properties + +#### Enumerated Values + +| Value | +| --------------------- | +| `all` | +| `application_connect` | + ## codersdk.AWSInstanceIdentityToken ```json @@ -201,7 +257,7 @@ "user": { "avatar_url": "http://example.com", "created_at": "2019-08-24T14:15:22Z", - "email": "string", + "email": "user@example.com", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "last_seen_at": "2019-08-24T14:15:22Z", "organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], @@ -277,7 +333,7 @@ "user": { "avatar_url": "http://example.com", "created_at": "2019-08-24T14:15:22Z", - "email": "string", + "email": "user@example.com", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "last_seen_at": "2019-08-24T14:15:22Z", "organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], @@ -304,6 +360,24 @@ | `audit_logs` | array of [codersdk.AuditLog](#codersdkauditlog) | false | | | | `count` | integer | false | | | +## codersdk.AuthMethods + +```json +{ + "github": true, + "oidc": true, + "password": true +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| ---------- | ------- | -------- | ------------ | ----------- | +| `github` | boolean | false | | | +| `oidc` | boolean | false | | | +| `password` | boolean | false | | | + ## codersdk.AuthorizationCheck ```json @@ -455,6 +529,42 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in | `autostart` | | `autostop` | +## codersdk.CreateFirstUserRequest + +```json +{ + "email": "string", + "password": "string", + "trial": true, + "username": "string" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| ---------- | ------- | -------- | ------------ | ----------- | +| `email` | string | true | | | +| `password` | string | true | | | +| `trial` | boolean | false | | | +| `username` | string | true | | | + +## codersdk.CreateFirstUserResponse + +```json +{ + "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6", + "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| ----------------- | ------ | -------- | ------------ | ----------- | +| `organization_id` | string | false | | | +| `user_id` | string | false | | | + ## codersdk.CreateOrganizationRequest ```json @@ -603,6 +713,49 @@ CreateParameterRequest is a structure used to create a new parameter value for a | `resource_type` | `api_key` | | `resource_type` | `group` | +## codersdk.CreateTokenRequest + +```json +{ + "lifetime": 0, + "scope": "all" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| ---------- | -------------------------------------------- | -------- | ------------ | ----------- | +| `lifetime` | integer | false | | | +| `scope` | [codersdk.APIKeyScope](#codersdkapikeyscope) | false | | | + +#### Enumerated Values + +| Property | Value | +| -------- | --------------------- | +| `scope` | `all` | +| `scope` | `application_connect` | + +## codersdk.CreateUserRequest + +```json +{ + "email": "user@example.com", + "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6", + "password": "string", + "username": "string" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| ----------------- | ------ | -------- | ------------ | ----------- | +| `email` | string | true | | | +| `organization_id` | string | true | | | +| `password` | string | true | | | +| `username` | string | true | | | + ## codersdk.CreateWorkspaceBuildRequest ```json @@ -1995,6 +2148,20 @@ CreateParameterRequest is a structure used to create a new parameter value for a | `usage` | string | false | | | | `value` | integer | false | | | +## codersdk.GenerateAPIKeyResponse + +```json +{ + "key": "string" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| ----- | ------ | -------- | ------------ | ----------- | +| `key` | string | false | | | + ## codersdk.GetAppHostResponse ```json @@ -2009,6 +2176,39 @@ CreateParameterRequest is a structure used to create a new parameter value for a | ------ | ------ | -------- | ------------ | ------------------------------------------------------------- | | `host` | string | false | | Host is the externally accessible URL for the Coder instance. | +## codersdk.GetUsersResponse + +```json +{ + "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", + "organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], + "roles": [ + { + "display_name": "string", + "name": "string" + } + ], + "status": "active", + "username": "string" + } + ] +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| ------- | --------------------------------------- | -------- | ------------ | ----------- | +| `count` | integer | false | | | +| `users` | array of [codersdk.User](#codersdkuser) | false | | | + ## codersdk.GitAuthConfig ```json @@ -2039,6 +2239,26 @@ CreateParameterRequest is a structure used to create a new parameter value for a | `type` | string | false | | | | `validate_url` | string | false | | | +## codersdk.GitSSHKey + +```json +{ + "created_at": "2019-08-24T14:15:22Z", + "public_key": "string", + "updated_at": "2019-08-24T14:15:22Z", + "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| ------------ | ------ | -------- | ------------ | ----------- | +| `created_at` | string | false | | | +| `public_key` | string | false | | | +| `updated_at` | string | false | | | +| `user_id` | string | false | | | + ## codersdk.GoogleInstanceIdentityToken ```json @@ -2104,6 +2324,53 @@ CreateParameterRequest is a structure used to create a new parameter value for a | `provisioner_daemon` | | `provisioner` | +## codersdk.LoginType + +```json +"password" +``` + +### Properties + +#### Enumerated Values + +| Value | +| ---------- | +| `password` | +| `github` | +| `oidc` | +| `token` | + +## codersdk.LoginWithPasswordRequest + +```json +{ + "email": "user@example.com", + "password": "string" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| ---------- | ------ | -------- | ------------ | ----------- | +| `email` | string | true | | | +| `password` | string | true | | | + +## codersdk.LoginWithPasswordResponse + +```json +{ + "session_token": "string" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| --------------- | ------ | -------- | ------------ | ----------- | +| `session_token` | string | true | | | + ## codersdk.OAuth2Config ```json @@ -3163,7 +3430,7 @@ Parameter represents a set value for the scope. ```json { "active_user_count": 0, - "active_version_id": "string", + "active_version_id": "eae64611-bd53-4a80-bb77-df1e432c0fbc", "allow_user_cancel_workspace_jobs": true, "build_time_stats": { "property1": { @@ -3265,7 +3532,7 @@ Parameter represents a set value for the scope. { "description": "string", "icon": "string", - "id": "string", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "markdown": "string", "name": "string", "tags": ["string"], @@ -3293,7 +3560,7 @@ Parameter represents a set value for the scope. "created_by": { "avatar_url": "http://example.com", "created_at": "2019-08-24T14:15:22Z", - "email": "string", + "email": "user@example.com", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "last_seen_at": "2019-08-24T14:15:22Z", "organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], @@ -3412,7 +3679,7 @@ Parameter represents a set value for the scope. ```json { - "id": "string" + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08" } ``` @@ -3454,6 +3721,36 @@ Parameter represents a set value for the scope. | ------- | --------------- | -------- | ------------ | ----------- | | `roles` | array of string | false | | | +## codersdk.UpdateUserPasswordRequest + +```json +{ + "old_password": "string", + "password": "string" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| -------------- | ------ | -------- | ------------ | ----------- | +| `old_password` | string | false | | | +| `password` | string | true | | | + +## codersdk.UpdateUserProfileRequest + +```json +{ + "username": "string" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| ---------- | ------ | -------- | ------------ | ----------- | +| `username` | string | true | | | + ## codersdk.UpdateWorkspaceAutostartRequest ```json @@ -3516,7 +3813,7 @@ Parameter represents a set value for the scope. { "avatar_url": "http://example.com", "created_at": "2019-08-24T14:15:22Z", - "email": "string", + "email": "user@example.com", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "last_seen_at": "2019-08-24T14:15:22Z", "organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], diff --git a/docs/api/templates.md b/docs/api/templates.md index 9cc37f5170ffc..ccab73d4cebf3 100644 --- a/docs/api/templates.md +++ b/docs/api/templates.md @@ -29,7 +29,7 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templat [ { "active_user_count": 0, - "active_version_id": "string", + "active_version_id": "eae64611-bd53-4a80-bb77-df1e432c0fbc", "allow_user_cancel_workspace_jobs": true, "build_time_stats": { "property1": { @@ -72,7 +72,7 @@ Status Code **200** | ------------------------------------ | ---------------------------------------------------------------------------- | -------- | ------------ | ------------------------------------------ | | `[array item]` | array | false | | | | `» active_user_count` | integer | false | | ActiveUserCount is set to -1 when loading. | -| `» active_version_id` | string | false | | | +| `» active_version_id` | string(uuid) | false | | | | `» allow_user_cancel_workspace_jobs` | boolean | false | | | | `» build_time_stats` | [codersdk.TemplateBuildTimeStats](schemas.md#codersdktemplatebuildtimestats) | false | | | | `»» [any property]` | [codersdk.TransitionStats](schemas.md#codersdktransitionstats) | false | | | @@ -151,7 +151,7 @@ curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/templa ```json { "active_user_count": 0, - "active_version_id": "string", + "active_version_id": "eae64611-bd53-4a80-bb77-df1e432c0fbc", "allow_user_cancel_workspace_jobs": true, "build_time_stats": { "property1": { @@ -215,7 +215,7 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templat { "description": "string", "icon": "string", - "id": "string", + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "markdown": "string", "name": "string", "tags": ["string"], @@ -234,16 +234,16 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templat Status Code **200** -| Name | Type | Required | Restrictions | Description | -| --------------- | ------ | -------- | ------------ | ----------- | -| `[array item]` | array | false | | | -| `» description` | string | false | | | -| `» icon` | string | false | | | -| `» id` | string | false | | | -| `» markdown` | string | false | | | -| `» name` | string | false | | | -| `» tags` | array | false | | | -| `» url` | string | false | | | +| Name | Type | Required | Restrictions | Description | +| --------------- | ------------ | -------- | ------------ | ----------- | +| `[array item]` | array | false | | | +| `» description` | string | false | | | +| `» icon` | string | false | | | +| `» id` | string(uuid) | false | | | +| `» markdown` | string | false | | | +| `» name` | string | false | | | +| `» tags` | array | false | | | +| `» url` | string | false | | | To perform this operation, you must be authenticated. [Learn more](authentication.md). @@ -274,7 +274,7 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templat ```json { "active_user_count": 0, - "active_version_id": "string", + "active_version_id": "eae64611-bd53-4a80-bb77-df1e432c0fbc", "allow_user_cancel_workspace_jobs": true, "build_time_stats": { "property1": { @@ -358,7 +358,7 @@ curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/templa "created_by": { "avatar_url": "http://example.com", "created_at": "2019-08-24T14:15:22Z", - "email": "string", + "email": "user@example.com", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "last_seen_at": "2019-08-24T14:15:22Z", "organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], @@ -433,7 +433,7 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templat "created_by": { "avatar_url": "http://example.com", "created_at": "2019-08-24T14:15:22Z", - "email": "string", + "email": "user@example.com", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "last_seen_at": "2019-08-24T14:15:22Z", "organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], @@ -508,7 +508,7 @@ curl -X GET http://coder-server:8080/api/v2/organizations/{organization}/templat "created_by": { "avatar_url": "http://example.com", "created_at": "2019-08-24T14:15:22Z", - "email": "string", + "email": "user@example.com", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "last_seen_at": "2019-08-24T14:15:22Z", "organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], @@ -579,7 +579,7 @@ curl -X GET http://coder-server:8080/api/v2/templates/{id} \ ```json { "active_user_count": 0, - "active_version_id": "string", + "active_version_id": "eae64611-bd53-4a80-bb77-df1e432c0fbc", "allow_user_cancel_workspace_jobs": true, "build_time_stats": { "property1": { @@ -685,7 +685,7 @@ curl -X PATCH http://coder-server:8080/api/v2/templates/{id} \ ```json { "active_user_count": 0, - "active_version_id": "string", + "active_version_id": "eae64611-bd53-4a80-bb77-df1e432c0fbc", "allow_user_cancel_workspace_jobs": true, "build_time_stats": { "property1": { @@ -778,9 +778,12 @@ curl -X GET http://coder-server:8080/api/v2/templates/{id}/versions \ ### Parameters -| Name | In | Type | Required | Description | -| ---- | ---- | ------------ | -------- | ----------- | -| `id` | path | string(uuid) | true | Template ID | +| Name | In | Type | Required | Description | +| ---------- | ----- | ------------ | -------- | ----------- | +| `id` | path | string(uuid) | true | Template ID | +| `after_id` | query | string(uuid) | false | After ID | +| `limit` | query | integer | false | Page limit | +| `offset` | query | integer | false | Page offset | ### Example responses @@ -793,7 +796,7 @@ curl -X GET http://coder-server:8080/api/v2/templates/{id}/versions \ "created_by": { "avatar_url": "http://example.com", "created_at": "2019-08-24T14:15:22Z", - "email": "string", + "email": "user@example.com", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "last_seen_at": "2019-08-24T14:15:22Z", "organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], @@ -848,7 +851,7 @@ Status Code **200** | `» created_by` | [codersdk.User](schemas.md#codersdkuser) | false | | | | `»» avatar_url` | string(uri) | false | | | | `»» created_at` | string(date-time) | true | | | -| `»» email` | string | true | | | +| `»» email` | string(email) | true | | | | `»» id` | string(uuid) | true | | | | `»» last_seen_at` | string(date-time) | false | | | | `»» organization_ids` | array | false | | | @@ -909,7 +912,7 @@ curl -X PATCH http://coder-server:8080/api/v2/templates/{id}/versions \ ```json { - "id": "string" + "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08" } ``` @@ -976,7 +979,7 @@ curl -X GET http://coder-server:8080/api/v2/templates/{id}/versions/{templatever "created_by": { "avatar_url": "http://example.com", "created_at": "2019-08-24T14:15:22Z", - "email": "string", + "email": "user@example.com", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "last_seen_at": "2019-08-24T14:15:22Z", "organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], @@ -1031,7 +1034,7 @@ Status Code **200** | `» created_by` | [codersdk.User](schemas.md#codersdkuser) | false | | | | `»» avatar_url` | string(uri) | false | | | | `»» created_at` | string(date-time) | true | | | -| `»» email` | string | true | | | +| `»» email` | string(email) | true | | | | `»» id` | string(uuid) | true | | | | `»» last_seen_at` | string(date-time) | false | | | | `»» organization_ids` | array | false | | | @@ -1103,7 +1106,7 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion} \ "created_by": { "avatar_url": "http://example.com", "created_at": "2019-08-24T14:15:22Z", - "email": "string", + "email": "user@example.com", "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08", "last_seen_at": "2019-08-24T14:15:22Z", "organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], diff --git a/docs/api/users.md b/docs/api/users.md new file mode 100644 index 0000000000000..8531673ba4f3d --- /dev/null +++ b/docs/api/users.md @@ -0,0 +1,1137 @@ +# Users + +> This page is incomplete, stay tuned. + +## Get users + +### Code samples + +```shell +# Example request using curl +curl -X GET http://coder-server:8080/api/v2/users \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`GET /users` + +### Parameters + +| Name | In | Type | Required | Description | +| ---------- | ----- | ------------ | -------- | ------------ | +| `q` | query | string | false | Search query | +| `after_id` | query | string(uuid) | false | After ID | +| `limit` | query | integer | false | Page limit | +| `offset` | query | integer | false | Page offset | + +### Example responses + +> 200 Response + +```json +{ + "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", + "organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], + "roles": [ + { + "display_name": "string", + "name": "string" + } + ], + "status": "active", + "username": "string" + } + ] +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------- | ----------- | ---------------------------------------------------------------- | +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.GetUsersResponse](schemas.md#codersdkgetusersresponse) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Create new user + +### Code samples + +```shell +# Example request using curl +curl -X POST http://coder-server:8080/api/v2/users \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`POST /users` + +> Body parameter + +```json +{ + "email": "user@example.com", + "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6", + "password": "string", + "username": "string" +} +``` + +### Parameters + +| Name | In | Type | Required | Description | +| ------ | ---- | ------------------------------------------------------------------ | -------- | ------------------- | +| `body` | body | [codersdk.CreateUserRequest](schemas.md#codersdkcreateuserrequest) | true | Create user request | + +### Example responses + +> 201 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", + "organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], + "roles": [ + { + "display_name": "string", + "name": "string" + } + ], + "status": "active", + "username": "string" +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------------ | ----------- | ---------------------------------------- | +| 201 | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created | [codersdk.User](schemas.md#codersdkuser) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Get authentication methods + +### Code samples + +```shell +# Example request using curl +curl -X GET http://coder-server:8080/api/v2/users/authmethods \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`GET /users/authmethods` + +### Example responses + +> 200 Response + +```json +{ + "github": true, + "oidc": true, + "password": true +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------- | ----------- | ------------------------------------------------------ | +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.AuthMethods](schemas.md#codersdkauthmethods) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Check initial user created + +### Code samples + +```shell +# Example request using curl +curl -X GET http://coder-server:8080/api/v2/users/first \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`GET /users/first` + +### Example responses + +> 200 Response + +```json +{ + "detail": "string", + "message": "string", + "validations": [ + { + "detail": "string", + "field": "string" + } + ] +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------- | ----------- | ------------------------------------------------ | +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.Response](schemas.md#codersdkresponse) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Create initial user + +### Code samples + +```shell +# Example request using curl +curl -X POST http://coder-server:8080/api/v2/users/first \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`POST /users/first` + +> Body parameter + +```json +{ + "email": "string", + "password": "string", + "trial": true, + "username": "string" +} +``` + +### Parameters + +| Name | In | Type | Required | Description | +| ------ | ---- | ---------------------------------------------------------------------------- | -------- | ------------------ | +| `body` | body | [codersdk.CreateFirstUserRequest](schemas.md#codersdkcreatefirstuserrequest) | true | First user request | + +### Example responses + +> 201 Response + +```json +{ + "organization_id": "7c60d51f-b44e-4682-87d6-449835ea4de6", + "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5" +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------------ | ----------- | ------------------------------------------------------------------------------ | +| 201 | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created | [codersdk.CreateFirstUserResponse](schemas.md#codersdkcreatefirstuserresponse) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Log out user + +### Code samples + +```shell +# Example request using curl +curl -X POST http://coder-server:8080/api/v2/users/logout \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`POST /users/logout` + +### Example responses + +> 200 Response + +```json +{ + "detail": "string", + "message": "string", + "validations": [ + { + "detail": "string", + "field": "string" + } + ] +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------- | ----------- | ------------------------------------------------ | +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.Response](schemas.md#codersdkresponse) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## OAuth 2.0 GitHub Callback + +### Code samples + +```shell +# Example request using curl +curl -X GET http://coder-server:8080/api/v2/users/oauth2/github/callback \ + -H 'Coder-Session-Token: API_KEY' +``` + +`GET /users/oauth2/github/callback` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ----------------------------------------------------------------------- | ------------------ | ------ | +| 307 | [Temporary Redirect](https://tools.ietf.org/html/rfc7231#section-6.4.7) | Temporary Redirect | | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## OpenID Connect Callback + +### Code samples + +```shell +# Example request using curl +curl -X GET http://coder-server:8080/api/v2/users/oidc/callback \ + -H 'Coder-Session-Token: API_KEY' +``` + +`GET /users/oidc/callback` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ----------------------------------------------------------------------- | ------------------ | ------ | +| 307 | [Temporary Redirect](https://tools.ietf.org/html/rfc7231#section-6.4.7) | Temporary Redirect | | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Get user by name + +### Code samples + +```shell +# Example request using curl +curl -X GET http://coder-server:8080/api/v2/users/{user} \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`GET /users/{user}` + +### Parameters + +| Name | In | Type | Required | Description | +| ------ | ---- | ------ | -------- | -------------------- | +| `user` | path | string | true | User ID, name, or me | + +### Example responses + +> 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", + "organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], + "roles": [ + { + "display_name": "string", + "name": "string" + } + ], + "status": "active", + "username": "string" +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------- | ----------- | ---------------------------------------- | +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.User](schemas.md#codersdkuser) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Delete user + +### Code samples + +```shell +# Example request using curl +curl -X DELETE http://coder-server:8080/api/v2/users/{user} \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`DELETE /users/{user}` + +### Parameters + +| Name | In | Type | Required | Description | +| ------ | ---- | ------ | -------- | -------------------- | +| `user` | path | string | true | User ID, name, or me | + +### Example responses + +> 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", + "organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], + "roles": [ + { + "display_name": "string", + "name": "string" + } + ], + "status": "active", + "username": "string" +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------- | ----------- | ---------------------------------------- | +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.User](schemas.md#codersdkuser) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Get user Git SSH key + +### Code samples + +```shell +# Example request using curl +curl -X GET http://coder-server:8080/api/v2/users/{user}/gitsshkey \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`GET /users/{user}/gitsshkey` + +### Parameters + +| Name | In | Type | Required | Description | +| ------ | ---- | ------ | -------- | -------------------- | +| `user` | path | string | true | User ID, name, or me | + +### Example responses + +> 200 Response + +```json +{ + "created_at": "2019-08-24T14:15:22Z", + "public_key": "string", + "updated_at": "2019-08-24T14:15:22Z", + "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5" +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------- | ----------- | -------------------------------------------------- | +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.GitSSHKey](schemas.md#codersdkgitsshkey) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Regenerate user SSH key + +### Code samples + +```shell +# Example request using curl +curl -X PUT http://coder-server:8080/api/v2/users/{user}/gitsshkey \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`PUT /users/{user}/gitsshkey` + +### Parameters + +| Name | In | Type | Required | Description | +| ------ | ---- | ------ | -------- | -------------------- | +| `user` | path | string | true | User ID, name, or me | + +### Example responses + +> 200 Response + +```json +{ + "created_at": "2019-08-24T14:15:22Z", + "public_key": "string", + "updated_at": "2019-08-24T14:15:22Z", + "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5" +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------- | ----------- | -------------------------------------------------- | +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.GitSSHKey](schemas.md#codersdkgitsshkey) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Create new session key + +### Code samples + +```shell +# Example request using curl +curl -X POST http://coder-server:8080/api/v2/users/{user}/keys \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`POST /users/{user}/keys` + +### Parameters + +| Name | In | Type | Required | Description | +| ------ | ---- | ------ | -------- | -------------------- | +| `user` | path | string | true | User ID, name, or me | + +### Example responses + +> 201 Response + +```json +{ + "key": "string" +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------------ | ----------- | ---------------------------------------------------------------------------- | +| 201 | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created | [codersdk.GenerateAPIKeyResponse](schemas.md#codersdkgenerateapikeyresponse) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Get user tokens + +### Code samples + +```shell +# Example request using curl +curl -X GET http://coder-server:8080/api/v2/users/{user}/keys/tokens \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`GET /users/{user}/keys/tokens` + +### Parameters + +| Name | In | Type | Required | Description | +| ------ | ---- | ------ | -------- | -------------------- | +| `user` | path | string | true | User ID, name, or me | + +### Example responses + +> 200 Response + +```json +[ + { + "created_at": "2019-08-24T14:15:22Z", + "expires_at": "2019-08-24T14:15:22Z", + "id": "string", + "last_used": "2019-08-24T14:15:22Z", + "lifetime_seconds": 0, + "login_type": "password", + "scope": "all", + "updated_at": "2019-08-24T14:15:22Z", + "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5" + } +] +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------- | ----------- | ----------------------------------------------------- | +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | array of [codersdk.APIKey](schemas.md#codersdkapikey) | + +

Response Schema

+ +Status Code **200** + +| Name | Type | Required | Restrictions | Description | +| -------------------- | ------------------------------------------------------ | -------- | ------------ | ----------------------------------------- | +| `[array item]` | array | false | | | +| `» created_at` | string(date-time) | true | | | +| `» expires_at` | string(date-time) | true | | | +| `» id` | string | true | | | +| `» last_used` | string(date-time) | true | | | +| `» lifetime_seconds` | integer | true | | | +| `» login_type` | [codersdk.LoginType](schemas.md#codersdklogintype) | true | | | +| `» scope` | [codersdk.APIKeyScope](schemas.md#codersdkapikeyscope) | true | | | +| `» updated_at` | string(date-time) | true | | | +| `» user_id` | string(uuid) | true | | NOTE: do not ever return the HashedSecret | + +#### Enumerated Values + +| Property | Value | +| ------------ | --------------------- | +| `login_type` | `password` | +| `login_type` | `github` | +| `login_type` | `oidc` | +| `login_type` | `token` | +| `scope` | `all` | +| `scope` | `application_connect` | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Create token API key + +### Code samples + +```shell +# Example request using curl +curl -X POST http://coder-server:8080/api/v2/users/{user}/keys/tokens \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`POST /users/{user}/keys/tokens` + +> Body parameter + +```json +{ + "lifetime": 0, + "scope": "all" +} +``` + +### Parameters + +| Name | In | Type | Required | Description | +| ------ | ---- | -------------------------------------------------------------------- | -------- | -------------------- | +| `user` | path | string | true | User ID, name, or me | +| `body` | body | [codersdk.CreateTokenRequest](schemas.md#codersdkcreatetokenrequest) | true | Create token request | + +### Example responses + +> 201 Response + +```json +{ + "key": "string" +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------------ | ----------- | ---------------------------------------------------------------------------- | +| 201 | [Created](https://tools.ietf.org/html/rfc7231#section-6.3.2) | Created | [codersdk.GenerateAPIKeyResponse](schemas.md#codersdkgenerateapikeyresponse) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Get API key + +### Code samples + +```shell +# Example request using curl +curl -X GET http://coder-server:8080/api/v2/users/{user}/keys/{keyid} \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`GET /users/{user}/keys/{keyid}` + +### Parameters + +| Name | In | Type | Required | Description | +| ------- | ---- | ------------ | -------- | -------------------- | +| `user` | path | string | true | User ID, name, or me | +| `keyid` | path | string(uuid) | true | Key ID | + +### Example responses + +> 200 Response + +```json +{ + "created_at": "2019-08-24T14:15:22Z", + "expires_at": "2019-08-24T14:15:22Z", + "id": "string", + "last_used": "2019-08-24T14:15:22Z", + "lifetime_seconds": 0, + "login_type": "password", + "scope": "all", + "updated_at": "2019-08-24T14:15:22Z", + "user_id": "a169451c-8525-4352-b8ca-070dd449a1a5" +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------- | ----------- | -------------------------------------------- | +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.APIKey](schemas.md#codersdkapikey) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Delete API key + +### Code samples + +```shell +# Example request using curl +curl -X DELETE http://coder-server:8080/api/v2/users/{user}/keys/{keyid} \ + -H 'Coder-Session-Token: API_KEY' +``` + +`DELETE /users/{user}/keys/{keyid}` + +### Parameters + +| Name | In | Type | Required | Description | +| ------- | ---- | ------------ | -------- | -------------------- | +| `user` | path | string | true | User ID, name, or me | +| `keyid` | path | string(uuid) | true | Key ID | + +### 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). + +## Get organizations by user + +### Code samples + +```shell +# Example request using curl +curl -X GET http://coder-server:8080/api/v2/users/{user}/organizations \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`GET /users/{user}/organizations` + +### Parameters + +| Name | In | Type | Required | Description | +| ------ | ---- | ------ | -------- | -------------------- | +| `user` | path | string | true | User ID, name, or me | + +### Example responses + +> 200 Response + +```json +[ + { + "created_at": "2019-08-24T14:15:22Z", + "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.Organization](schemas.md#codersdkorganization) | + +

Response Schema

+ +Status Code **200** + +| Name | Type | Required | Restrictions | Description | +| -------------- | ----------------- | -------- | ------------ | ----------- | +| `[array item]` | array | false | | | +| `» created_at` | string(date-time) | true | | | +| `» id` | string(uuid) | true | | | +| `» name` | string | true | | | +| `» updated_at` | string(date-time) | true | | | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Get organization by user and organization name + +### Code samples + +```shell +# Example request using curl +curl -X GET http://coder-server:8080/api/v2/users/{user}/organizations/{organizationname} \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`GET /users/{user}/organizations/{organizationname}` + +### Parameters + +| Name | In | Type | Required | Description | +| ------------------ | ---- | ------ | -------- | -------------------- | +| `user` | path | string | true | User ID, name, or me | +| `organizationname` | path | string | true | Organization name | + +### Example responses + +> 200 Response + +```json +{ + "created_at": "2019-08-24T14:15:22Z", + "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.Organization](schemas.md#codersdkorganization) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Update user password + +### Code samples + +```shell +# Example request using curl +curl -X PUT http://coder-server:8080/api/v2/users/{user}/password \ + -H 'Content-Type: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`PUT /users/{user}/password` + +> Body parameter + +```json +{ + "old_password": "string", + "password": "string" +} +``` + +### Parameters + +| Name | In | Type | Required | Description | +| ------ | ---- | ---------------------------------------------------------------------------------- | -------- | ----------------------- | +| `user` | path | string | true | User ID, name, or me | +| `body` | body | [codersdk.UpdateUserPasswordRequest](schemas.md#codersdkupdateuserpasswordrequest) | true | Update password request | + +### 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 user profile + +### Code samples + +```shell +# Example request using curl +curl -X PUT http://coder-server:8080/api/v2/users/{user}/profile \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`PUT /users/{user}/profile` + +> Body parameter + +```json +{ + "username": "string" +} +``` + +### Parameters + +| Name | In | Type | Required | Description | +| ------ | ---- | -------------------------------------------------------------------------------- | -------- | -------------------- | +| `user` | path | string | true | User ID, name, or me | +| `body` | body | [codersdk.UpdateUserProfileRequest](schemas.md#codersdkupdateuserprofilerequest) | true | Updated profile | + +### Example responses + +> 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", + "organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], + "roles": [ + { + "display_name": "string", + "name": "string" + } + ], + "status": "active", + "username": "string" +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------- | ----------- | ---------------------------------------- | +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.User](schemas.md#codersdkuser) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Get user roles + +### Code samples + +```shell +# Example request using curl +curl -X GET http://coder-server:8080/api/v2/users/{user}/roles \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`GET /users/{user}/roles` + +### Parameters + +| Name | In | Type | Required | Description | +| ------ | ---- | ------ | -------- | -------------------- | +| `user` | path | string | true | User ID, name, or me | + +### Example responses + +> 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", + "organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], + "roles": [ + { + "display_name": "string", + "name": "string" + } + ], + "status": "active", + "username": "string" +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------- | ----------- | ---------------------------------------- | +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.User](schemas.md#codersdkuser) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Assign role to user + +### Code samples + +```shell +# Example request using curl +curl -X PUT http://coder-server:8080/api/v2/users/{user}/roles \ + -H 'Content-Type: application/json' \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`PUT /users/{user}/roles` + +> Body parameter + +```json +{ + "roles": ["string"] +} +``` + +### Parameters + +| Name | In | Type | Required | Description | +| ------ | ---- | ------------------------------------------------------ | -------- | -------------------- | +| `user` | path | string | true | User ID, name, or me | +| `body` | body | [codersdk.UpdateRoles](schemas.md#codersdkupdateroles) | true | Update roles request | + +### Example responses + +> 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", + "organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], + "roles": [ + { + "display_name": "string", + "name": "string" + } + ], + "status": "active", + "username": "string" +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------- | ----------- | ---------------------------------------- | +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.User](schemas.md#codersdkuser) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Activate user account + +### Code samples + +```shell +# Example request using curl +curl -X PUT http://coder-server:8080/api/v2/users/{user}/status/activate \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`PUT /users/{user}/status/activate` + +### Parameters + +| Name | In | Type | Required | Description | +| ------ | ---- | ------ | -------- | -------------------- | +| `user` | path | string | true | User ID, name, or me | + +### Example responses + +> 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", + "organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], + "roles": [ + { + "display_name": "string", + "name": "string" + } + ], + "status": "active", + "username": "string" +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------- | ----------- | ---------------------------------------- | +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.User](schemas.md#codersdkuser) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). + +## Suspend user account + +### Code samples + +```shell +# Example request using curl +curl -X PUT http://coder-server:8080/api/v2/users/{user}/status/suspend \ + -H 'Accept: application/json' \ + -H 'Coder-Session-Token: API_KEY' +``` + +`PUT /users/{user}/status/suspend` + +### Parameters + +| Name | In | Type | Required | Description | +| ------ | ---- | ------ | -------- | -------------------- | +| `user` | path | string | true | User ID, name, or me | + +### Example responses + +> 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", + "organization_ids": ["497f6eca-6276-4993-bfeb-53cbbbba6f08"], + "roles": [ + { + "display_name": "string", + "name": "string" + } + ], + "status": "active", + "username": "string" +} +``` + +### Responses + +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------- | ----------- | ---------------------------------------- | +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.User](schemas.md#codersdkuser) | + +To perform this operation, you must be authenticated. [Learn more](authentication.md). diff --git a/docs/api/workspaces.md b/docs/api/workspaces.md index ab06dbfe4e779..c97140e001257 100644 --- a/docs/api/workspaces.md +++ b/docs/api/workspaces.md @@ -162,7 +162,7 @@ curl -X POST http://coder-server:8080/api/v2/organizations/{organization}/member To perform this operation, you must be authenticated. [Learn more](authentication.md). -## Get workspace metadata by owner and workspace name +## Get workspace metadata by user and workspace name ### Code samples @@ -179,7 +179,7 @@ curl -X GET http://coder-server:8080/api/v2/users/{user}/workspace/{workspacenam | Name | In | Type | Required | Description | | ----------------- | ----- | ------- | -------- | ----------------------------------------------------------- | -| `user` | path | string | true | Owner username | +| `user` | path | string | true | User ID, name, or me | | `workspacename` | path | string | true | Workspace name | | `include_deleted` | query | boolean | false | Return data instead of HTTP 404 if the workspace is deleted | diff --git a/docs/manifest.json b/docs/manifest.json index 603771bedcb0b..d0b0d78417b05 100644 --- a/docs/manifest.json +++ b/docs/manifest.json @@ -370,13 +370,17 @@ "path": "./api/parameters.md" }, { - "title": "Agents", - "path": "./api/agents.md" + "title": "Users", + "path": "./api/users.md" }, { "title": "Builds", "path": "./api/builds.md" }, + { + "title": "Agents", + "path": "./api/agents.md" + }, { "title": "Schemas", "path": "./api/schemas.md"