From ec0e12ddc459d9f69fe8660ad1281c4937bbff0d Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Fri, 29 Sep 2023 19:56:01 +0000 Subject: [PATCH 1/6] chore: move `/gitauth` to `/externalauth` on the frontend This actually took a lot more jank than anticipated, so I wanted to split this up before adding the ability to embed new providers. --- .vscode/settings.json | 1 + cli/create_test.go | 8 +- cli/server.go | 12 +- coderd/apidoc/docs.go | 320 +++++++++--------- coderd/apidoc/swagger.json | 312 ++++++++--------- coderd/coderd.go | 47 +-- coderd/coderdtest/coderdtest.go | 12 +- coderd/database/dbauthz/dbauthz.go | 2 +- coderd/{gitauth.go => externalauth.go} | 74 ++-- coderd/{gitauth => externalauth}/config.go | 60 ++-- .../{gitauth => externalauth}/config_test.go | 40 +-- coderd/{gitauth => externalauth}/oauth.go | 8 +- .../{gitauth_test.go => externalauth_test.go} | 84 ++--- coderd/gitauth/oauth_test.go | 9 - coderd/httpmw/externalauthparam.go | 40 +++ ...aram_test.go => externalauthparam_test.go} | 14 +- coderd/httpmw/gitauthparam.go | 40 --- .../patternmatcher/routepatterns_test.go | 4 +- .../provisionerdserver/provisionerdserver.go | 8 +- .../provisionerdserver_test.go | 10 +- coderd/templateversions.go | 18 +- coderd/templateversions_test.go | 10 +- coderd/tracing/httpmw.go | 2 +- coderd/tracing/httpmw_test.go | 2 +- coderd/workspaceagents.go | 48 +-- codersdk/{gitauth.go => externalauth.go} | 54 +-- codersdk/templateversions.go | 2 +- docs/api/git.md | 48 +-- docs/api/schemas.md | 214 ++++++------ docs/api/templates.md | 8 +- provisioner/echo/serve.go | 8 +- provisioner/terraform/executor.go | 14 +- provisioner/terraform/resources.go | 12 +- provisioner/terraform/resources_test.go | 8 +- provisionerd/runner/runner.go | 2 +- provisionersdk/proto/provisioner.pb.go | 174 +++++----- provisionersdk/proto/provisioner.proto | 4 +- site/e2e/tests/gitAuth.spec.ts | 14 +- site/src/AppRouter.tsx | 2 +- site/src/api/api.ts | 22 +- site/src/api/queries/templates.ts | 2 +- site/src/api/typesGenerated.ts | 80 ++--- .../CreateWorkspacePage.test.tsx | 10 +- site/src/pages/GitAuthPage/GitAuthPage.tsx | 58 ++-- .../GitAuthPage/GitAuthPageView.stories.tsx | 16 +- .../src/pages/GitAuthPage/GitAuthPageView.tsx | 28 +- site/src/testHelpers/entities.ts | 4 +- site/src/testHelpers/handlers.ts | 2 +- site/src/utils/gitAuth.ts | 1 - 49 files changed, 984 insertions(+), 988 deletions(-) rename coderd/{gitauth.go => externalauth.go} (73%) rename coderd/{gitauth => externalauth}/config.go (83%) rename coderd/{gitauth => externalauth}/config_test.go (91%) rename coderd/{gitauth => externalauth}/oauth.go (98%) rename coderd/{gitauth_test.go => externalauth_test.go} (84%) delete mode 100644 coderd/gitauth/oauth_test.go create mode 100644 coderd/httpmw/externalauthparam.go rename coderd/httpmw/{gitauthparam_test.go => externalauthparam_test.go} (72%) delete mode 100644 coderd/httpmw/gitauthparam.go rename codersdk/{gitauth.go => externalauth.go} (51%) delete mode 100644 site/src/utils/gitAuth.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index b187ed265fd71..0664d7e81cc75 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -39,6 +39,7 @@ "enterprisemeta", "errgroup", "eventsourcemock", + "externalauth", "Failf", "fatih", "Formik", diff --git a/cli/create_test.go b/cli/create_test.go index 6c516ae8d8414..2cd4c9abaaabf 100644 --- a/cli/create_test.go +++ b/cli/create_test.go @@ -14,7 +14,7 @@ import ( "github.com/coder/coder/v2/cli/clitest" "github.com/coder/coder/v2/coderd/coderdtest" - "github.com/coder/coder/v2/coderd/gitauth" + "github.com/coder/coder/v2/coderd/externalauth" "github.com/coder/coder/v2/coderd/util/ptr" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/provisioner/echo" @@ -600,7 +600,7 @@ func TestCreateWithGitAuth(t *testing.T) { { Type: &proto.Response_Plan{ Plan: &proto.PlanComplete{ - GitAuthProviders: []string{"github"}, + ExternalAuthProviders: []string{"github"}, }, }, }, @@ -609,7 +609,7 @@ func TestCreateWithGitAuth(t *testing.T) { } client := coderdtest.New(t, &coderdtest.Options{ - ExternalAuthConfigs: []*gitauth.Config{{ + ExternalAuthConfigs: []*externalauth.Config{{ OAuth2Config: &testutil.OAuth2Config{}, ID: "github", Regex: regexp.MustCompile(`github\.com`), @@ -628,7 +628,7 @@ func TestCreateWithGitAuth(t *testing.T) { clitest.Start(t, inv) pty.ExpectMatch("You must authenticate with GitHub to create a workspace") - resp := coderdtest.RequestGitAuthCallback(t, "github", client) + resp := coderdtest.RequestExternalAuthCallback(t, "github", client) _ = resp.Body.Close() require.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode) pty.ExpectMatch("Confirm create?") diff --git a/cli/server.go b/cli/server.go index 634bb059dd63d..b0ec9f999b448 100644 --- a/cli/server.go +++ b/cli/server.go @@ -72,7 +72,7 @@ import ( "github.com/coder/coder/v2/coderd/database/migrations" "github.com/coder/coder/v2/coderd/database/pubsub" "github.com/coder/coder/v2/coderd/devtunnel" - "github.com/coder/coder/v2/coderd/gitauth" + "github.com/coder/coder/v2/coderd/externalauth" "github.com/coder/coder/v2/coderd/gitsshkey" "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/httpmw" @@ -574,16 +574,16 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd. } vals.GitAuthProviders.Value = append(vals.GitAuthProviders.Value, gitAuthEnv...) - gitAuthConfigs, err := gitauth.ConvertConfig( + externalAuthConfigs, err := externalauth.ConvertConfig( vals.GitAuthProviders.Value, vals.AccessURL.Value(), ) if err != nil { - return xerrors.Errorf("convert git auth config: %w", err) + return xerrors.Errorf("convert external auth config: %w", err) } - for _, c := range gitAuthConfigs { + for _, c := range externalAuthConfigs { logger.Debug( - ctx, "loaded git auth config", + ctx, "loaded external auth config", slog.F("id", c.ID), ) } @@ -608,7 +608,7 @@ func (r *RootCmd) Server(newAPI func(context.Context, *coderd.Options) (*coderd. Pubsub: pubsub.NewInMemory(), CacheDir: cacheDir, GoogleTokenValidator: googleTokenValidator, - ExternalAuthConfigs: gitAuthConfigs, + ExternalAuthConfigs: externalAuthConfigs, RealIPConfig: realIPConfig, SecureAuthCookie: vals.SecureAuthCookie.Value(), SSHKeygenAlgorithm: sshKeygenAlgorithm, diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 003baf16796b4..ab794794f6e3e 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -602,174 +602,174 @@ const docTemplate = `{ } } }, - "/files": { - "post": { + "/externalauth/{externalauth}": { + "get": { "security": [ { "CoderSessionToken": [] } ], - "description": "Swagger notice: Swagger 2.0 doesn't support file upload with a ` + "`" + `content-type` + "`" + ` different than ` + "`" + `application/x-www-form-urlencoded` + "`" + `.", - "consumes": [ - "application/x-tar" - ], "produces": [ "application/json" ], "tags": [ - "Files" + "Git" ], - "summary": "Upload file", - "operationId": "upload-file", + "summary": "Get external auth by ID", + "operationId": "get-external-auth-by-id", "parameters": [ { "type": "string", - "default": "application/x-tar", - "description": "Content-Type must be ` + "`" + `application/x-tar` + "`" + `", - "name": "Content-Type", - "in": "header", - "required": true - }, - { - "type": "file", - "description": "File to be uploaded", - "name": "file", - "in": "formData", + "format": "string", + "description": "Git Provider ID", + "name": "externalauth", + "in": "path", "required": true } ], "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/codersdk.UploadResponse" + "$ref": "#/definitions/codersdk.ExternalAuth" } } } } }, - "/files/{fileID}": { + "/externalauth/{externalauth}/device": { "get": { "security": [ { "CoderSessionToken": [] } ], + "produces": [ + "application/json" + ], "tags": [ - "Files" + "Git" ], - "summary": "Get file by ID", - "operationId": "get-file-by-id", + "summary": "Get external auth device by ID.", + "operationId": "get-external-auth-device-by-id", "parameters": [ { "type": "string", - "format": "uuid", - "description": "File ID", - "name": "fileID", + "format": "string", + "description": "Git Provider ID", + "name": "externalauth", "in": "path", "required": true } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.ExternalAuthDevice" + } } } - } - }, - "/gitauth/{gitauth}": { - "get": { + }, + "post": { "security": [ { "CoderSessionToken": [] } ], - "produces": [ - "application/json" - ], "tags": [ "Git" ], - "summary": "Get git auth by ID", - "operationId": "get-git-auth-by-id", + "summary": "Post external auth device by ID", + "operationId": "post-external-auth-device-by-id", "parameters": [ { "type": "string", "format": "string", - "description": "Git Provider ID", - "name": "gitauth", + "description": "External Provider ID", + "name": "externalauth", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/codersdk.GitAuth" - } + "204": { + "description": "No Content" } } } }, - "/gitauth/{gitauth}/device": { - "get": { + "/files": { + "post": { "security": [ { "CoderSessionToken": [] } ], + "description": "Swagger notice: Swagger 2.0 doesn't support file upload with a ` + "`" + `content-type` + "`" + ` different than ` + "`" + `application/x-www-form-urlencoded` + "`" + `.", + "consumes": [ + "application/x-tar" + ], "produces": [ "application/json" ], "tags": [ - "Git" + "Files" ], - "summary": "Get git auth device by ID.", - "operationId": "get-git-auth-device-by-id", + "summary": "Upload file", + "operationId": "upload-file", "parameters": [ { "type": "string", - "format": "string", - "description": "Git Provider ID", - "name": "gitauth", - "in": "path", + "default": "application/x-tar", + "description": "Content-Type must be ` + "`" + `application/x-tar` + "`" + `", + "name": "Content-Type", + "in": "header", + "required": true + }, + { + "type": "file", + "description": "File to be uploaded", + "name": "file", + "in": "formData", "required": true } ], "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "schema": { - "$ref": "#/definitions/codersdk.GitAuthDevice" + "$ref": "#/definitions/codersdk.UploadResponse" } } } - }, - "post": { + } + }, + "/files/{fileID}": { + "get": { "security": [ { "CoderSessionToken": [] } ], "tags": [ - "Git" + "Files" ], - "summary": "Post git auth device by ID", - "operationId": "post-git-auth-device-by-id", + "summary": "Get file by ID", + "operationId": "get-file-by-id", "parameters": [ { "type": "string", - "format": "string", - "description": "Git Provider ID", - "name": "gitauth", + "format": "uuid", + "description": "File ID", + "name": "fileID", "in": "path", "required": true } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK" } } } @@ -2768,7 +2768,7 @@ const docTemplate = `{ } } }, - "/templateversions/{templateversion}/gitauth": { + "/templateversions/{templateversion}/externalauth": { "get": { "security": [ { @@ -2781,8 +2781,8 @@ const docTemplate = `{ "tags": [ "Templates" ], - "summary": "Get git auth by template version", - "operationId": "get-git-auth-by-template-version", + "summary": "Get external auth by template version", + "operationId": "get-external-auth-by-template-version", "parameters": [ { "type": "string", @@ -8186,6 +8186,77 @@ const docTemplate = `{ "ExperimentDeploymentHealthPage" ] }, + "codersdk.ExternalAuth": { + "type": "object", + "properties": { + "app_install_url": { + "description": "AppInstallURL is the URL to install the app.", + "type": "string" + }, + "app_installable": { + "description": "AppInstallable is true if the request for app installs was successful.", + "type": "boolean" + }, + "authenticated": { + "type": "boolean" + }, + "device": { + "type": "boolean" + }, + "installations": { + "description": "AppInstallations are the installations that the user has access to.", + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.ExternalAuthAppInstallation" + } + }, + "type": { + "type": "string" + }, + "user": { + "description": "User is the user that authenticated with the provider.", + "allOf": [ + { + "$ref": "#/definitions/codersdk.ExternalAuthUser" + } + ] + } + } + }, + "codersdk.ExternalAuthAppInstallation": { + "type": "object", + "properties": { + "account": { + "$ref": "#/definitions/codersdk.ExternalAuthUser" + }, + "configure_url": { + "type": "string" + }, + "id": { + "type": "integer" + } + } + }, + "codersdk.ExternalAuthDevice": { + "type": "object", + "properties": { + "device_code": { + "type": "string" + }, + "expires_in": { + "type": "integer" + }, + "interval": { + "type": "integer" + }, + "user_code": { + "type": "string" + }, + "verification_uri": { + "type": "string" + } + } + }, "codersdk.ExternalAuthProvider": { "type": "string", "enum": [ @@ -8203,6 +8274,23 @@ const docTemplate = `{ "ExternalAuthProviderOpenIDConnect" ] }, + "codersdk.ExternalAuthUser": { + "type": "object", + "properties": { + "avatar_url": { + "type": "string" + }, + "login": { + "type": "string" + }, + "name": { + "type": "string" + }, + "profile_url": { + "type": "string" + } + } + }, "codersdk.Feature": { "type": "object", "properties": { @@ -8242,57 +8330,6 @@ const docTemplate = `{ } } }, - "codersdk.GitAuth": { - "type": "object", - "properties": { - "app_install_url": { - "description": "AppInstallURL is the URL to install the app.", - "type": "string" - }, - "app_installable": { - "description": "AppInstallable is true if the request for app installs was successful.", - "type": "boolean" - }, - "authenticated": { - "type": "boolean" - }, - "device": { - "type": "boolean" - }, - "installations": { - "description": "AppInstallations are the installations that the user has access to.", - "type": "array", - "items": { - "$ref": "#/definitions/codersdk.GitAuthAppInstallation" - } - }, - "type": { - "type": "string" - }, - "user": { - "description": "User is the user that authenticated with the provider.", - "allOf": [ - { - "$ref": "#/definitions/codersdk.GitAuthUser" - } - ] - } - } - }, - "codersdk.GitAuthAppInstallation": { - "type": "object", - "properties": { - "account": { - "$ref": "#/definitions/codersdk.GitAuthUser" - }, - "configure_url": { - "type": "string" - }, - "id": { - "type": "integer" - } - } - }, "codersdk.GitAuthConfig": { "type": "object", "properties": { @@ -8340,43 +8377,6 @@ const docTemplate = `{ } } }, - "codersdk.GitAuthDevice": { - "type": "object", - "properties": { - "device_code": { - "type": "string" - }, - "expires_in": { - "type": "integer" - }, - "interval": { - "type": "integer" - }, - "user_code": { - "type": "string" - }, - "verification_uri": { - "type": "string" - } - } - }, - "codersdk.GitAuthUser": { - "type": "object", - "properties": { - "avatar_url": { - "type": "string" - }, - "login": { - "type": "string" - }, - "name": { - "type": "string" - }, - "profile_url": { - "type": "string" - } - } - }, "codersdk.GitSSHKey": { "type": "object", "properties": { diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index ec02780589503..7a7ee0a69e12c 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -512,156 +512,156 @@ } } }, - "/files": { - "post": { + "/externalauth/{externalauth}": { + "get": { "security": [ { "CoderSessionToken": [] } ], - "description": "Swagger notice: Swagger 2.0 doesn't support file upload with a `content-type` different than `application/x-www-form-urlencoded`.", - "consumes": ["application/x-tar"], "produces": ["application/json"], - "tags": ["Files"], - "summary": "Upload file", - "operationId": "upload-file", + "tags": ["Git"], + "summary": "Get external auth by ID", + "operationId": "get-external-auth-by-id", "parameters": [ { "type": "string", - "default": "application/x-tar", - "description": "Content-Type must be `application/x-tar`", - "name": "Content-Type", - "in": "header", - "required": true - }, - { - "type": "file", - "description": "File to be uploaded", - "name": "file", - "in": "formData", + "format": "string", + "description": "Git Provider ID", + "name": "externalauth", + "in": "path", "required": true } ], "responses": { - "201": { - "description": "Created", + "200": { + "description": "OK", "schema": { - "$ref": "#/definitions/codersdk.UploadResponse" + "$ref": "#/definitions/codersdk.ExternalAuth" } } } } }, - "/files/{fileID}": { + "/externalauth/{externalauth}/device": { "get": { "security": [ { "CoderSessionToken": [] } ], - "tags": ["Files"], - "summary": "Get file by ID", - "operationId": "get-file-by-id", + "produces": ["application/json"], + "tags": ["Git"], + "summary": "Get external auth device by ID.", + "operationId": "get-external-auth-device-by-id", "parameters": [ { "type": "string", - "format": "uuid", - "description": "File ID", - "name": "fileID", + "format": "string", + "description": "Git Provider ID", + "name": "externalauth", "in": "path", "required": true } ], "responses": { "200": { - "description": "OK" + "description": "OK", + "schema": { + "$ref": "#/definitions/codersdk.ExternalAuthDevice" + } } } - } - }, - "/gitauth/{gitauth}": { - "get": { + }, + "post": { "security": [ { "CoderSessionToken": [] } ], - "produces": ["application/json"], "tags": ["Git"], - "summary": "Get git auth by ID", - "operationId": "get-git-auth-by-id", + "summary": "Post external auth device by ID", + "operationId": "post-external-auth-device-by-id", "parameters": [ { "type": "string", "format": "string", - "description": "Git Provider ID", - "name": "gitauth", + "description": "External Provider ID", + "name": "externalauth", "in": "path", "required": true } ], "responses": { - "200": { - "description": "OK", - "schema": { - "$ref": "#/definitions/codersdk.GitAuth" - } + "204": { + "description": "No Content" } } } }, - "/gitauth/{gitauth}/device": { - "get": { + "/files": { + "post": { "security": [ { "CoderSessionToken": [] } ], + "description": "Swagger notice: Swagger 2.0 doesn't support file upload with a `content-type` different than `application/x-www-form-urlencoded`.", + "consumes": ["application/x-tar"], "produces": ["application/json"], - "tags": ["Git"], - "summary": "Get git auth device by ID.", - "operationId": "get-git-auth-device-by-id", + "tags": ["Files"], + "summary": "Upload file", + "operationId": "upload-file", "parameters": [ { "type": "string", - "format": "string", - "description": "Git Provider ID", - "name": "gitauth", - "in": "path", + "default": "application/x-tar", + "description": "Content-Type must be `application/x-tar`", + "name": "Content-Type", + "in": "header", + "required": true + }, + { + "type": "file", + "description": "File to be uploaded", + "name": "file", + "in": "formData", "required": true } ], "responses": { - "200": { - "description": "OK", + "201": { + "description": "Created", "schema": { - "$ref": "#/definitions/codersdk.GitAuthDevice" + "$ref": "#/definitions/codersdk.UploadResponse" } } } - }, - "post": { + } + }, + "/files/{fileID}": { + "get": { "security": [ { "CoderSessionToken": [] } ], - "tags": ["Git"], - "summary": "Post git auth device by ID", - "operationId": "post-git-auth-device-by-id", + "tags": ["Files"], + "summary": "Get file by ID", + "operationId": "get-file-by-id", "parameters": [ { "type": "string", - "format": "string", - "description": "Git Provider ID", - "name": "gitauth", + "format": "uuid", + "description": "File ID", + "name": "fileID", "in": "path", "required": true } ], "responses": { - "204": { - "description": "No Content" + "200": { + "description": "OK" } } } @@ -2430,7 +2430,7 @@ } } }, - "/templateversions/{templateversion}/gitauth": { + "/templateversions/{templateversion}/externalauth": { "get": { "security": [ { @@ -2439,8 +2439,8 @@ ], "produces": ["application/json"], "tags": ["Templates"], - "summary": "Get git auth by template version", - "operationId": "get-git-auth-by-template-version", + "summary": "Get external auth by template version", + "operationId": "get-external-auth-by-template-version", "parameters": [ { "type": "string", @@ -7334,6 +7334,77 @@ "ExperimentDeploymentHealthPage" ] }, + "codersdk.ExternalAuth": { + "type": "object", + "properties": { + "app_install_url": { + "description": "AppInstallURL is the URL to install the app.", + "type": "string" + }, + "app_installable": { + "description": "AppInstallable is true if the request for app installs was successful.", + "type": "boolean" + }, + "authenticated": { + "type": "boolean" + }, + "device": { + "type": "boolean" + }, + "installations": { + "description": "AppInstallations are the installations that the user has access to.", + "type": "array", + "items": { + "$ref": "#/definitions/codersdk.ExternalAuthAppInstallation" + } + }, + "type": { + "type": "string" + }, + "user": { + "description": "User is the user that authenticated with the provider.", + "allOf": [ + { + "$ref": "#/definitions/codersdk.ExternalAuthUser" + } + ] + } + } + }, + "codersdk.ExternalAuthAppInstallation": { + "type": "object", + "properties": { + "account": { + "$ref": "#/definitions/codersdk.ExternalAuthUser" + }, + "configure_url": { + "type": "string" + }, + "id": { + "type": "integer" + } + } + }, + "codersdk.ExternalAuthDevice": { + "type": "object", + "properties": { + "device_code": { + "type": "string" + }, + "expires_in": { + "type": "integer" + }, + "interval": { + "type": "integer" + }, + "user_code": { + "type": "string" + }, + "verification_uri": { + "type": "string" + } + } + }, "codersdk.ExternalAuthProvider": { "type": "string", "enum": [ @@ -7351,6 +7422,23 @@ "ExternalAuthProviderOpenIDConnect" ] }, + "codersdk.ExternalAuthUser": { + "type": "object", + "properties": { + "avatar_url": { + "type": "string" + }, + "login": { + "type": "string" + }, + "name": { + "type": "string" + }, + "profile_url": { + "type": "string" + } + } + }, "codersdk.Feature": { "type": "object", "properties": { @@ -7390,57 +7478,6 @@ } } }, - "codersdk.GitAuth": { - "type": "object", - "properties": { - "app_install_url": { - "description": "AppInstallURL is the URL to install the app.", - "type": "string" - }, - "app_installable": { - "description": "AppInstallable is true if the request for app installs was successful.", - "type": "boolean" - }, - "authenticated": { - "type": "boolean" - }, - "device": { - "type": "boolean" - }, - "installations": { - "description": "AppInstallations are the installations that the user has access to.", - "type": "array", - "items": { - "$ref": "#/definitions/codersdk.GitAuthAppInstallation" - } - }, - "type": { - "type": "string" - }, - "user": { - "description": "User is the user that authenticated with the provider.", - "allOf": [ - { - "$ref": "#/definitions/codersdk.GitAuthUser" - } - ] - } - } - }, - "codersdk.GitAuthAppInstallation": { - "type": "object", - "properties": { - "account": { - "$ref": "#/definitions/codersdk.GitAuthUser" - }, - "configure_url": { - "type": "string" - }, - "id": { - "type": "integer" - } - } - }, "codersdk.GitAuthConfig": { "type": "object", "properties": { @@ -7488,43 +7525,6 @@ } } }, - "codersdk.GitAuthDevice": { - "type": "object", - "properties": { - "device_code": { - "type": "string" - }, - "expires_in": { - "type": "integer" - }, - "interval": { - "type": "integer" - }, - "user_code": { - "type": "string" - }, - "verification_uri": { - "type": "string" - } - } - }, - "codersdk.GitAuthUser": { - "type": "object", - "properties": { - "avatar_url": { - "type": "string" - }, - "login": { - "type": "string" - }, - "name": { - "type": "string" - }, - "profile_url": { - "type": "string" - } - } - }, "codersdk.GitSSHKey": { "type": "object", "properties": { diff --git a/coderd/coderd.go b/coderd/coderd.go index 656204474655e..c02f9a8d3d570 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -37,6 +37,7 @@ import ( // Used for swagger docs. _ "github.com/coder/coder/v2/coderd/apidoc" + "github.com/coder/coder/v2/coderd/externalauth" "cdr.dev/slog" "github.com/coder/coder/v2/buildinfo" @@ -47,7 +48,6 @@ import ( "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/database/dbauthz" "github.com/coder/coder/v2/coderd/database/pubsub" - "github.com/coder/coder/v2/coderd/gitauth" "github.com/coder/coder/v2/coderd/gitsshkey" "github.com/coder/coder/v2/coderd/healthcheck" "github.com/coder/coder/v2/coderd/httpapi" @@ -115,7 +115,7 @@ type Options struct { SSHKeygenAlgorithm gitsshkey.Algorithm Telemetry telemetry.Reporter TracerProvider trace.TracerProvider - ExternalAuthConfigs []*gitauth.Config + ExternalAuthConfigs []*externalauth.Config RealIPConfig *httpmw.RealIPConfig TrialGenerator func(ctx context.Context, email string) error // TLSCertificates is used to mesh DERP servers securely. @@ -546,21 +546,24 @@ func New(options *Options) *API { }) // Register callback handlers for each OAuth2 provider. - r.Route("/gitauth", func(r chi.Router) { - for _, gitAuthConfig := range options.ExternalAuthConfigs { - // We don't need to register a callback handler for device auth. - if gitAuthConfig.DeviceAuth != nil { - continue + // We must support gitauth and externalauth for backwards compatibility. + for _, route := range []string{"gitauth", "externalauth"} { + r.Route("/"+route, func(r chi.Router) { + for _, externalAuthConfig := range options.ExternalAuthConfigs { + // We don't need to register a callback handler for device auth. + if externalAuthConfig.DeviceAuth != nil { + continue + } + r.Route(fmt.Sprintf("/%s/callback", externalAuthConfig.ID), func(r chi.Router) { + r.Use( + apiKeyMiddlewareRedirect, + httpmw.ExtractOAuth2(externalAuthConfig, options.HTTPClient, nil), + ) + r.Get("/", api.externalAuthCallback(externalAuthConfig)) + }) } - r.Route(fmt.Sprintf("/%s/callback", gitAuthConfig.ID), func(r chi.Router) { - r.Use( - apiKeyMiddlewareRedirect, - httpmw.ExtractOAuth2(gitAuthConfig, options.HTTPClient, nil), - ) - r.Get("/", api.gitAuthCallback(gitAuthConfig)) - }) - } - }) + }) + } r.Route("/api/v2", func(r chi.Router) { api.APIHandler = r @@ -613,14 +616,14 @@ func New(options *Options) *API { r.Get("/{fileID}", api.fileByID) r.Post("/", api.postFile) }) - r.Route("/gitauth/{gitauth}", func(r chi.Router) { + r.Route("/externalauth/{externalauth}", func(r chi.Router) { r.Use( apiKeyMiddleware, - httpmw.ExtractGitAuthParam(options.ExternalAuthConfigs), + httpmw.ExtractExternalAuthParam(options.ExternalAuthConfigs), ) - r.Get("/", api.gitAuthByID) - r.Post("/device", api.postGitAuthDeviceByID) - r.Get("/device", api.gitAuthDeviceByID) + r.Get("/", api.externalAuthByID) + r.Post("/device", api.postExternalAuthDeviceByID) + r.Get("/device", api.externalAuthDeviceByID) }) r.Route("/organizations", func(r chi.Router) { r.Use( @@ -686,7 +689,7 @@ func New(options *Options) *API { r.Get("/schema", templateVersionSchemaDeprecated) r.Get("/parameters", templateVersionParametersDeprecated) r.Get("/rich-parameters", api.templateVersionRichParameters) - r.Get("/gitauth", api.templateVersionGitAuth) + r.Get("/externalauth", api.templateVersionExternalAuth) r.Get("/variables", api.templateVersionVariables) r.Get("/resources", api.templateVersionResources) r.Get("/logs", api.templateVersionLogs) diff --git a/coderd/coderdtest/coderdtest.go b/coderd/coderdtest/coderdtest.go index 9700311fe7ff3..6cc0d5132e7fd 100644 --- a/coderd/coderdtest/coderdtest.go +++ b/coderd/coderdtest/coderdtest.go @@ -59,7 +59,7 @@ import ( "github.com/coder/coder/v2/coderd/database/dbauthz" "github.com/coder/coder/v2/coderd/database/dbtestutil" "github.com/coder/coder/v2/coderd/database/pubsub" - "github.com/coder/coder/v2/coderd/gitauth" + "github.com/coder/coder/v2/coderd/externalauth" "github.com/coder/coder/v2/coderd/gitsshkey" "github.com/coder/coder/v2/coderd/healthcheck" "github.com/coder/coder/v2/coderd/httpapi" @@ -105,7 +105,7 @@ type Options struct { AutobuildStats chan<- autobuild.Stats Auditor audit.Auditor TLSCertificates []tls.Certificate - ExternalAuthConfigs []*gitauth.Config + ExternalAuthConfigs []*externalauth.Config TrialGenerator func(context.Context, string) error TemplateScheduleStore schedule.TemplateScheduleStore Coordinator tailnet.Coordinator @@ -899,14 +899,14 @@ func MustWorkspace(t *testing.T, client *codersdk.Client, workspaceID uuid.UUID) return ws } -// RequestGitAuthCallback makes a request with the proper OAuth2 state cookie -// to the git auth callback endpoint. -func RequestGitAuthCallback(t *testing.T, providerID string, client *codersdk.Client) *http.Response { +// RequestExternalAuthCallback makes a request with the proper OAuth2 state cookie +// to the external auth callback endpoint. +func RequestExternalAuthCallback(t *testing.T, providerID string, client *codersdk.Client) *http.Response { client.HTTPClient.CheckRedirect = func(req *http.Request, via []*http.Request) error { return http.ErrUseLastResponse } state := "somestate" - oauthURL, err := client.URL.Parse(fmt.Sprintf("/gitauth/%s/callback?code=asd&state=%s", providerID, state)) + oauthURL, err := client.URL.Parse(fmt.Sprintf("/externalauth/%s/callback?code=asd&state=%s", providerID, state)) require.NoError(t, err) req, err := http.NewRequestWithContext(context.Background(), "GET", oauthURL.String(), nil) require.NoError(t, err) diff --git a/coderd/database/dbauthz/dbauthz.go b/coderd/database/dbauthz/dbauthz.go index bee782a1aacd8..c0a5cfcecf3cf 100644 --- a/coderd/database/dbauthz/dbauthz.go +++ b/coderd/database/dbauthz/dbauthz.go @@ -2486,7 +2486,7 @@ func (q *querier) UpdateTemplateVersionDescriptionByJobID(ctx context.Context, a } func (q *querier) UpdateTemplateVersionExternalAuthProvidersByJobID(ctx context.Context, arg database.UpdateTemplateVersionExternalAuthProvidersByJobIDParams) error { - // An actor is allowed to update the template version git auth providers if they are authorized to update the template. + // An actor is allowed to update the template version external auth providers if they are authorized to update the template. tv, err := q.db.GetTemplateVersionByJobID(ctx, arg.JobID) if err != nil { return err diff --git a/coderd/gitauth.go b/coderd/externalauth.go similarity index 73% rename from coderd/gitauth.go rename to coderd/externalauth.go index 728f4d6613d2c..f668d6b5a980a 100644 --- a/coderd/gitauth.go +++ b/coderd/externalauth.go @@ -10,31 +10,31 @@ import ( "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/database/dbtime" - "github.com/coder/coder/v2/coderd/gitauth" + "github.com/coder/coder/v2/coderd/externalauth" "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/httpmw" "github.com/coder/coder/v2/codersdk" ) -// @Summary Get git auth by ID -// @ID get-git-auth-by-id +// @Summary Get external auth by ID +// @ID get-external-auth-by-id // @Security CoderSessionToken // @Produce json // @Tags Git -// @Param gitauth path string true "Git Provider ID" format(string) -// @Success 200 {object} codersdk.GitAuth -// @Router /gitauth/{gitauth} [get] -func (api *API) gitAuthByID(w http.ResponseWriter, r *http.Request) { - config := httpmw.GitAuthParam(r) +// @Param externalauth path string true "Git Provider ID" format(string) +// @Success 200 {object} codersdk.ExternalAuth +// @Router /externalauth/{externalauth} [get] +func (api *API) externalAuthByID(w http.ResponseWriter, r *http.Request) { + config := httpmw.ExternalAuthParam(r) apiKey := httpmw.APIKey(r) ctx := r.Context() - res := codersdk.GitAuth{ + res := codersdk.ExternalAuth{ Authenticated: false, Device: config.DeviceAuth != nil, AppInstallURL: config.AppInstallURL, Type: config.Type.Pretty(), - AppInstallations: []codersdk.GitAuthAppInstallation{}, + AppInstallations: []codersdk.ExternalAuthAppInstallation{}, } link, err := api.Database.GetExternalAuthLink(ctx, database.GetExternalAuthLinkParams{ @@ -44,7 +44,7 @@ func (api *API) gitAuthByID(w http.ResponseWriter, r *http.Request) { if err != nil { if !errors.Is(err, sql.ErrNoRows) { httpapi.Write(ctx, w, http.StatusInternalServerError, codersdk.Response{ - Message: "Failed to get git auth link.", + Message: "Failed to get external auth link.", Detail: err.Error(), }) return @@ -71,24 +71,24 @@ func (api *API) gitAuthByID(w http.ResponseWriter, r *http.Request) { return } if res.AppInstallations == nil { - res.AppInstallations = []codersdk.GitAuthAppInstallation{} + res.AppInstallations = []codersdk.ExternalAuthAppInstallation{} } httpapi.Write(ctx, w, http.StatusOK, res) } -// @Summary Post git auth device by ID -// @ID post-git-auth-device-by-id +// @Summary Post external auth device by ID +// @ID post-external-auth-device-by-id // @Security CoderSessionToken // @Tags Git -// @Param gitauth path string true "Git Provider ID" format(string) +// @Param externalauth path string true "External Provider ID" format(string) // @Success 204 -// @Router /gitauth/{gitauth}/device [post] -func (api *API) postGitAuthDeviceByID(rw http.ResponseWriter, r *http.Request) { +// @Router /externalauth/{externalauth}/device [post] +func (api *API) postExternalAuthDeviceByID(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() apiKey := httpmw.APIKey(r) - config := httpmw.GitAuthParam(r) + config := httpmw.ExternalAuthParam(r) - var req codersdk.GitAuthDeviceExchange + var req codersdk.ExternalAuthDeviceExchange if !httpapi.Read(ctx, rw, r, &req) { return } @@ -116,7 +116,7 @@ func (api *API) postGitAuthDeviceByID(rw http.ResponseWriter, r *http.Request) { if err != nil { if !errors.Is(err, sql.ErrNoRows) { httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ - Message: "Failed to get git auth link.", + Message: "Failed to get external auth link.", Detail: err.Error(), }) return @@ -133,7 +133,7 @@ func (api *API) postGitAuthDeviceByID(rw http.ResponseWriter, r *http.Request) { }) if err != nil { httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ - Message: "Failed to insert git auth link.", + Message: "Failed to insert external auth link.", Detail: err.Error(), }) return @@ -149,7 +149,7 @@ func (api *API) postGitAuthDeviceByID(rw http.ResponseWriter, r *http.Request) { }) if err != nil { httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ - Message: "Failed to update git auth link.", + Message: "Failed to update external auth link.", Detail: err.Error(), }) return @@ -158,16 +158,16 @@ func (api *API) postGitAuthDeviceByID(rw http.ResponseWriter, r *http.Request) { httpapi.Write(ctx, rw, http.StatusNoContent, nil) } -// @Summary Get git auth device by ID. -// @ID get-git-auth-device-by-id +// @Summary Get external auth device by ID. +// @ID get-external-auth-device-by-id // @Security CoderSessionToken // @Produce json // @Tags Git -// @Param gitauth path string true "Git Provider ID" format(string) -// @Success 200 {object} codersdk.GitAuthDevice -// @Router /gitauth/{gitauth}/device [get] -func (*API) gitAuthDeviceByID(rw http.ResponseWriter, r *http.Request) { - config := httpmw.GitAuthParam(r) +// @Param externalauth path string true "Git Provider ID" format(string) +// @Success 200 {object} codersdk.ExternalAuthDevice +// @Router /externalauth/{externalauth}/device [get] +func (*API) externalAuthDeviceByID(rw http.ResponseWriter, r *http.Request) { + config := httpmw.ExternalAuthParam(r) ctx := r.Context() if config.DeviceAuth == nil { @@ -189,7 +189,7 @@ func (*API) gitAuthDeviceByID(rw http.ResponseWriter, r *http.Request) { httpapi.Write(ctx, rw, http.StatusOK, deviceAuth) } -func (api *API) gitAuthCallback(gitAuthConfig *gitauth.Config) http.HandlerFunc { +func (api *API) externalAuthCallback(externalAuthConfig *externalauth.Config) http.HandlerFunc { return func(rw http.ResponseWriter, r *http.Request) { var ( ctx = r.Context() @@ -198,20 +198,20 @@ func (api *API) gitAuthCallback(gitAuthConfig *gitauth.Config) http.HandlerFunc ) _, err := api.Database.GetExternalAuthLink(ctx, database.GetExternalAuthLinkParams{ - ProviderID: gitAuthConfig.ID, + ProviderID: externalAuthConfig.ID, UserID: apiKey.UserID, }) if err != nil { if !errors.Is(err, sql.ErrNoRows) { httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ - Message: "Failed to get git auth link.", + Message: "Failed to get external auth link.", Detail: err.Error(), }) return } _, err = api.Database.InsertExternalAuthLink(ctx, database.InsertExternalAuthLinkParams{ - ProviderID: gitAuthConfig.ID, + ProviderID: externalAuthConfig.ID, UserID: apiKey.UserID, CreatedAt: dbtime.Now(), UpdatedAt: dbtime.Now(), @@ -221,14 +221,14 @@ func (api *API) gitAuthCallback(gitAuthConfig *gitauth.Config) http.HandlerFunc }) if err != nil { httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ - Message: "Failed to insert git auth link.", + Message: "Failed to insert external auth link.", Detail: err.Error(), }) return } } else { _, err = api.Database.UpdateExternalAuthLink(ctx, database.UpdateExternalAuthLinkParams{ - ProviderID: gitAuthConfig.ID, + ProviderID: externalAuthConfig.ID, UserID: apiKey.UserID, UpdatedAt: dbtime.Now(), OAuthAccessToken: state.Token.AccessToken, @@ -237,7 +237,7 @@ func (api *API) gitAuthCallback(gitAuthConfig *gitauth.Config) http.HandlerFunc }) if err != nil { httpapi.Write(ctx, rw, http.StatusBadRequest, codersdk.Response{ - Message: "Failed to update git auth link.", + Message: "Failed to update external auth link.", Detail: err.Error(), }) return @@ -247,7 +247,7 @@ func (api *API) gitAuthCallback(gitAuthConfig *gitauth.Config) http.HandlerFunc redirect := state.Redirect if redirect == "" { // This is a nicely rendered screen on the frontend - redirect = fmt.Sprintf("/gitauth/%s", gitAuthConfig.ID) + redirect = fmt.Sprintf("/externalauth/%s", externalAuthConfig.ID) } http.Redirect(rw, r, redirect, http.StatusTemporaryRedirect) } diff --git a/coderd/gitauth/config.go b/coderd/externalauth/config.go similarity index 83% rename from coderd/gitauth/config.go rename to coderd/externalauth/config.go index 820721ad1b08d..51ef86635466b 100644 --- a/coderd/gitauth/config.go +++ b/coderd/externalauth/config.go @@ -1,4 +1,4 @@ -package gitauth +package externalauth import ( "context" @@ -65,35 +65,35 @@ type Config struct { // RefreshToken automatically refreshes the token if expired and permitted. // It returns the token and a bool indicating if the token is valid. -func (c *Config) RefreshToken(ctx context.Context, db database.Store, gitAuthLink database.ExternalAuthLink) (database.ExternalAuthLink, bool, error) { +func (c *Config) RefreshToken(ctx context.Context, db database.Store, externalAuthLink database.ExternalAuthLink) (database.ExternalAuthLink, bool, error) { // If the token is expired and refresh is disabled, we prompt // the user to authenticate again. if c.NoRefresh && // If the time is set to 0, then it should never expire. // This is true for github, which has no expiry. - !gitAuthLink.OAuthExpiry.IsZero() && - gitAuthLink.OAuthExpiry.Before(dbtime.Now()) { - return gitAuthLink, false, nil + !externalAuthLink.OAuthExpiry.IsZero() && + externalAuthLink.OAuthExpiry.Before(dbtime.Now()) { + return externalAuthLink, false, nil } // This is additional defensive programming. Because TokenSource is an interface, // we cannot be sure that the implementation will treat an 'IsZero' time // as "not-expired". The default implementation does, but a custom implementation // might not. Removing the refreshToken will guarantee a refresh will fail. - refreshToken := gitAuthLink.OAuthRefreshToken + refreshToken := externalAuthLink.OAuthRefreshToken if c.NoRefresh { refreshToken = "" } token, err := c.TokenSource(ctx, &oauth2.Token{ - AccessToken: gitAuthLink.OAuthAccessToken, + AccessToken: externalAuthLink.OAuthAccessToken, RefreshToken: refreshToken, - Expiry: gitAuthLink.OAuthExpiry, + Expiry: externalAuthLink.OAuthExpiry, }).Token() if err != nil { // Even if the token fails to be obtained, we still return false because // we aren't trying to surface an error, we're just trying to obtain a valid token. - return gitAuthLink, false, nil + return externalAuthLink, false, nil } r := retry.New(50*time.Millisecond, 200*time.Millisecond) // See the comment below why the retry and cancel is required. @@ -102,7 +102,7 @@ func (c *Config) RefreshToken(ctx context.Context, db database.Store, gitAuthLin validate: valid, _, err := c.ValidateToken(ctx, token.AccessToken) if err != nil { - return gitAuthLink, false, xerrors.Errorf("validate git auth token: %w", err) + return externalAuthLink, false, xerrors.Errorf("validate external auth token: %w", err) } if !valid { // A customer using GitHub in Australia reported that validating immediately @@ -116,29 +116,29 @@ validate: goto validate } // The token is no longer valid! - return gitAuthLink, false, nil + return externalAuthLink, false, nil } - if token.AccessToken != gitAuthLink.OAuthAccessToken { + if token.AccessToken != externalAuthLink.OAuthAccessToken { // Update it - gitAuthLink, err = db.UpdateExternalAuthLink(ctx, database.UpdateExternalAuthLinkParams{ + externalAuthLink, err = db.UpdateExternalAuthLink(ctx, database.UpdateExternalAuthLinkParams{ ProviderID: c.ID, - UserID: gitAuthLink.UserID, + UserID: externalAuthLink.UserID, UpdatedAt: dbtime.Now(), OAuthAccessToken: token.AccessToken, OAuthRefreshToken: token.RefreshToken, OAuthExpiry: token.Expiry, }) if err != nil { - return gitAuthLink, false, xerrors.Errorf("update git auth link: %w", err) + return externalAuthLink, false, xerrors.Errorf("update external auth link: %w", err) } } - return gitAuthLink, true, nil + return externalAuthLink, true, nil } // ValidateToken ensures the Git token provided is valid! // The user is optionally returned if the provider supports it. -func (c *Config) ValidateToken(ctx context.Context, token string) (bool, *codersdk.GitAuthUser, error) { +func (c *Config) ValidateToken(ctx context.Context, token string) (bool, *codersdk.ExternalAuthUser, error) { if c.ValidateURL == "" { // Default that the token is valid if no validation URL is provided. return true, nil, nil @@ -167,12 +167,12 @@ func (c *Config) ValidateToken(ctx context.Context, token string) (bool, *coders return false, nil, xerrors.Errorf("status %d: body: %s", res.StatusCode, data) } - var user *codersdk.GitAuthUser + var user *codersdk.ExternalAuthUser if c.Type == codersdk.ExternalAuthProviderGitHub { var ghUser github.User err = json.NewDecoder(res.Body).Decode(&ghUser) if err == nil { - user = &codersdk.GitAuthUser{ + user = &codersdk.ExternalAuthUser{ Login: ghUser.GetLogin(), AvatarURL: ghUser.GetAvatarURL(), ProfileURL: ghUser.GetHTMLURL(), @@ -194,7 +194,7 @@ type AppInstallation struct { // AppInstallations returns a list of app installations for the given token. // If the provider does not support app installations, it returns nil. -func (c *Config) AppInstallations(ctx context.Context, token string) ([]codersdk.GitAuthAppInstallation, bool, error) { +func (c *Config) AppInstallations(ctx context.Context, token string) ([]codersdk.ExternalAuthAppInstallation, bool, error) { if c.AppInstallationsURL == "" { return nil, false, nil } @@ -213,7 +213,7 @@ func (c *Config) AppInstallations(ctx context.Context, token string) ([]codersdk if res.StatusCode != http.StatusOK { return nil, false, nil } - installs := []codersdk.GitAuthAppInstallation{} + installs := []codersdk.ExternalAuthAppInstallation{} if c.Type == codersdk.ExternalAuthProviderGitHub { var ghInstalls struct { Installations []*github.Installation `json:"installations"` @@ -227,10 +227,10 @@ func (c *Config) AppInstallations(ctx context.Context, token string) ([]codersdk if account == nil { continue } - installs = append(installs, codersdk.GitAuthAppInstallation{ + installs = append(installs, codersdk.ExternalAuthAppInstallation{ ID: int(installation.GetID()), ConfigureURL: installation.GetHTMLURL(), - Account: codersdk.GitAuthUser{ + Account: codersdk.ExternalAuthUser{ Login: account.GetLogin(), AvatarURL: account.GetAvatarURL(), ProfileURL: account.GetHTMLURL(), @@ -266,30 +266,30 @@ func ConvertConfig(entries []codersdk.GitAuthConfig, accessURL *url.URL) ([]*Con entry.ID = string(typ) } if valid := httpapi.NameValid(entry.ID); valid != nil { - return nil, xerrors.Errorf("git auth provider %q doesn't have a valid id: %w", entry.ID, valid) + return nil, xerrors.Errorf("external auth provider %q doesn't have a valid id: %w", entry.ID, valid) } _, exists := ids[entry.ID] if exists { if entry.ID == string(typ) { - return nil, xerrors.Errorf("multiple %s git auth providers provided. you must specify a unique id for each", typ) + return nil, xerrors.Errorf("multiple %s external auth providers provided. you must specify a unique id for each", typ) } return nil, xerrors.Errorf("multiple git providers exist with the id %q. specify a unique id for each", entry.ID) } ids[entry.ID] = struct{}{} if entry.ClientID == "" { - return nil, xerrors.Errorf("%q git auth provider: client_id must be provided", entry.ID) + return nil, xerrors.Errorf("%q external auth provider: client_id must be provided", entry.ID) } - authRedirect, err := accessURL.Parse(fmt.Sprintf("/gitauth/%s/callback", entry.ID)) + authRedirect, err := accessURL.Parse(fmt.Sprintf("/externalauth/%s/callback", entry.ID)) if err != nil { - return nil, xerrors.Errorf("parse gitauth callback url: %w", err) + return nil, xerrors.Errorf("parse externalauth callback url: %w", err) } regex := regex[typ] if entry.Regex != "" { regex, err = regexp.Compile(entry.Regex) if err != nil { - return nil, xerrors.Errorf("compile regex for git auth provider %q: %w", entry.ID, entry.Regex) + return nil, xerrors.Errorf("compile regex for external auth provider %q: %w", entry.ID, entry.Regex) } } @@ -339,7 +339,7 @@ func ConvertConfig(entries []codersdk.GitAuthConfig, accessURL *url.URL) ([]*Con entry.DeviceCodeURL = deviceAuthURL[typ] } if entry.DeviceCodeURL == "" { - return nil, xerrors.Errorf("git auth provider %q: device auth url must be provided", entry.ID) + return nil, xerrors.Errorf("external auth provider %q: device auth url must be provided", entry.ID) } cfg.DeviceAuth = &DeviceAuth{ ClientID: entry.ClientID, diff --git a/coderd/gitauth/config_test.go b/coderd/externalauth/config_test.go similarity index 91% rename from coderd/gitauth/config_test.go rename to coderd/externalauth/config_test.go index 3fecc561afd91..c7a529933d87f 100644 --- a/coderd/gitauth/config_test.go +++ b/coderd/externalauth/config_test.go @@ -1,4 +1,4 @@ -package gitauth_test +package externalauth_test import ( "context" @@ -19,7 +19,7 @@ import ( "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/database/dbauthz" "github.com/coder/coder/v2/coderd/database/dbfake" - "github.com/coder/coder/v2/coderd/gitauth" + "github.com/coder/coder/v2/coderd/externalauth" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/testutil" ) @@ -44,7 +44,7 @@ func TestRefreshToken(t *testing.T) { return nil, xerrors.New("should not be called") }), }, - GitConfigOpt: func(cfg *gitauth.Config) { + GitConfigOpt: func(cfg *externalauth.Config) { cfg.NoRefresh = true }, }) @@ -75,7 +75,7 @@ func TestRefreshToken(t *testing.T) { return jwt.MapClaims{}, nil }), }, - GitConfigOpt: func(cfg *gitauth.Config) { + GitConfigOpt: func(cfg *externalauth.Config) { cfg.NoRefresh = true }, }) @@ -92,7 +92,7 @@ func TestRefreshToken(t *testing.T) { t.Run("FalseIfTokenSourceFails", func(t *testing.T) { t.Parallel() - config := &gitauth.Config{ + config := &externalauth.Config{ OAuth2Config: &testutil.OAuth2Config{ TokenSourceFunc: func() (*oauth2.Token, error) { return nil, xerrors.New("failure") @@ -118,7 +118,7 @@ func TestRefreshToken(t *testing.T) { return jwt.MapClaims{}, xerrors.New(staticError) }), }, - GitConfigOpt: func(cfg *gitauth.Config) { + GitConfigOpt: func(cfg *externalauth.Config) { }, }) @@ -143,7 +143,7 @@ func TestRefreshToken(t *testing.T) { return jwt.MapClaims{}, oidctest.StatusError(http.StatusUnauthorized, xerrors.New(staticError)) }), }, - GitConfigOpt: func(cfg *gitauth.Config) { + GitConfigOpt: func(cfg *externalauth.Config) { }, }) @@ -176,7 +176,7 @@ func TestRefreshToken(t *testing.T) { return jwt.MapClaims{}, oidctest.StatusError(http.StatusUnauthorized, xerrors.New(staticError)) }), }, - GitConfigOpt: func(cfg *gitauth.Config) { + GitConfigOpt: func(cfg *externalauth.Config) { cfg.Type = codersdk.ExternalAuthProviderGitHub }, }) @@ -206,7 +206,7 @@ func TestRefreshToken(t *testing.T) { return jwt.MapClaims{}, nil }), }, - GitConfigOpt: func(cfg *gitauth.Config) { + GitConfigOpt: func(cfg *externalauth.Config) { cfg.Type = codersdk.ExternalAuthProviderGitHub }, }) @@ -237,7 +237,7 @@ func TestRefreshToken(t *testing.T) { return jwt.MapClaims{}, nil }), }, - GitConfigOpt: func(cfg *gitauth.Config) { + GitConfigOpt: func(cfg *externalauth.Config) { cfg.Type = codersdk.ExternalAuthProviderGitHub }, DB: db, @@ -268,7 +268,7 @@ func TestConvertYAML(t *testing.T) { for _, tc := range []struct { Name string Input []codersdk.GitAuthConfig - Output []*gitauth.Config + Output []*externalauth.Config Error string }{{ Name: "InvalidType", @@ -298,7 +298,7 @@ func TestConvertYAML(t *testing.T) { }, { Type: string(codersdk.ExternalAuthProviderGitHub), }}, - Error: "multiple github git auth providers provided", + Error: "multiple github external auth providers provided", }, { Name: "InvalidRegex", Input: []codersdk.GitAuthConfig{{ @@ -307,7 +307,7 @@ func TestConvertYAML(t *testing.T) { ClientSecret: "example", Regex: `\K`, }}, - Error: "compile regex for git auth provider", + Error: "compile regex for external auth provider", }, { Name: "NoDeviceURL", Input: []codersdk.GitAuthConfig{{ @@ -321,7 +321,7 @@ func TestConvertYAML(t *testing.T) { tc := tc t.Run(tc.Name, func(t *testing.T) { t.Parallel() - output, err := gitauth.ConvertConfig(tc.Input, &url.URL{}) + output, err := externalauth.ConvertConfig(tc.Input, &url.URL{}) if tc.Error != "" { require.Error(t, err) require.Contains(t, err.Error(), tc.Error) @@ -333,7 +333,7 @@ func TestConvertYAML(t *testing.T) { t.Run("CustomScopesAndEndpoint", func(t *testing.T) { t.Parallel() - config, err := gitauth.ConvertConfig([]codersdk.GitAuthConfig{{ + config, err := externalauth.ConvertConfig([]codersdk.GitAuthConfig{{ Type: string(codersdk.ExternalAuthProviderGitLab), ClientID: "id", ClientSecret: "secret", @@ -342,24 +342,24 @@ func TestConvertYAML(t *testing.T) { Scopes: []string{"read"}, }}, &url.URL{}) require.NoError(t, err) - require.Equal(t, "https://auth.com?client_id=id&redirect_uri=%2Fgitauth%2Fgitlab%2Fcallback&response_type=code&scope=read", config[0].AuthCodeURL("")) + require.Equal(t, "https://auth.com?client_id=id&redirect_uri=%2Fexternalauth%2Fgitlab%2Fcallback&response_type=code&scope=read", config[0].AuthCodeURL("")) }) } type testConfig struct { FakeIDPOpts []oidctest.FakeIDPOpt CoderOIDCConfigOpts []func(cfg *coderd.OIDCConfig) - GitConfigOpt func(cfg *gitauth.Config) + GitConfigOpt func(cfg *externalauth.Config) // If DB is passed in, the link will be inserted into the DB. DB database.Store } -// setupTest will configure a fake IDP and a gitauth.Config for testing. +// setupTest will configure a fake IDP and a externalauth.Config for testing. // The Fake's userinfo endpoint is used for validating tokens. // No http servers are started so use the fake IDP's HTTPClient to make requests. // The returned token is a fully valid token for the IDP. Feel free to manipulate it // to test different scenarios. -func setupOauth2Test(t *testing.T, settings testConfig) (*oidctest.FakeIDP, *gitauth.Config, database.ExternalAuthLink) { +func setupOauth2Test(t *testing.T, settings testConfig) (*oidctest.FakeIDP, *externalauth.Config, database.ExternalAuthLink) { t.Helper() const providerID = "test-idp" @@ -367,7 +367,7 @@ func setupOauth2Test(t *testing.T, settings testConfig) (*oidctest.FakeIDP, *git append([]oidctest.FakeIDPOpt{}, settings.FakeIDPOpts...)..., ) - config := &gitauth.Config{ + config := &externalauth.Config{ OAuth2Config: fake.OIDCConfig(t, nil, settings.CoderOIDCConfigOpts...), ID: providerID, ValidateURL: fake.WellknownConfig().UserInfoURL, diff --git a/coderd/gitauth/oauth.go b/coderd/externalauth/oauth.go similarity index 98% rename from coderd/gitauth/oauth.go rename to coderd/externalauth/oauth.go index 24b0416d203f1..0f679e8fe050e 100644 --- a/coderd/gitauth/oauth.go +++ b/coderd/externalauth/oauth.go @@ -1,4 +1,4 @@ -package gitauth +package externalauth import ( "context" @@ -107,7 +107,7 @@ type DeviceAuth struct { // AuthorizeDevice begins the device authorization flow. // See: https://tools.ietf.org/html/rfc8628#section-3.1 -func (c *DeviceAuth) AuthorizeDevice(ctx context.Context) (*codersdk.GitAuthDevice, error) { +func (c *DeviceAuth) AuthorizeDevice(ctx context.Context) (*codersdk.ExternalAuthDevice, error) { if c.CodeURL == "" { return nil, xerrors.New("oauth2: device code URL not set") } @@ -126,7 +126,7 @@ func (c *DeviceAuth) AuthorizeDevice(ctx context.Context) (*codersdk.GitAuthDevi } defer resp.Body.Close() var r struct { - codersdk.GitAuthDevice + codersdk.ExternalAuthDevice ErrorDescription string `json:"error_description"` } err = json.NewDecoder(resp.Body).Decode(&r) @@ -136,7 +136,7 @@ func (c *DeviceAuth) AuthorizeDevice(ctx context.Context) (*codersdk.GitAuthDevi if r.ErrorDescription != "" { return nil, xerrors.New(r.ErrorDescription) } - return &r.GitAuthDevice, nil + return &r.ExternalAuthDevice, nil } type ExchangeDeviceCodeResponse struct { diff --git a/coderd/gitauth_test.go b/coderd/externalauth_test.go similarity index 84% rename from coderd/gitauth_test.go rename to coderd/externalauth_test.go index 985a823af4b82..b5090b6058804 100644 --- a/coderd/gitauth_test.go +++ b/coderd/externalauth_test.go @@ -18,7 +18,7 @@ import ( "github.com/coder/coder/v2/coderd/coderdtest" "github.com/coder/coder/v2/coderd/database/dbtime" - "github.com/coder/coder/v2/coderd/gitauth" + "github.com/coder/coder/v2/coderd/externalauth" "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/codersdk" "github.com/coder/coder/v2/codersdk/agentsdk" @@ -26,19 +26,19 @@ import ( "github.com/coder/coder/v2/testutil" ) -func TestGitAuthByID(t *testing.T) { +func TestExternalAuthByID(t *testing.T) { t.Parallel() t.Run("Unauthenticated", func(t *testing.T) { t.Parallel() client := coderdtest.New(t, &coderdtest.Options{ - ExternalAuthConfigs: []*gitauth.Config{{ + ExternalAuthConfigs: []*externalauth.Config{{ ID: "test", OAuth2Config: &testutil.OAuth2Config{}, Type: codersdk.ExternalAuthProviderGitHub, }}, }) coderdtest.CreateFirstUser(t, client) - auth, err := client.GitAuthByID(context.Background(), "test") + auth, err := client.ExternalAuthByID(context.Background(), "test") require.NoError(t, err) require.False(t, auth.Authenticated) }) @@ -47,7 +47,7 @@ func TestGitAuthByID(t *testing.T) { // still return that the provider is authenticated. t.Parallel() client := coderdtest.New(t, &coderdtest.Options{ - ExternalAuthConfigs: []*gitauth.Config{{ + ExternalAuthConfigs: []*externalauth.Config{{ ID: "test", OAuth2Config: &testutil.OAuth2Config{}, // AzureDevops doesn't have a user endpoint! @@ -55,9 +55,9 @@ func TestGitAuthByID(t *testing.T) { }}, }) coderdtest.CreateFirstUser(t, client) - resp := coderdtest.RequestGitAuthCallback(t, "test", client) + resp := coderdtest.RequestExternalAuthCallback(t, "test", client) _ = resp.Body.Close() - auth, err := client.GitAuthByID(context.Background(), "test") + auth, err := client.ExternalAuthByID(context.Background(), "test") require.NoError(t, err) require.True(t, auth.Authenticated) }) @@ -71,7 +71,7 @@ func TestGitAuthByID(t *testing.T) { })) defer validateSrv.Close() client := coderdtest.New(t, &coderdtest.Options{ - ExternalAuthConfigs: []*gitauth.Config{{ + ExternalAuthConfigs: []*externalauth.Config{{ ID: "test", ValidateURL: validateSrv.URL, OAuth2Config: &testutil.OAuth2Config{}, @@ -79,9 +79,9 @@ func TestGitAuthByID(t *testing.T) { }}, }) coderdtest.CreateFirstUser(t, client) - resp := coderdtest.RequestGitAuthCallback(t, "test", client) + resp := coderdtest.RequestExternalAuthCallback(t, "test", client) _ = resp.Body.Close() - auth, err := client.GitAuthByID(context.Background(), "test") + auth, err := client.ExternalAuthByID(context.Background(), "test") require.NoError(t, err) require.True(t, auth.Authenticated) require.NotNil(t, auth.User) @@ -111,7 +111,7 @@ func TestGitAuthByID(t *testing.T) { })) defer srv.Close() client := coderdtest.New(t, &coderdtest.Options{ - ExternalAuthConfigs: []*gitauth.Config{{ + ExternalAuthConfigs: []*externalauth.Config{{ ID: "test", ValidateURL: srv.URL + "/user", AppInstallationsURL: srv.URL + "/installs", @@ -120,9 +120,9 @@ func TestGitAuthByID(t *testing.T) { }}, }) coderdtest.CreateFirstUser(t, client) - resp := coderdtest.RequestGitAuthCallback(t, "test", client) + resp := coderdtest.RequestExternalAuthCallback(t, "test", client) _ = resp.Body.Close() - auth, err := client.GitAuthByID(context.Background(), "test") + auth, err := client.ExternalAuthByID(context.Background(), "test") require.NoError(t, err) require.True(t, auth.Authenticated) require.NotNil(t, auth.User) @@ -137,12 +137,12 @@ func TestGitAuthDevice(t *testing.T) { t.Run("NotSupported", func(t *testing.T) { t.Parallel() client := coderdtest.New(t, &coderdtest.Options{ - ExternalAuthConfigs: []*gitauth.Config{{ + ExternalAuthConfigs: []*externalauth.Config{{ ID: "test", }}, }) coderdtest.CreateFirstUser(t, client) - _, err := client.GitAuthDeviceByID(context.Background(), "test") + _, err := client.ExternalAuthDeviceByID(context.Background(), "test") var sdkErr *codersdk.Error require.ErrorAs(t, err, &sdkErr) require.Equal(t, http.StatusBadRequest, sdkErr.StatusCode()) @@ -150,15 +150,15 @@ func TestGitAuthDevice(t *testing.T) { t.Run("FetchCode", func(t *testing.T) { t.Parallel() srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - httpapi.Write(r.Context(), w, http.StatusOK, codersdk.GitAuthDevice{ + httpapi.Write(r.Context(), w, http.StatusOK, codersdk.ExternalAuthDevice{ UserCode: "hey", }) })) defer srv.Close() client := coderdtest.New(t, &coderdtest.Options{ - ExternalAuthConfigs: []*gitauth.Config{{ + ExternalAuthConfigs: []*externalauth.Config{{ ID: "test", - DeviceAuth: &gitauth.DeviceAuth{ + DeviceAuth: &externalauth.DeviceAuth{ ClientID: "test", CodeURL: srv.URL, Scopes: []string{"repo"}, @@ -166,13 +166,13 @@ func TestGitAuthDevice(t *testing.T) { }}, }) coderdtest.CreateFirstUser(t, client) - device, err := client.GitAuthDeviceByID(context.Background(), "test") + device, err := client.ExternalAuthDeviceByID(context.Background(), "test") require.NoError(t, err) require.Equal(t, "hey", device.UserCode) }) t.Run("ExchangeCode", func(t *testing.T) { t.Parallel() - resp := gitauth.ExchangeDeviceCodeResponse{ + resp := externalauth.ExchangeDeviceCodeResponse{ Error: "authorization_pending", } srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { @@ -180,9 +180,9 @@ func TestGitAuthDevice(t *testing.T) { })) defer srv.Close() client := coderdtest.New(t, &coderdtest.Options{ - ExternalAuthConfigs: []*gitauth.Config{{ + ExternalAuthConfigs: []*externalauth.Config{{ ID: "test", - DeviceAuth: &gitauth.DeviceAuth{ + DeviceAuth: &externalauth.DeviceAuth{ ClientID: "test", TokenURL: srv.URL, Scopes: []string{"repo"}, @@ -190,7 +190,7 @@ func TestGitAuthDevice(t *testing.T) { }}, }) coderdtest.CreateFirstUser(t, client) - err := client.GitAuthDeviceExchange(context.Background(), "test", codersdk.GitAuthDeviceExchange{ + err := client.ExternalAuthDeviceExchange(context.Background(), "test", codersdk.ExternalAuthDeviceExchange{ DeviceCode: "hey", }) var sdkErr *codersdk.Error @@ -198,16 +198,16 @@ func TestGitAuthDevice(t *testing.T) { require.Equal(t, http.StatusBadRequest, sdkErr.StatusCode()) require.Equal(t, "authorization_pending", sdkErr.Detail) - resp = gitauth.ExchangeDeviceCodeResponse{ + resp = externalauth.ExchangeDeviceCodeResponse{ AccessToken: "hey", } - err = client.GitAuthDeviceExchange(context.Background(), "test", codersdk.GitAuthDeviceExchange{ + err = client.ExternalAuthDeviceExchange(context.Background(), "test", codersdk.ExternalAuthDeviceExchange{ DeviceCode: "hey", }) require.NoError(t, err) - auth, err := client.GitAuthByID(context.Background(), "test") + auth, err := client.ExternalAuthByID(context.Background(), "test") require.NoError(t, err) require.True(t, auth.Authenticated) }) @@ -220,7 +220,7 @@ func TestGitAuthCallback(t *testing.T) { t.Parallel() client := coderdtest.New(t, &coderdtest.Options{ IncludeProvisionerDaemon: true, - ExternalAuthConfigs: []*gitauth.Config{}, + ExternalAuthConfigs: []*externalauth.Config{}, }) user := coderdtest.CreateFirstUser(t, client) authToken := uuid.NewString() @@ -245,7 +245,7 @@ func TestGitAuthCallback(t *testing.T) { t.Parallel() client := coderdtest.New(t, &coderdtest.Options{ IncludeProvisionerDaemon: true, - ExternalAuthConfigs: []*gitauth.Config{{ + ExternalAuthConfigs: []*externalauth.Config{{ OAuth2Config: &testutil.OAuth2Config{}, ID: "github", Regex: regexp.MustCompile(`github\.com`), @@ -268,27 +268,27 @@ func TestGitAuthCallback(t *testing.T) { agentClient.SetSessionToken(authToken) token, err := agentClient.GitAuth(context.Background(), "github.com/asd/asd", false) require.NoError(t, err) - require.True(t, strings.HasSuffix(token.URL, fmt.Sprintf("/gitauth/%s", "github"))) + require.True(t, strings.HasSuffix(token.URL, fmt.Sprintf("/externalauth/%s", "github"))) }) t.Run("UnauthorizedCallback", func(t *testing.T) { t.Parallel() client := coderdtest.New(t, &coderdtest.Options{ IncludeProvisionerDaemon: true, - ExternalAuthConfigs: []*gitauth.Config{{ + ExternalAuthConfigs: []*externalauth.Config{{ OAuth2Config: &testutil.OAuth2Config{}, ID: "github", Regex: regexp.MustCompile(`github\.com`), Type: codersdk.ExternalAuthProviderGitHub, }}, }) - resp := coderdtest.RequestGitAuthCallback(t, "github", client) + resp := coderdtest.RequestExternalAuthCallback(t, "github", client) require.Equal(t, http.StatusSeeOther, resp.StatusCode) }) t.Run("AuthorizedCallback", func(t *testing.T) { t.Parallel() client := coderdtest.New(t, &coderdtest.Options{ IncludeProvisionerDaemon: true, - ExternalAuthConfigs: []*gitauth.Config{{ + ExternalAuthConfigs: []*externalauth.Config{{ OAuth2Config: &testutil.OAuth2Config{}, ID: "github", Regex: regexp.MustCompile(`github\.com`), @@ -296,14 +296,14 @@ func TestGitAuthCallback(t *testing.T) { }}, }) _ = coderdtest.CreateFirstUser(t, client) - resp := coderdtest.RequestGitAuthCallback(t, "github", client) + resp := coderdtest.RequestExternalAuthCallback(t, "github", client) require.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode) location, err := resp.Location() require.NoError(t, err) - require.Equal(t, "/gitauth/github", location.Path) + require.Equal(t, "/externalauth/github", location.Path) // Callback again to simulate updating the token. - resp = coderdtest.RequestGitAuthCallback(t, "github", client) + resp = coderdtest.RequestExternalAuthCallback(t, "github", client) require.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode) }) t.Run("ValidateURL", func(t *testing.T) { @@ -314,7 +314,7 @@ func TestGitAuthCallback(t *testing.T) { defer srv.Close() client := coderdtest.New(t, &coderdtest.Options{ IncludeProvisionerDaemon: true, - ExternalAuthConfigs: []*gitauth.Config{{ + ExternalAuthConfigs: []*externalauth.Config{{ ValidateURL: srv.URL, OAuth2Config: &testutil.OAuth2Config{}, ID: "github", @@ -337,7 +337,7 @@ func TestGitAuthCallback(t *testing.T) { agentClient := agentsdk.New(client.URL) agentClient.SetSessionToken(authToken) - resp := coderdtest.RequestGitAuthCallback(t, "github", client) + resp := coderdtest.RequestExternalAuthCallback(t, "github", client) require.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode) // If the validation URL says unauthorized, the callback @@ -359,14 +359,14 @@ func TestGitAuthCallback(t *testing.T) { var apiError *codersdk.Error require.ErrorAs(t, err, &apiError) require.Equal(t, http.StatusInternalServerError, apiError.StatusCode()) - require.Equal(t, "validate git auth token: status 403: body: Something went wrong!", apiError.Detail) + require.Equal(t, "validate external auth token: status 403: body: Something went wrong!", apiError.Detail) }) t.Run("ExpiredNoRefresh", func(t *testing.T) { t.Parallel() client := coderdtest.New(t, &coderdtest.Options{ IncludeProvisionerDaemon: true, - ExternalAuthConfigs: []*gitauth.Config{{ + ExternalAuthConfigs: []*externalauth.Config{{ OAuth2Config: &testutil.OAuth2Config{ Token: &oauth2.Token{ AccessToken: "token", @@ -402,7 +402,7 @@ func TestGitAuthCallback(t *testing.T) { // In the configuration, we set our OAuth provider // to return an expired token. Coder consumes this // and stores it. - resp := coderdtest.RequestGitAuthCallback(t, "github", client) + resp := coderdtest.RequestExternalAuthCallback(t, "github", client) require.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode) // Because the token is expired and `NoRefresh` is specified, @@ -416,7 +416,7 @@ func TestGitAuthCallback(t *testing.T) { t.Parallel() client := coderdtest.New(t, &coderdtest.Options{ IncludeProvisionerDaemon: true, - ExternalAuthConfigs: []*gitauth.Config{{ + ExternalAuthConfigs: []*externalauth.Config{{ OAuth2Config: &testutil.OAuth2Config{}, ID: "github", Regex: regexp.MustCompile(`github\.com`), @@ -452,7 +452,7 @@ func TestGitAuthCallback(t *testing.T) { time.Sleep(250 * time.Millisecond) - resp := coderdtest.RequestGitAuthCallback(t, "github", client) + resp := coderdtest.RequestExternalAuthCallback(t, "github", client) require.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode) token = <-tokenChan require.Equal(t, "access_token", token.Username) diff --git a/coderd/gitauth/oauth_test.go b/coderd/gitauth/oauth_test.go deleted file mode 100644 index b85baeb935ed5..0000000000000 --- a/coderd/gitauth/oauth_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package gitauth_test - -import ( - "testing" -) - -func TestOAuthJWTConfig(t *testing.T) { - t.Parallel() -} diff --git a/coderd/httpmw/externalauthparam.go b/coderd/httpmw/externalauthparam.go new file mode 100644 index 0000000000000..91c3e22f22cef --- /dev/null +++ b/coderd/httpmw/externalauthparam.go @@ -0,0 +1,40 @@ +package httpmw + +import ( + "context" + "net/http" + + "github.com/go-chi/chi/v5" + + "github.com/coder/coder/v2/coderd/externalauth" + "github.com/coder/coder/v2/coderd/httpapi" +) + +type externalAuthParamContextKey struct{} + +func ExternalAuthParam(r *http.Request) *externalauth.Config { + config, ok := r.Context().Value(externalAuthParamContextKey{}).(*externalauth.Config) + if !ok { + panic("developer error: external auth param middleware not provided") + } + return config +} + +func ExtractExternalAuthParam(configs []*externalauth.Config) func(next http.Handler) http.Handler { + configByID := make(map[string]*externalauth.Config) + for _, c := range configs { + configByID[c.ID] = c + } + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + config, ok := configByID[chi.URLParam(r, "externalauth")] + if !ok { + httpapi.ResourceNotFound(w) + return + } + + r = r.WithContext(context.WithValue(r.Context(), externalAuthParamContextKey{}, config)) + next.ServeHTTP(w, r) + }) + } +} diff --git a/coderd/httpmw/gitauthparam_test.go b/coderd/httpmw/externalauthparam_test.go similarity index 72% rename from coderd/httpmw/gitauthparam_test.go rename to coderd/httpmw/externalauthparam_test.go index 665e438a23c0c..4081e9f42627b 100644 --- a/coderd/httpmw/gitauthparam_test.go +++ b/coderd/httpmw/externalauthparam_test.go @@ -9,25 +9,25 @@ import ( "github.com/go-chi/chi/v5" "github.com/stretchr/testify/require" - "github.com/coder/coder/v2/coderd/gitauth" + "github.com/coder/coder/v2/coderd/externalauth" "github.com/coder/coder/v2/coderd/httpmw" ) //nolint:bodyclose -func TestGitAuthParam(t *testing.T) { +func TestExternalAuthParam(t *testing.T) { t.Parallel() t.Run("Found", func(t *testing.T) { t.Parallel() routeCtx := chi.NewRouteContext() - routeCtx.URLParams.Add("gitauth", "my-id") + routeCtx.URLParams.Add("externalauth", "my-id") r := httptest.NewRequest(http.MethodGet, "/", nil) r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, routeCtx)) res := httptest.NewRecorder() - httpmw.ExtractGitAuthParam([]*gitauth.Config{{ + httpmw.ExtractExternalAuthParam([]*externalauth.Config{{ ID: "my-id", }})(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - require.Equal(t, "my-id", httpmw.GitAuthParam(r).ID) + require.Equal(t, "my-id", httpmw.ExternalAuthParam(r).ID) w.WriteHeader(http.StatusOK) })).ServeHTTP(res, r) @@ -37,12 +37,12 @@ func TestGitAuthParam(t *testing.T) { t.Run("NotFound", func(t *testing.T) { t.Parallel() routeCtx := chi.NewRouteContext() - routeCtx.URLParams.Add("gitauth", "my-id") + routeCtx.URLParams.Add("externalauth", "my-id") r := httptest.NewRequest(http.MethodGet, "/", nil) r = r.WithContext(context.WithValue(r.Context(), chi.RouteCtxKey, routeCtx)) res := httptest.NewRecorder() - httpmw.ExtractGitAuthParam([]*gitauth.Config{})(nil).ServeHTTP(res, r) + httpmw.ExtractExternalAuthParam([]*externalauth.Config{})(nil).ServeHTTP(res, r) require.Equal(t, http.StatusNotFound, res.Result().StatusCode) }) diff --git a/coderd/httpmw/gitauthparam.go b/coderd/httpmw/gitauthparam.go deleted file mode 100644 index 240732275bd83..0000000000000 --- a/coderd/httpmw/gitauthparam.go +++ /dev/null @@ -1,40 +0,0 @@ -package httpmw - -import ( - "context" - "net/http" - - "github.com/go-chi/chi/v5" - - "github.com/coder/coder/v2/coderd/gitauth" - "github.com/coder/coder/v2/coderd/httpapi" -) - -type gitAuthParamContextKey struct{} - -func GitAuthParam(r *http.Request) *gitauth.Config { - config, ok := r.Context().Value(gitAuthParamContextKey{}).(*gitauth.Config) - if !ok { - panic("developer error: gitauth param middleware not provided") - } - return config -} - -func ExtractGitAuthParam(configs []*gitauth.Config) func(next http.Handler) http.Handler { - configByID := make(map[string]*gitauth.Config) - for _, c := range configs { - configByID[c.ID] = c - } - return func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - config, ok := configByID[chi.URLParam(r, "gitauth")] - if !ok { - httpapi.ResourceNotFound(w) - return - } - - r = r.WithContext(context.WithValue(r.Context(), gitAuthParamContextKey{}, config)) - next.ServeHTTP(w, r) - }) - } -} diff --git a/coderd/httpmw/patternmatcher/routepatterns_test.go b/coderd/httpmw/patternmatcher/routepatterns_test.go index dc7f779136360..880fa88e711a3 100644 --- a/coderd/httpmw/patternmatcher/routepatterns_test.go +++ b/coderd/httpmw/patternmatcher/routepatterns_test.go @@ -65,9 +65,9 @@ func Test_RoutePatterns(t *testing.T) { "/api/**", "/@*/*/apps/**", "/%40*/*/apps/**", - "/gitauth/*/callback", + "/externalauth/*/callback", }, - output: "^(/api/?|/api/.+/?|/@[^/]+/[^/]+/apps/.+/?|/%40[^/]+/[^/]+/apps/.+/?|/gitauth/[^/]+/callback/?)$", + output: "^(/api/?|/api/.+/?|/@[^/]+/[^/]+/apps/.+/?|/%40[^/]+/[^/]+/apps/.+/?|/externalauth/[^/]+/callback/?)$", }, { name: "Slash", diff --git a/coderd/provisionerdserver/provisionerdserver.go b/coderd/provisionerdserver/provisionerdserver.go index 2c063660db97b..bbda529af6775 100644 --- a/coderd/provisionerdserver/provisionerdserver.go +++ b/coderd/provisionerdserver/provisionerdserver.go @@ -31,7 +31,7 @@ import ( "github.com/coder/coder/v2/coderd/database/dbauthz" "github.com/coder/coder/v2/coderd/database/dbtime" "github.com/coder/coder/v2/coderd/database/pubsub" - "github.com/coder/coder/v2/coderd/gitauth" + "github.com/coder/coder/v2/coderd/externalauth" "github.com/coder/coder/v2/coderd/httpmw" "github.com/coder/coder/v2/coderd/schedule" "github.com/coder/coder/v2/coderd/telemetry" @@ -49,7 +49,7 @@ const DefaultAcquireJobLongPollDur = time.Second * 5 type Options struct { OIDCConfig httpmw.OAuth2Config - ExternalAuthConfigs []*gitauth.Config + ExternalAuthConfigs []*externalauth.Config // TimeNowFn is only used in tests TimeNowFn func() time.Time @@ -62,7 +62,7 @@ type server struct { ID uuid.UUID Logger slog.Logger Provisioners []database.ProvisionerType - ExternalAuthConfigs []*gitauth.Config + ExternalAuthConfigs []*externalauth.Config Tags Tags Database database.Store Pubsub pubsub.Pubsub @@ -416,7 +416,7 @@ func (s *server) acquireProtoJob(ctx context.Context, job database.ProvisionerJo if err != nil { return nil, failJob(fmt.Sprintf("acquire external auth link: %s", err)) } - var config *gitauth.Config + var config *externalauth.Config for _, c := range s.ExternalAuthConfigs { if c.ID != p { continue diff --git a/coderd/provisionerdserver/provisionerdserver_test.go b/coderd/provisionerdserver/provisionerdserver_test.go index 7b380b6426974..4b9ccd4e9abcd 100644 --- a/coderd/provisionerdserver/provisionerdserver_test.go +++ b/coderd/provisionerdserver/provisionerdserver_test.go @@ -31,7 +31,7 @@ import ( "github.com/coder/coder/v2/coderd/database/dbgen" "github.com/coder/coder/v2/coderd/database/dbtime" "github.com/coder/coder/v2/coderd/database/pubsub" - "github.com/coder/coder/v2/coderd/gitauth" + "github.com/coder/coder/v2/coderd/externalauth" "github.com/coder/coder/v2/coderd/provisionerdserver" "github.com/coder/coder/v2/coderd/schedule" "github.com/coder/coder/v2/coderd/schedule/cron" @@ -143,7 +143,7 @@ func TestAcquireJob(t *testing.T) { gitAuthProvider := "github" srv, db, ps := setup(t, false, &overrides{ deploymentValues: dv, - externalAuthConfigs: []*gitauth.Config{{ + externalAuthConfigs: []*externalauth.Config{{ ID: gitAuthProvider, OAuth2Config: &testutil.OAuth2Config{}, }}, @@ -941,7 +941,7 @@ func TestCompleteJob(t *testing.T) { srvID := uuid.New() srv, db, _ := setup(t, false, &overrides{ id: &srvID, - externalAuthConfigs: []*gitauth.Config{{ + externalAuthConfigs: []*externalauth.Config{{ ID: "github", }}, }) @@ -1675,7 +1675,7 @@ func TestInsertWorkspaceResource(t *testing.T) { type overrides struct { deploymentValues *codersdk.DeploymentValues - externalAuthConfigs []*gitauth.Config + externalAuthConfigs []*externalauth.Config id *uuid.UUID templateScheduleStore *atomic.Pointer[schedule.TemplateScheduleStore] userQuietHoursScheduleStore *atomic.Pointer[schedule.UserQuietHoursScheduleStore] @@ -1691,7 +1691,7 @@ func setup(t *testing.T, ignoreLogErrors bool, ov *overrides) (proto.DRPCProvisi db := dbfake.New() ps := pubsub.NewInMemory() deploymentValues := &codersdk.DeploymentValues{} - var externalAuthConfigs []*gitauth.Config + var externalAuthConfigs []*externalauth.Config srvID := uuid.New() tss := testTemplateScheduleStore() uqhss := testUserQuietHoursScheduleStore() diff --git a/coderd/templateversions.go b/coderd/templateversions.go index a797d1697952f..cbc9bb0605f0d 100644 --- a/coderd/templateversions.go +++ b/coderd/templateversions.go @@ -22,7 +22,7 @@ import ( "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/database/dbtime" "github.com/coder/coder/v2/coderd/database/provisionerjobs" - "github.com/coder/coder/v2/coderd/gitauth" + "github.com/coder/coder/v2/coderd/externalauth" "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/httpmw" "github.com/coder/coder/v2/coderd/parameter" @@ -273,15 +273,15 @@ func (api *API) templateVersionRichParameters(rw http.ResponseWriter, r *http.Re httpapi.Write(ctx, rw, http.StatusOK, templateVersionParameters) } -// @Summary Get git auth by template version -// @ID get-git-auth-by-template-version +// @Summary Get external auth by template version +// @ID get-external-auth-by-template-version // @Security CoderSessionToken // @Produce json // @Tags Templates // @Param templateversion path string true "Template version ID" format(uuid) // @Success 200 {array} codersdk.TemplateVersionExternalAuth -// @Router /templateversions/{templateversion}/gitauth [get] -func (api *API) templateVersionGitAuth(rw http.ResponseWriter, r *http.Request) { +// @Router /templateversions/{templateversion}/externalauth [get] +func (api *API) templateVersionExternalAuth(rw http.ResponseWriter, r *http.Request) { ctx := r.Context() var ( apiKey = httpmw.APIKey(r) @@ -291,7 +291,7 @@ func (api *API) templateVersionGitAuth(rw http.ResponseWriter, r *http.Request) rawProviders := templateVersion.ExternalAuthProviders providers := make([]codersdk.TemplateVersionExternalAuth, 0) for _, rawProvider := range rawProviders { - var config *gitauth.Config + var config *externalauth.Config for _, provider := range api.ExternalAuthConfigs { if provider.ID == rawProvider { config = provider @@ -307,7 +307,7 @@ func (api *API) templateVersionGitAuth(rw http.ResponseWriter, r *http.Request) } // This is the URL that will redirect the user with a state token. - redirectURL, err := api.AccessURL.Parse(fmt.Sprintf("/gitauth/%s", config.ID)) + redirectURL, err := api.AccessURL.Parse(fmt.Sprintf("/externalauth/%s", config.ID)) if err != nil { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ Message: "Failed to parse access URL.", @@ -333,7 +333,7 @@ func (api *API) templateVersionGitAuth(rw http.ResponseWriter, r *http.Request) } if err != nil { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ - Message: "Internal error fetching git auth link.", + Message: "Internal error fetching external auth link.", Detail: err.Error(), }) return @@ -342,7 +342,7 @@ func (api *API) templateVersionGitAuth(rw http.ResponseWriter, r *http.Request) _, updated, err := config.RefreshToken(ctx, api.Database, authLink) if err != nil { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ - Message: "Failed to refresh git auth token.", + Message: "Failed to refresh external auth token.", Detail: err.Error(), }) return diff --git a/coderd/templateversions_test.go b/coderd/templateversions_test.go index 1218356703cc0..7f9c7f54dc203 100644 --- a/coderd/templateversions_test.go +++ b/coderd/templateversions_test.go @@ -16,7 +16,7 @@ import ( "github.com/coder/coder/v2/coderd/audit" "github.com/coder/coder/v2/coderd/coderdtest" "github.com/coder/coder/v2/coderd/database" - "github.com/coder/coder/v2/coderd/gitauth" + "github.com/coder/coder/v2/coderd/externalauth" "github.com/coder/coder/v2/coderd/provisionerdserver" "github.com/coder/coder/v2/coderd/rbac" "github.com/coder/coder/v2/codersdk" @@ -319,7 +319,7 @@ func TestPatchCancelTemplateVersion(t *testing.T) { }) } -func TestTemplateVersionsGitAuth(t *testing.T) { +func TestTemplateVersionsExternalAuth(t *testing.T) { t.Parallel() t.Run("Empty", func(t *testing.T) { t.Parallel() @@ -338,7 +338,7 @@ func TestTemplateVersionsGitAuth(t *testing.T) { t.Parallel() client := coderdtest.New(t, &coderdtest.Options{ IncludeProvisionerDaemon: true, - ExternalAuthConfigs: []*gitauth.Config{{ + ExternalAuthConfigs: []*externalauth.Config{{ OAuth2Config: &testutil.OAuth2Config{}, ID: "github", Regex: regexp.MustCompile(`github\.com`), @@ -351,7 +351,7 @@ func TestTemplateVersionsGitAuth(t *testing.T) { ProvisionPlan: []*proto.Response{{ Type: &proto.Response_Plan{ Plan: &proto.PlanComplete{ - GitAuthProviders: []string{"github"}, + ExternalAuthProviders: []string{"github"}, }, }, }}, @@ -368,7 +368,7 @@ func TestTemplateVersionsGitAuth(t *testing.T) { require.False(t, providers[0].Authenticated) // Perform the Git auth callback to authenticate the user... - resp := coderdtest.RequestGitAuthCallback(t, "github", client) + resp := coderdtest.RequestExternalAuthCallback(t, "github", client) _ = resp.Body.Close() require.Equal(t, http.StatusTemporaryRedirect, resp.StatusCode) diff --git a/coderd/tracing/httpmw.go b/coderd/tracing/httpmw.go index 653a74386245b..994c16f41aed6 100644 --- a/coderd/tracing/httpmw.go +++ b/coderd/tracing/httpmw.go @@ -26,7 +26,7 @@ func Middleware(tracerProvider trace.TracerProvider) func(http.Handler) http.Han "/api/**", "/@*/*/apps/**", "/%40*/*/apps/**", - "/gitauth/*/callback", + "/externalauth/*/callback", }.MustCompile() var tracer trace.Tracer diff --git a/coderd/tracing/httpmw_test.go b/coderd/tracing/httpmw_test.go index e866acd513ec3..ca759513ec6d0 100644 --- a/coderd/tracing/httpmw_test.go +++ b/coderd/tracing/httpmw_test.go @@ -59,7 +59,7 @@ func Test_Middleware(t *testing.T) { {"/%40hi/hi/apps/hi", true}, {"/%40hi/hi/apps/hi/hi", true}, {"/%40hi/hi/apps/hi/hi", true}, - {"/gitauth/hi/callback", true}, + {"/externalauth/hi/callback", true}, // Other routes that should not be collected. {"/index.html", false}, diff --git a/coderd/workspaceagents.go b/coderd/workspaceagents.go index cef39105819c8..b7b258b4f8a96 100644 --- a/coderd/workspaceagents.go +++ b/coderd/workspaceagents.go @@ -34,7 +34,7 @@ import ( "github.com/coder/coder/v2/coderd/database" "github.com/coder/coder/v2/coderd/database/dbauthz" "github.com/coder/coder/v2/coderd/database/dbtime" - "github.com/coder/coder/v2/coderd/gitauth" + "github.com/coder/coder/v2/coderd/externalauth" "github.com/coder/coder/v2/coderd/httpapi" "github.com/coder/coder/v2/coderd/httpmw" "github.com/coder/coder/v2/coderd/rbac" @@ -2178,25 +2178,25 @@ func (api *API) workspaceAgentsGitAuth(rw http.ResponseWriter, r *http.Request) // new token to be issued! listen := r.URL.Query().Has("listen") - var gitAuthConfig *gitauth.Config + var externalAuthConfig *externalauth.Config for _, gitAuth := range api.ExternalAuthConfigs { matches := gitAuth.Regex.MatchString(gitURL) if !matches { continue } - gitAuthConfig = gitAuth + externalAuthConfig = gitAuth } - if gitAuthConfig == nil { - detail := "No git providers are configured." + if externalAuthConfig == nil { + detail := "No external auth providers are configured." if len(api.ExternalAuthConfigs) > 0 { regexURLs := make([]string, 0, len(api.ExternalAuthConfigs)) - for _, gitAuth := range api.ExternalAuthConfigs { - regexURLs = append(regexURLs, fmt.Sprintf("%s=%q", gitAuth.ID, gitAuth.Regex.String())) + for _, extAuth := range api.ExternalAuthConfigs { + regexURLs = append(regexURLs, fmt.Sprintf("%s=%q", extAuth.ID, extAuth.Regex.String())) } - detail = fmt.Sprintf("The configured git provider have regex filters that do not match the git url. Provider url regexs: %s", strings.Join(regexURLs, ",")) + detail = fmt.Sprintf("The configured external auth provider have regex filters that do not match the git url. Provider url regexs: %s", strings.Join(regexURLs, ",")) } httpapi.Write(ctx, rw, http.StatusNotFound, codersdk.Response{ - Message: fmt.Sprintf("No matching git provider found in Coder for the url %q.", gitURL), + Message: fmt.Sprintf("No matching external auth provider found in Coder for the url %q.", gitURL), Detail: detail, }) return @@ -2239,8 +2239,8 @@ func (api *API) workspaceAgentsGitAuth(rw http.ResponseWriter, r *http.Request) return case <-ticker.C: } - gitAuthLink, err := api.Database.GetExternalAuthLink(ctx, database.GetExternalAuthLinkParams{ - ProviderID: gitAuthConfig.ID, + externalAuthLink, err := api.Database.GetExternalAuthLink(ctx, database.GetExternalAuthLinkParams{ + ProviderID: externalAuthConfig.ID, UserID: workspace.OwnerID, }) if err != nil { @@ -2248,7 +2248,7 @@ func (api *API) workspaceAgentsGitAuth(rw http.ResponseWriter, r *http.Request) continue } httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ - Message: "Failed to get git auth link.", + Message: "Failed to get external auth link.", Detail: err.Error(), }) return @@ -2258,27 +2258,27 @@ func (api *API) workspaceAgentsGitAuth(rw http.ResponseWriter, r *http.Request) // to expire. // See // https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-a-user-access-token-for-a-github-app. - if gitAuthLink.OAuthExpiry.Before(dbtime.Now()) && !gitAuthLink.OAuthExpiry.IsZero() { + if externalAuthLink.OAuthExpiry.Before(dbtime.Now()) && !externalAuthLink.OAuthExpiry.IsZero() { continue } - valid, _, err := gitAuthConfig.ValidateToken(ctx, gitAuthLink.OAuthAccessToken) + valid, _, err := externalAuthConfig.ValidateToken(ctx, externalAuthLink.OAuthAccessToken) if err != nil { - api.Logger.Warn(ctx, "failed to validate git auth token", + api.Logger.Warn(ctx, "failed to validate external auth token", slog.F("workspace_owner_id", workspace.OwnerID.String()), - slog.F("validate_url", gitAuthConfig.ValidateURL), + slog.F("validate_url", externalAuthConfig.ValidateURL), slog.Error(err), ) } if !valid { continue } - httpapi.Write(ctx, rw, http.StatusOK, formatGitAuthAccessToken(gitAuthConfig.Type, gitAuthLink.OAuthAccessToken)) + httpapi.Write(ctx, rw, http.StatusOK, formatGitAuthAccessToken(externalAuthConfig.Type, externalAuthLink.OAuthAccessToken)) return } } // This is the URL that will redirect the user with a state token. - redirectURL, err := api.AccessURL.Parse(fmt.Sprintf("/gitauth/%s", gitAuthConfig.ID)) + redirectURL, err := api.AccessURL.Parse(fmt.Sprintf("/externalauth/%s", externalAuthConfig.ID)) if err != nil { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ Message: "Failed to parse access URL.", @@ -2287,14 +2287,14 @@ func (api *API) workspaceAgentsGitAuth(rw http.ResponseWriter, r *http.Request) return } - gitAuthLink, err := api.Database.GetExternalAuthLink(ctx, database.GetExternalAuthLinkParams{ - ProviderID: gitAuthConfig.ID, + externalAuthLink, err := api.Database.GetExternalAuthLink(ctx, database.GetExternalAuthLinkParams{ + ProviderID: externalAuthConfig.ID, UserID: workspace.OwnerID, }) if err != nil { if !errors.Is(err, sql.ErrNoRows) { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ - Message: "Failed to get git auth link.", + Message: "Failed to get external auth link.", Detail: err.Error(), }) return @@ -2306,10 +2306,10 @@ func (api *API) workspaceAgentsGitAuth(rw http.ResponseWriter, r *http.Request) return } - gitAuthLink, updated, err := gitAuthConfig.RefreshToken(ctx, api.Database, gitAuthLink) + externalAuthLink, updated, err := externalAuthConfig.RefreshToken(ctx, api.Database, externalAuthLink) if err != nil { httpapi.Write(ctx, rw, http.StatusInternalServerError, codersdk.Response{ - Message: "Failed to refresh git auth token.", + Message: "Failed to refresh external auth token.", Detail: err.Error(), }) return @@ -2320,7 +2320,7 @@ func (api *API) workspaceAgentsGitAuth(rw http.ResponseWriter, r *http.Request) }) return } - httpapi.Write(ctx, rw, http.StatusOK, formatGitAuthAccessToken(gitAuthConfig.Type, gitAuthLink.OAuthAccessToken)) + httpapi.Write(ctx, rw, http.StatusOK, formatGitAuthAccessToken(externalAuthConfig.Type, externalAuthLink.OAuthAccessToken)) } // Provider types have different username/password formats. diff --git a/codersdk/gitauth.go b/codersdk/externalauth.go similarity index 51% rename from codersdk/gitauth.go rename to codersdk/externalauth.go index c8259771207b8..5350dc3a6b93d 100644 --- a/codersdk/gitauth.go +++ b/codersdk/externalauth.go @@ -7,37 +7,37 @@ import ( "net/http" ) -type GitAuth struct { +type ExternalAuth struct { Authenticated bool `json:"authenticated"` Device bool `json:"device"` Type string `json:"type"` // User is the user that authenticated with the provider. - User *GitAuthUser `json:"user"` + User *ExternalAuthUser `json:"user"` // AppInstallable is true if the request for app installs was successful. AppInstallable bool `json:"app_installable"` // AppInstallations are the installations that the user has access to. - AppInstallations []GitAuthAppInstallation `json:"installations"` + AppInstallations []ExternalAuthAppInstallation `json:"installations"` // AppInstallURL is the URL to install the app. AppInstallURL string `json:"app_install_url"` } -type GitAuthAppInstallation struct { - ID int `json:"id"` - Account GitAuthUser `json:"account"` - ConfigureURL string `json:"configure_url"` +type ExternalAuthAppInstallation struct { + ID int `json:"id"` + Account ExternalAuthUser `json:"account"` + ConfigureURL string `json:"configure_url"` } -type GitAuthUser struct { +type ExternalAuthUser struct { Login string `json:"login"` AvatarURL string `json:"avatar_url"` ProfileURL string `json:"profile_url"` Name string `json:"name"` } -// GitAuthDevice is the response from the device authorization endpoint. +// ExternalAuthDevice is the response from the device authorization endpoint. // See: https://tools.ietf.org/html/rfc8628#section-3.2 -type GitAuthDevice struct { +type ExternalAuthDevice struct { DeviceCode string `json:"device_code"` UserCode string `json:"user_code"` VerificationURI string `json:"verification_uri"` @@ -45,26 +45,26 @@ type GitAuthDevice struct { Interval int `json:"interval"` } -type GitAuthDeviceExchange struct { +type ExternalAuthDeviceExchange struct { DeviceCode string `json:"device_code"` } -func (c *Client) GitAuthDeviceByID(ctx context.Context, provider string) (GitAuthDevice, error) { - res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/gitauth/%s/device", provider), nil) +func (c *Client) ExternalAuthDeviceByID(ctx context.Context, provider string) (ExternalAuthDevice, error) { + res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/externalauth/%s/device", provider), nil) if err != nil { - return GitAuthDevice{}, err + return ExternalAuthDevice{}, err } defer res.Body.Close() if res.StatusCode != http.StatusOK { - return GitAuthDevice{}, ReadBodyAsError(res) + return ExternalAuthDevice{}, ReadBodyAsError(res) } - var gitauth GitAuthDevice - return gitauth, json.NewDecoder(res.Body).Decode(&gitauth) + var extAuth ExternalAuthDevice + return extAuth, json.NewDecoder(res.Body).Decode(&extAuth) } -// ExchangeGitAuth exchanges a device code for a git auth token. -func (c *Client) GitAuthDeviceExchange(ctx context.Context, provider string, req GitAuthDeviceExchange) error { - res, err := c.Request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/gitauth/%s/device", provider), req) +// ExchangeGitAuth exchanges a device code for an external auth token. +func (c *Client) ExternalAuthDeviceExchange(ctx context.Context, provider string, req ExternalAuthDeviceExchange) error { + res, err := c.Request(ctx, http.MethodPost, fmt.Sprintf("/api/v2/externalauth/%s/device", provider), req) if err != nil { return err } @@ -75,16 +75,16 @@ func (c *Client) GitAuthDeviceExchange(ctx context.Context, provider string, req return nil } -// GitAuthByID returns the git auth for the given provider by ID. -func (c *Client) GitAuthByID(ctx context.Context, provider string) (GitAuth, error) { - res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/gitauth/%s", provider), nil) +// ExternalAuthByID returns the external auth for the given provider by ID. +func (c *Client) ExternalAuthByID(ctx context.Context, provider string) (ExternalAuth, error) { + res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/externalauth/%s", provider), nil) if err != nil { - return GitAuth{}, err + return ExternalAuth{}, err } defer res.Body.Close() if res.StatusCode != http.StatusOK { - return GitAuth{}, ReadBodyAsError(res) + return ExternalAuth{}, ReadBodyAsError(res) } - var gitauth GitAuth - return gitauth, json.NewDecoder(res.Body).Decode(&gitauth) + var extAuth ExternalAuth + return extAuth, json.NewDecoder(res.Body).Decode(&extAuth) } diff --git a/codersdk/templateversions.go b/codersdk/templateversions.go index 3e3a1363bccf2..fb1f0b21febf0 100644 --- a/codersdk/templateversions.go +++ b/codersdk/templateversions.go @@ -134,7 +134,7 @@ func (c *Client) TemplateVersionRichParameters(ctx context.Context, version uuid // TemplateVersionExternalAuth returns authentication providers for the requested template version. func (c *Client) TemplateVersionExternalAuth(ctx context.Context, version uuid.UUID) ([]TemplateVersionExternalAuth, error) { - res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templateversions/%s/gitauth", version), nil) + res, err := c.Request(ctx, http.MethodGet, fmt.Sprintf("/api/v2/templateversions/%s/externalauth", version), nil) if err != nil { return nil, err } diff --git a/docs/api/git.md b/docs/api/git.md index 0f55fdfba909a..bcc88890069f5 100644 --- a/docs/api/git.md +++ b/docs/api/git.md @@ -1,23 +1,23 @@ # Git -## Get git auth by ID +## Get external auth by ID ### Code samples ```shell # Example request using curl -curl -X GET http://coder-server:8080/api/v2/gitauth/{gitauth} \ +curl -X GET http://coder-server:8080/api/v2/externalauth/{externalauth} \ -H 'Accept: application/json' \ -H 'Coder-Session-Token: API_KEY' ``` -`GET /gitauth/{gitauth}` +`GET /externalauth/{externalauth}` ### Parameters -| Name | In | Type | Required | Description | -| --------- | ---- | -------------- | -------- | --------------- | -| `gitauth` | path | string(string) | true | Git Provider ID | +| Name | In | Type | Required | Description | +| -------------- | ---- | -------------- | -------- | --------------- | +| `externalauth` | path | string(string) | true | Git Provider ID | ### Example responses @@ -53,30 +53,30 @@ curl -X GET http://coder-server:8080/api/v2/gitauth/{gitauth} \ ### Responses -| Status | Meaning | Description | Schema | -| ------ | ------------------------------------------------------- | ----------- | ---------------------------------------------- | -| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.GitAuth](schemas.md#codersdkgitauth) | +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------- | ----------- | -------------------------------------------------------- | +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.ExternalAuth](schemas.md#codersdkexternalauth) | To perform this operation, you must be authenticated. [Learn more](authentication.md). -## Get git auth device by ID. +## Get external auth device by ID. ### Code samples ```shell # Example request using curl -curl -X GET http://coder-server:8080/api/v2/gitauth/{gitauth}/device \ +curl -X GET http://coder-server:8080/api/v2/externalauth/{externalauth}/device \ -H 'Accept: application/json' \ -H 'Coder-Session-Token: API_KEY' ``` -`GET /gitauth/{gitauth}/device` +`GET /externalauth/{externalauth}/device` ### Parameters -| Name | In | Type | Required | Description | -| --------- | ---- | -------------- | -------- | --------------- | -| `gitauth` | path | string(string) | true | Git Provider ID | +| Name | In | Type | Required | Description | +| -------------- | ---- | -------------- | -------- | --------------- | +| `externalauth` | path | string(string) | true | Git Provider ID | ### Example responses @@ -94,29 +94,29 @@ curl -X GET http://coder-server:8080/api/v2/gitauth/{gitauth}/device \ ### Responses -| Status | Meaning | Description | Schema | -| ------ | ------------------------------------------------------- | ----------- | ---------------------------------------------------------- | -| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.GitAuthDevice](schemas.md#codersdkgitauthdevice) | +| Status | Meaning | Description | Schema | +| ------ | ------------------------------------------------------- | ----------- | -------------------------------------------------------------------- | +| 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | [codersdk.ExternalAuthDevice](schemas.md#codersdkexternalauthdevice) | To perform this operation, you must be authenticated. [Learn more](authentication.md). -## Post git auth device by ID +## Post external auth device by ID ### Code samples ```shell # Example request using curl -curl -X POST http://coder-server:8080/api/v2/gitauth/{gitauth}/device \ +curl -X POST http://coder-server:8080/api/v2/externalauth/{externalauth}/device \ -H 'Coder-Session-Token: API_KEY' ``` -`POST /gitauth/{gitauth}/device` +`POST /externalauth/{externalauth}/device` ### Parameters -| Name | In | Type | Required | Description | -| --------- | ---- | -------------- | -------- | --------------- | -| `gitauth` | path | string(string) | true | Git Provider ID | +| Name | In | Type | Required | Description | +| -------------- | ---- | -------------- | -------- | -------------------- | +| `externalauth` | path | string(string) | true | External Provider ID | ### Responses diff --git a/docs/api/schemas.md b/docs/api/schemas.md index 4e4a1dede69b2..00b61e6202351 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -2752,6 +2752,93 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in | `template_autostop_requirement` | | `deployment_health_page` | +## codersdk.ExternalAuth + +```json +{ + "app_install_url": "string", + "app_installable": true, + "authenticated": true, + "device": true, + "installations": [ + { + "account": { + "avatar_url": "string", + "login": "string", + "name": "string", + "profile_url": "string" + }, + "configure_url": "string", + "id": 0 + } + ], + "type": "string", + "user": { + "avatar_url": "string", + "login": "string", + "name": "string", + "profile_url": "string" + } +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| ----------------- | ------------------------------------------------------------------------------------- | -------- | ------------ | ----------------------------------------------------------------------- | +| `app_install_url` | string | false | | App install URL is the URL to install the app. | +| `app_installable` | boolean | false | | App installable is true if the request for app installs was successful. | +| `authenticated` | boolean | false | | | +| `device` | boolean | false | | | +| `installations` | array of [codersdk.ExternalAuthAppInstallation](#codersdkexternalauthappinstallation) | false | | Installations are the installations that the user has access to. | +| `type` | string | false | | | +| `user` | [codersdk.ExternalAuthUser](#codersdkexternalauthuser) | false | | User is the user that authenticated with the provider. | + +## codersdk.ExternalAuthAppInstallation + +```json +{ + "account": { + "avatar_url": "string", + "login": "string", + "name": "string", + "profile_url": "string" + }, + "configure_url": "string", + "id": 0 +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| --------------- | ------------------------------------------------------ | -------- | ------------ | ----------- | +| `account` | [codersdk.ExternalAuthUser](#codersdkexternalauthuser) | false | | | +| `configure_url` | string | false | | | +| `id` | integer | false | | | + +## codersdk.ExternalAuthDevice + +```json +{ + "device_code": "string", + "expires_in": 0, + "interval": 0, + "user_code": "string", + "verification_uri": "string" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| ------------------ | ------- | -------- | ------------ | ----------- | +| `device_code` | string | false | | | +| `expires_in` | integer | false | | | +| `interval` | integer | false | | | +| `user_code` | string | false | | | +| `verification_uri` | string | false | | | + ## codersdk.ExternalAuthProvider ```json @@ -2770,6 +2857,26 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in | `bitbucket` | | `openid-connect` | +## codersdk.ExternalAuthUser + +```json +{ + "avatar_url": "string", + "login": "string", + "name": "string", + "profile_url": "string" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| ------------- | ------ | -------- | ------------ | ----------- | +| `avatar_url` | string | false | | | +| `login` | string | false | | | +| `name` | string | false | | | +| `profile_url` | string | false | | | + ## codersdk.Feature ```json @@ -2838,71 +2945,6 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in | `count` | integer | false | | | | `users` | array of [codersdk.User](#codersdkuser) | false | | | -## codersdk.GitAuth - -```json -{ - "app_install_url": "string", - "app_installable": true, - "authenticated": true, - "device": true, - "installations": [ - { - "account": { - "avatar_url": "string", - "login": "string", - "name": "string", - "profile_url": "string" - }, - "configure_url": "string", - "id": 0 - } - ], - "type": "string", - "user": { - "avatar_url": "string", - "login": "string", - "name": "string", - "profile_url": "string" - } -} -``` - -### Properties - -| Name | Type | Required | Restrictions | Description | -| ----------------- | --------------------------------------------------------------------------- | -------- | ------------ | ----------------------------------------------------------------------- | -| `app_install_url` | string | false | | App install URL is the URL to install the app. | -| `app_installable` | boolean | false | | App installable is true if the request for app installs was successful. | -| `authenticated` | boolean | false | | | -| `device` | boolean | false | | | -| `installations` | array of [codersdk.GitAuthAppInstallation](#codersdkgitauthappinstallation) | false | | Installations are the installations that the user has access to. | -| `type` | string | false | | | -| `user` | [codersdk.GitAuthUser](#codersdkgitauthuser) | false | | User is the user that authenticated with the provider. | - -## codersdk.GitAuthAppInstallation - -```json -{ - "account": { - "avatar_url": "string", - "login": "string", - "name": "string", - "profile_url": "string" - }, - "configure_url": "string", - "id": 0 -} -``` - -### Properties - -| Name | Type | Required | Restrictions | Description | -| --------------- | -------------------------------------------- | -------- | ------------ | ----------- | -| `account` | [codersdk.GitAuthUser](#codersdkgitauthuser) | false | | | -| `configure_url` | string | false | | | -| `id` | integer | false | | | - ## codersdk.GitAuthConfig ```json @@ -2941,48 +2983,6 @@ AuthorizationObject can represent a "set" of objects, such as: all workspaces in | `type` | string | false | | | | `validate_url` | string | false | | | -## codersdk.GitAuthDevice - -```json -{ - "device_code": "string", - "expires_in": 0, - "interval": 0, - "user_code": "string", - "verification_uri": "string" -} -``` - -### Properties - -| Name | Type | Required | Restrictions | Description | -| ------------------ | ------- | -------- | ------------ | ----------- | -| `device_code` | string | false | | | -| `expires_in` | integer | false | | | -| `interval` | integer | false | | | -| `user_code` | string | false | | | -| `verification_uri` | string | false | | | - -## codersdk.GitAuthUser - -```json -{ - "avatar_url": "string", - "login": "string", - "name": "string", - "profile_url": "string" -} -``` - -### Properties - -| Name | Type | Required | Restrictions | Description | -| ------------- | ------ | -------- | ------------ | ----------- | -| `avatar_url` | string | false | | | -| `login` | string | false | | | -| `name` | string | false | | | -| `profile_url` | string | false | | | - ## codersdk.GitSSHKey ```json diff --git a/docs/api/templates.md b/docs/api/templates.md index f4084144e0494..fe9d76633e47a 100644 --- a/docs/api/templates.md +++ b/docs/api/templates.md @@ -1800,18 +1800,18 @@ Status Code **200** To perform this operation, you must be authenticated. [Learn more](authentication.md). -## Get git auth by template version +## Get external auth by template version ### Code samples ```shell # Example request using curl -curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/gitauth \ +curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/externalauth \ -H 'Accept: application/json' \ -H 'Coder-Session-Token: API_KEY' ``` -`GET /templateversions/{templateversion}/gitauth` +`GET /templateversions/{templateversion}/externalauth` ### Parameters @@ -1840,7 +1840,7 @@ curl -X GET http://coder-server:8080/api/v2/templateversions/{templateversion}/g | ------ | ------------------------------------------------------- | ----------- | ----------------------------------------------------------------------------------------------- | | 200 | [OK](https://tools.ietf.org/html/rfc7231#section-6.3.1) | OK | array of [codersdk.TemplateVersionExternalAuth](schemas.md#codersdktemplateversionexternalauth) | -

Response Schema

+

Response Schema

Status Code **200** diff --git a/provisioner/echo/serve.go b/provisioner/echo/serve.go index 9e22157bc381b..6ab89c13a629e 100644 --- a/provisioner/echo/serve.go +++ b/provisioner/echo/serve.go @@ -225,10 +225,10 @@ func Tar(responses *Responses) ([]byte, error) { } responses.ProvisionPlan = append(responses.ProvisionPlan, &proto.Response{ Type: &proto.Response_Plan{Plan: &proto.PlanComplete{ - Error: resp.GetApply().GetError(), - Resources: resp.GetApply().GetResources(), - Parameters: resp.GetApply().GetParameters(), - GitAuthProviders: resp.GetApply().GetGitAuthProviders(), + Error: resp.GetApply().GetError(), + Resources: resp.GetApply().GetResources(), + Parameters: resp.GetApply().GetParameters(), + ExternalAuthProviders: resp.GetApply().GetExternalAuthProviders(), }}, }) } diff --git a/provisioner/terraform/executor.go b/provisioner/terraform/executor.go index d523eeca198e5..3917e4ca154fd 100644 --- a/provisioner/terraform/executor.go +++ b/provisioner/terraform/executor.go @@ -264,9 +264,9 @@ func (e *executor) plan(ctx, killCtx context.Context, env, vars []string, logr l return nil, err } return &proto.PlanComplete{ - Parameters: state.Parameters, - Resources: state.Resources, - GitAuthProviders: state.GitAuthProviders, + Parameters: state.Parameters, + Resources: state.Resources, + ExternalAuthProviders: state.ExternalAuthProviders, }, nil } @@ -404,10 +404,10 @@ func (e *executor) apply( return nil, xerrors.Errorf("read statefile %q: %w", statefilePath, err) } return &proto.ApplyComplete{ - Parameters: state.Parameters, - Resources: state.Resources, - GitAuthProviders: state.GitAuthProviders, - State: stateContent, + Parameters: state.Parameters, + Resources: state.Resources, + ExternalAuthProviders: state.ExternalAuthProviders, + State: stateContent, }, nil } diff --git a/provisioner/terraform/resources.go b/provisioner/terraform/resources.go index 4cdd16890731c..36d494711d0fd 100644 --- a/provisioner/terraform/resources.go +++ b/provisioner/terraform/resources.go @@ -114,9 +114,9 @@ type resourceMetadataItem struct { } type State struct { - Resources []*proto.Resource - Parameters []*proto.RichParameter - GitAuthProviders []string + Resources []*proto.Resource + Parameters []*proto.RichParameter + ExternalAuthProviders []string } // ConvertState consumes Terraform state and a GraphViz representation @@ -680,9 +680,9 @@ func ConvertState(modules []*tfjson.StateModule, rawGraph string) (*State, error } return &State{ - Resources: resources, - Parameters: parameters, - GitAuthProviders: gitAuthProviders, + Resources: resources, + Parameters: parameters, + ExternalAuthProviders: gitAuthProviders, }, nil } diff --git a/provisioner/terraform/resources_test.go b/provisioner/terraform/resources_test.go index cb3c4237c1f80..83aaabf21a8ea 100644 --- a/provisioner/terraform/resources_test.go +++ b/provisioner/terraform/resources_test.go @@ -546,7 +546,7 @@ func TestConvertResources(t *testing.T) { state, err := terraform.ConvertState(modules, string(tfPlanGraph)) require.NoError(t, err) sortResources(state.Resources) - sort.Strings(state.GitAuthProviders) + sort.Strings(state.ExternalAuthProviders) expectedNoMetadata := make([]*proto.Resource, 0) for _, resource := range expected.resources { @@ -584,7 +584,7 @@ func TestConvertResources(t *testing.T) { require.Equal(t, string(parametersWant), string(parametersGot)) require.Equal(t, expectedNoMetadataMap, resourcesMap) - require.ElementsMatch(t, expected.gitAuthProviders, state.GitAuthProviders) + require.ElementsMatch(t, expected.gitAuthProviders, state.ExternalAuthProviders) }) t.Run("Provision", func(t *testing.T) { @@ -600,7 +600,7 @@ func TestConvertResources(t *testing.T) { state, err := terraform.ConvertState([]*tfjson.StateModule{tfState.Values.RootModule}, string(tfStateGraph)) require.NoError(t, err) sortResources(state.Resources) - sort.Strings(state.GitAuthProviders) + sort.Strings(state.ExternalAuthProviders) for _, resource := range state.Resources { for _, agent := range resource.Agents { agent.Id = "" @@ -627,7 +627,7 @@ func TestConvertResources(t *testing.T) { require.NoError(t, err) require.Equal(t, expectedMap, resourcesMap) - require.ElementsMatch(t, expected.gitAuthProviders, state.GitAuthProviders) + require.ElementsMatch(t, expected.gitAuthProviders, state.ExternalAuthProviders) }) }) } diff --git a/provisionerd/runner/runner.go b/provisionerd/runner/runner.go index 7fe2c5a5211d7..0a529e20da8e0 100644 --- a/provisionerd/runner/runner.go +++ b/provisionerd/runner/runner.go @@ -720,7 +720,7 @@ func (r *Runner) runTemplateImportProvisionWithRichParameters( return &templateImportProvision{ Resources: c.Resources, Parameters: c.Parameters, - ExternalAuthProviders: c.GitAuthProviders, + ExternalAuthProviders: c.ExternalAuthProviders, }, nil default: return nil, xerrors.Errorf("invalid message type %q received from provisioner", diff --git a/provisionersdk/proto/provisioner.pb.go b/provisionersdk/proto/provisioner.pb.go index 7ec9944717c18..271801463d426 100644 --- a/provisionersdk/proto/provisioner.pb.go +++ b/provisionersdk/proto/provisioner.pb.go @@ -1867,10 +1867,10 @@ type PlanComplete struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` - Resources []*Resource `protobuf:"bytes,2,rep,name=resources,proto3" json:"resources,omitempty"` - Parameters []*RichParameter `protobuf:"bytes,3,rep,name=parameters,proto3" json:"parameters,omitempty"` - GitAuthProviders []string `protobuf:"bytes,4,rep,name=git_auth_providers,json=gitAuthProviders,proto3" json:"git_auth_providers,omitempty"` + Error string `protobuf:"bytes,1,opt,name=error,proto3" json:"error,omitempty"` + Resources []*Resource `protobuf:"bytes,2,rep,name=resources,proto3" json:"resources,omitempty"` + Parameters []*RichParameter `protobuf:"bytes,3,rep,name=parameters,proto3" json:"parameters,omitempty"` + ExternalAuthProviders []string `protobuf:"bytes,4,rep,name=external_auth_providers,json=externalAuthProviders,proto3" json:"external_auth_providers,omitempty"` } func (x *PlanComplete) Reset() { @@ -1926,9 +1926,9 @@ func (x *PlanComplete) GetParameters() []*RichParameter { return nil } -func (x *PlanComplete) GetGitAuthProviders() []string { +func (x *PlanComplete) GetExternalAuthProviders() []string { if x != nil { - return x.GitAuthProviders + return x.ExternalAuthProviders } return nil } @@ -1988,11 +1988,11 @@ type ApplyComplete struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - State []byte `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` - Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` - Resources []*Resource `protobuf:"bytes,3,rep,name=resources,proto3" json:"resources,omitempty"` - Parameters []*RichParameter `protobuf:"bytes,4,rep,name=parameters,proto3" json:"parameters,omitempty"` - GitAuthProviders []string `protobuf:"bytes,5,rep,name=git_auth_providers,json=gitAuthProviders,proto3" json:"git_auth_providers,omitempty"` + State []byte `protobuf:"bytes,1,opt,name=state,proto3" json:"state,omitempty"` + Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` + Resources []*Resource `protobuf:"bytes,3,rep,name=resources,proto3" json:"resources,omitempty"` + Parameters []*RichParameter `protobuf:"bytes,4,rep,name=parameters,proto3" json:"parameters,omitempty"` + ExternalAuthProviders []string `protobuf:"bytes,5,rep,name=external_auth_providers,json=externalAuthProviders,proto3" json:"external_auth_providers,omitempty"` } func (x *ApplyComplete) Reset() { @@ -2055,9 +2055,9 @@ func (x *ApplyComplete) GetParameters() []*RichParameter { return nil } -func (x *ApplyComplete) GetGitAuthProviders() []string { +func (x *ApplyComplete) GetExternalAuthProviders() []string { if x != nil { - return x.GitAuthProviders + return x.ExternalAuthProviders } return nil } @@ -2778,7 +2778,7 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{ 0x32, 0x21, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x52, 0x15, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, - 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x22, 0xc3, 0x01, 0x0a, 0x0c, 0x50, + 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x22, 0xcd, 0x01, 0x0a, 0x0c, 0x50, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x02, @@ -2788,78 +2788,80 @@ var file_provisionersdk_proto_provisioner_proto_rawDesc = []byte{ 0x74, 0x65, 0x72, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, - 0x72, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x67, 0x69, 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, - 0x67, 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, - 0x22, 0x41, 0x0a, 0x0c, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x12, 0x31, 0x0a, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, - 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, - 0x61, 0x74, 0x61, 0x22, 0xda, 0x01, 0x0a, 0x0d, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43, 0x6f, 0x6d, - 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, - 0x72, 0x12, 0x33, 0x0a, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x03, - 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, - 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x3a, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, - 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, - 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, - 0x72, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x67, 0x69, 0x74, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, - 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, - 0x67, 0x69, 0x74, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, - 0x22, 0x0f, 0x0a, 0x0d, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x22, 0x8c, 0x02, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2d, 0x0a, - 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x43, 0x6f, 0x6e, 0x66, - 0x69, 0x67, 0x48, 0x00, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x31, 0x0a, 0x05, - 0x70, 0x61, 0x72, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x12, - 0x2e, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x18, 0x2e, - 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x6c, 0x61, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x12, - 0x31, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, - 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x70, 0x70, - 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x05, 0x61, 0x70, 0x70, - 0x6c, 0x79, 0x12, 0x34, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, - 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, - 0x52, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, - 0x22, 0xd1, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x24, 0x0a, - 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x72, 0x6f, - 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, 0x48, 0x00, 0x52, 0x03, - 0x6c, 0x6f, 0x67, 0x12, 0x32, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, - 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, - 0x52, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, - 0x48, 0x00, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x12, 0x32, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x6c, - 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, - 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43, 0x6f, 0x6d, 0x70, 0x6c, - 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x42, 0x06, 0x0a, 0x04, - 0x74, 0x79, 0x70, 0x65, 0x2a, 0x3f, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, - 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x44, - 0x45, 0x42, 0x55, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x02, - 0x12, 0x08, 0x0a, 0x04, 0x57, 0x41, 0x52, 0x4e, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x45, 0x52, - 0x52, 0x4f, 0x52, 0x10, 0x04, 0x2a, 0x3b, 0x0a, 0x0f, 0x41, 0x70, 0x70, 0x53, 0x68, 0x61, 0x72, - 0x69, 0x6e, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x4f, 0x57, 0x4e, 0x45, - 0x52, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x41, 0x55, 0x54, 0x48, 0x45, 0x4e, 0x54, 0x49, 0x43, - 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x55, 0x42, 0x4c, 0x49, 0x43, - 0x10, 0x02, 0x2a, 0x37, 0x0a, 0x13, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x09, 0x0a, 0x05, 0x53, 0x54, 0x41, - 0x52, 0x54, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x54, 0x4f, 0x50, 0x10, 0x01, 0x12, 0x0b, - 0x0a, 0x07, 0x44, 0x45, 0x53, 0x54, 0x52, 0x4f, 0x59, 0x10, 0x02, 0x32, 0x49, 0x0a, 0x0b, 0x50, - 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x12, 0x3a, 0x0a, 0x07, 0x53, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, - 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x70, 0x72, - 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, - 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x73, - 0x64, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x72, 0x73, 0x12, 0x36, 0x0a, 0x17, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, + 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x15, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, + 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x22, 0x41, 0x0a, 0x0c, 0x41, 0x70, + 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x31, 0x0a, 0x08, 0x6d, 0x65, + 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x70, + 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x22, 0xe4, 0x01, + 0x0a, 0x0d, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x12, + 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x74, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, + 0x73, 0x74, 0x61, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x33, 0x0a, 0x09, 0x72, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, + 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x09, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, + 0x12, 0x3a, 0x0a, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x18, 0x04, + 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, + 0x65, 0x72, 0x2e, 0x52, 0x69, 0x63, 0x68, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, + 0x52, 0x0a, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x65, 0x74, 0x65, 0x72, 0x73, 0x12, 0x36, 0x0a, 0x17, + 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x64, 0x65, 0x72, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x09, 0x52, 0x15, 0x65, + 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x41, 0x75, 0x74, 0x68, 0x50, 0x72, 0x6f, 0x76, 0x69, + 0x64, 0x65, 0x72, 0x73, 0x22, 0x0f, 0x0a, 0x0d, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x8c, 0x02, 0x0a, 0x07, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x2d, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x13, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x48, 0x00, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x12, 0x31, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, + 0x72, 0x73, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x05, 0x70, 0x61, + 0x72, 0x73, 0x65, 0x12, 0x2e, 0x0a, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x18, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, + 0x50, 0x6c, 0x61, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, 0x04, 0x70, + 0x6c, 0x61, 0x6e, 0x12, 0x31, 0x0a, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, + 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x48, 0x00, 0x52, + 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, 0x12, 0x34, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x48, 0x00, 0x52, 0x06, 0x63, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x42, 0x06, 0x0a, 0x04, + 0x74, 0x79, 0x70, 0x65, 0x22, 0xd1, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x24, 0x0a, 0x03, 0x6c, 0x6f, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, + 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x4c, 0x6f, 0x67, + 0x48, 0x00, 0x52, 0x03, 0x6c, 0x6f, 0x67, 0x12, 0x32, 0x0a, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, + 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x61, 0x72, 0x73, 0x65, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, + 0x74, 0x65, 0x48, 0x00, 0x52, 0x05, 0x70, 0x61, 0x72, 0x73, 0x65, 0x12, 0x2f, 0x0a, 0x04, 0x70, + 0x6c, 0x61, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x50, 0x6c, 0x61, 0x6e, 0x43, 0x6f, 0x6d, 0x70, + 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x04, 0x70, 0x6c, 0x61, 0x6e, 0x12, 0x32, 0x0a, 0x05, + 0x61, 0x70, 0x70, 0x6c, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x70, 0x72, + 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x41, 0x70, 0x70, 0x6c, 0x79, 0x43, + 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x48, 0x00, 0x52, 0x05, 0x61, 0x70, 0x70, 0x6c, 0x79, + 0x42, 0x06, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x2a, 0x3f, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c, + 0x65, 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x00, 0x12, + 0x09, 0x0a, 0x05, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x49, 0x4e, + 0x46, 0x4f, 0x10, 0x02, 0x12, 0x08, 0x0a, 0x04, 0x57, 0x41, 0x52, 0x4e, 0x10, 0x03, 0x12, 0x09, + 0x0a, 0x05, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x2a, 0x3b, 0x0a, 0x0f, 0x41, 0x70, 0x70, + 0x53, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x09, 0x0a, 0x05, + 0x4f, 0x57, 0x4e, 0x45, 0x52, 0x10, 0x00, 0x12, 0x11, 0x0a, 0x0d, 0x41, 0x55, 0x54, 0x48, 0x45, + 0x4e, 0x54, 0x49, 0x43, 0x41, 0x54, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x50, 0x55, + 0x42, 0x4c, 0x49, 0x43, 0x10, 0x02, 0x2a, 0x37, 0x0a, 0x13, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x09, 0x0a, + 0x05, 0x53, 0x54, 0x41, 0x52, 0x54, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x53, 0x54, 0x4f, 0x50, + 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, 0x53, 0x54, 0x52, 0x4f, 0x59, 0x10, 0x02, 0x32, + 0x49, 0x0a, 0x0b, 0x50, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x12, 0x3a, + 0x0a, 0x07, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x2e, 0x70, 0x72, 0x6f, 0x76, + 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x15, 0x2e, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, 0x6e, 0x65, 0x72, 0x2e, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x28, 0x01, 0x30, 0x01, 0x42, 0x30, 0x5a, 0x2e, 0x67, 0x69, + 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x63, + 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x73, 0x69, 0x6f, + 0x6e, 0x65, 0x72, 0x73, 0x64, 0x6b, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/provisionersdk/proto/provisioner.proto b/provisionersdk/proto/provisioner.proto index 24e0c87301767..1682d75f606e2 100644 --- a/provisionersdk/proto/provisioner.proto +++ b/provisionersdk/proto/provisioner.proto @@ -245,7 +245,7 @@ message PlanComplete { string error = 1; repeated Resource resources = 2; repeated RichParameter parameters = 3; - repeated string git_auth_providers = 4; + repeated string external_auth_providers = 4; } // ApplyRequest asks the provisioner to apply the changes. Apply MUST be preceded by a successful plan request/response @@ -260,7 +260,7 @@ message ApplyComplete { string error = 2; repeated Resource resources = 3; repeated RichParameter parameters = 4; - repeated string git_auth_providers = 5; + repeated string external_auth_providers = 5; } // CancelRequest requests that the previous request be canceled gracefully. diff --git a/site/e2e/tests/gitAuth.spec.ts b/site/e2e/tests/gitAuth.spec.ts index 1206561538f0a..a0e55e24d8b31 100644 --- a/site/e2e/tests/gitAuth.spec.ts +++ b/site/e2e/tests/gitAuth.spec.ts @@ -1,15 +1,15 @@ import { test } from "@playwright/test"; import { gitAuth } from "../constants"; import { Endpoints } from "@octokit/types"; -import { GitAuthDevice } from "api/typesGenerated"; +import { ExternalAuthDevice } from "api/typesGenerated"; import { Awaiter, createServer } from "../helpers"; import { beforeCoderTest } from "../hooks"; test.beforeEach(async ({ page }) => await beforeCoderTest(page)); // Ensures that a Git auth provider with the device flow functions and completes! -test("git auth device", async ({ page }) => { - const device: GitAuthDevice = { +test("external auth device", async ({ page }) => { + const device: ExternalAuthDevice = { device_code: "1234", user_code: "1234-5678", expires_in: 900, @@ -46,7 +46,7 @@ test("git auth device", async ({ page }) => { sentPending.done(); }); - await page.goto(`/gitauth/${gitAuth.deviceProvider}`, { + await page.goto(`/externalauth/${gitAuth.deviceProvider}`, { waitUntil: "domcontentloaded", }); await page.getByText(device.user_code).isVisible(); @@ -57,7 +57,7 @@ test("git auth device", async ({ page }) => { await page.waitForSelector("text=1 organization authorized"); }); -test("git auth web", async ({ baseURL, page }) => { +test("external auth web", async ({ baseURL, page }) => { const srv = await createServer(gitAuth.webPort); // The GitHub validate endpoint returns the currently authenticated user! srv.use(gitAuth.validatePath, (req, res) => { @@ -70,11 +70,11 @@ test("git auth web", async ({ baseURL, page }) => { }); srv.use(gitAuth.authPath, (req, res) => { res.redirect( - `${baseURL}/gitauth/${gitAuth.webProvider}/callback?code=1234&state=` + + `${baseURL}/externalauth/${gitAuth.webProvider}/callback?code=1234&state=` + req.query.state, ); }); - await page.goto(`/gitauth/${gitAuth.webProvider}`, { + await page.goto(`/externalauth/${gitAuth.webProvider}`, { waitUntil: "domcontentloaded", }); // This endpoint doesn't have the installations URL set intentionally! diff --git a/site/src/AppRouter.tsx b/site/src/AppRouter.tsx index badbbc0aa6496..97b5b373032fa 100644 --- a/site/src/AppRouter.tsx +++ b/site/src/AppRouter.tsx @@ -207,7 +207,7 @@ export const AppRouter: FC = () => { } /> - } /> + } /> } /> diff --git a/site/src/api/api.ts b/site/src/api/api.ts index 2670bebdb338c..9828ab78848ba 100644 --- a/site/src/api/api.ts +++ b/site/src/api/api.ts @@ -331,11 +331,11 @@ export const createTemplateVersion = async ( return response.data; }; -export const getTemplateVersionGitAuth = async ( +export const getTemplateVersionExternalAuth = async ( versionId: string, ): Promise => { const response = await axios.get( - `/api/v2/templateversions/${versionId}/gitauth`, + `/api/v2/templateversions/${versionId}/externalauth`, ); return response.data; }; @@ -855,25 +855,25 @@ export const getExperiments = async (): Promise => { } }; -export const getGitAuthProvider = async ( +export const getExternalAuthProvider = async ( provider: string, -): Promise => { - const resp = await axios.get(`/api/v2/gitauth/${provider}`); +): Promise => { + const resp = await axios.get(`/api/v2/externalauth/${provider}`); return resp.data; }; -export const getGitAuthDevice = async ( +export const getExternalAuthDevice = async ( provider: string, -): Promise => { - const resp = await axios.get(`/api/v2/gitauth/${provider}/device`); +): Promise => { + const resp = await axios.get(`/api/v2/externalauth/${provider}/device`); return resp.data; }; -export const exchangeGitAuthDevice = async ( +export const exchangeExternalAuthDevice = async ( provider: string, - req: TypesGen.GitAuthDeviceExchange, + req: TypesGen.ExternalAuthDeviceExchange, ): Promise => { - const resp = await axios.post(`/api/v2/gitauth/${provider}/device`, req); + const resp = await axios.post(`/api/v2/externalauth/${provider}/device`, req); return resp.data; }; diff --git a/site/src/api/queries/templates.ts b/site/src/api/queries/templates.ts index b01cb2d31a3e9..b021386b39d3d 100644 --- a/site/src/api/queries/templates.ts +++ b/site/src/api/queries/templates.ts @@ -130,6 +130,6 @@ export const templateVersionGitAuthKey = (versionId: string) => [ export const templateVersionGitAuth = (versionId: string) => { return { queryKey: templateVersionGitAuthKey(versionId), - queryFn: () => API.getTemplateVersionGitAuth(versionId), + queryFn: () => API.getTemplateVersionExternalAuth(versionId), }; }; diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index cd70732f8701c..0b7f0c4cde7a4 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -422,6 +422,46 @@ export interface Entitlements { // From codersdk/deployment.go export type Experiments = Experiment[]; +// From codersdk/externalauth.go +export interface ExternalAuth { + readonly authenticated: boolean; + readonly device: boolean; + readonly type: string; + readonly user?: ExternalAuthUser; + readonly app_installable: boolean; + readonly installations: ExternalAuthAppInstallation[]; + readonly app_install_url: string; +} + +// From codersdk/externalauth.go +export interface ExternalAuthAppInstallation { + readonly id: number; + readonly account: ExternalAuthUser; + readonly configure_url: string; +} + +// From codersdk/externalauth.go +export interface ExternalAuthDevice { + readonly device_code: string; + readonly user_code: string; + readonly verification_uri: string; + readonly expires_in: number; + readonly interval: number; +} + +// From codersdk/externalauth.go +export interface ExternalAuthDeviceExchange { + readonly device_code: string; +} + +// From codersdk/externalauth.go +export interface ExternalAuthUser { + readonly login: string; + readonly avatar_url: string; + readonly profile_url: string; + readonly name: string; +} + // From codersdk/deployment.go export interface Feature { readonly entitlement: Entitlement; @@ -441,24 +481,6 @@ export interface GetUsersResponse { readonly count: number; } -// From codersdk/gitauth.go -export interface GitAuth { - readonly authenticated: boolean; - readonly device: boolean; - readonly type: string; - readonly user?: GitAuthUser; - readonly app_installable: boolean; - readonly installations: GitAuthAppInstallation[]; - readonly app_install_url: string; -} - -// From codersdk/gitauth.go -export interface GitAuthAppInstallation { - readonly id: number; - readonly account: GitAuthUser; - readonly configure_url: string; -} - // From codersdk/deployment.go export interface GitAuthConfig { readonly id: string; @@ -476,28 +498,6 @@ export interface GitAuthConfig { readonly device_code_url: string; } -// From codersdk/gitauth.go -export interface GitAuthDevice { - readonly device_code: string; - readonly user_code: string; - readonly verification_uri: string; - readonly expires_in: number; - readonly interval: number; -} - -// From codersdk/gitauth.go -export interface GitAuthDeviceExchange { - readonly device_code: string; -} - -// From codersdk/gitauth.go -export interface GitAuthUser { - readonly login: string; - readonly avatar_url: string; - readonly profile_url: string; - readonly name: string; -} - // From codersdk/gitsshkey.go export interface GitSSHKey { readonly user_id: string; diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.test.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.test.tsx index 0e153b3136573..37cfbd791ca6a 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.test.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.test.tsx @@ -156,7 +156,7 @@ describe("CreateWorkspacePage", () => { expect(validationError).toBeInTheDocument(); }); - it("gitauth authenticates and succeeds", async () => { + it("external auth authenticates and succeeds", async () => { jest .spyOn(API, "getWorkspaceQuota") .mockResolvedValueOnce(MockWorkspaceQuota); @@ -165,7 +165,7 @@ describe("CreateWorkspacePage", () => { .mockResolvedValueOnce({ users: [MockUser], count: 1 }); jest.spyOn(API, "createWorkspace").mockResolvedValueOnce(MockWorkspace); jest - .spyOn(API, "getTemplateVersionGitAuth") + .spyOn(API, "getTemplateVersionExternalAuth") .mockResolvedValue([MockTemplateVersionExternalAuthGithub]); renderCreateWorkspacePage(); @@ -181,7 +181,7 @@ describe("CreateWorkspacePage", () => { await userEvent.click(githubButton); jest - .spyOn(API, "getTemplateVersionGitAuth") + .spyOn(API, "getTemplateVersionExternalAuth") .mockResolvedValue([MockTemplateVersionExternalAuthGithubAuthenticated]); await screen.findByText("Authenticated with GitHub"); @@ -200,9 +200,9 @@ describe("CreateWorkspacePage", () => { ); }); - it("gitauth: errors if unauthenticated and submits", async () => { + it("external auth: errors if unauthenticated and submits", async () => { jest - .spyOn(API, "getTemplateVersionGitAuth") + .spyOn(API, "getTemplateVersionExternalAuth") .mockResolvedValueOnce([MockTemplateVersionExternalAuthGithub]); renderCreateWorkspacePage(); diff --git a/site/src/pages/GitAuthPage/GitAuthPage.tsx b/site/src/pages/GitAuthPage/GitAuthPage.tsx index f0ebfa22f34ef..6412f9f16187a 100644 --- a/site/src/pages/GitAuthPage/GitAuthPage.tsx +++ b/site/src/pages/GitAuthPage/GitAuthPage.tsx @@ -1,8 +1,8 @@ import { useQuery, useQueryClient } from "@tanstack/react-query"; import { - exchangeGitAuthDevice, - getGitAuthDevice, - getGitAuthProvider, + exchangeExternalAuthDevice, + getExternalAuthDevice, + getExternalAuthProvider, } from "api/api"; import { usePermissions } from "hooks"; import { type FC } from "react"; @@ -18,70 +18,70 @@ const GitAuthPage: FC = () => { } const permissions = usePermissions(); const queryClient = useQueryClient(); - const getGitAuthProviderQuery = useQuery({ - queryKey: ["gitauth", provider], - queryFn: () => getGitAuthProvider(provider), + const getExternalAuthProviderQuery = useQuery({ + queryKey: ["externalauth", provider], + queryFn: () => getExternalAuthProvider(provider), refetchOnWindowFocus: true, }); - const getGitAuthDeviceQuery = useQuery({ + const getExternalAuthDeviceQuery = useQuery({ enabled: - Boolean(!getGitAuthProviderQuery.data?.authenticated) && - Boolean(getGitAuthProviderQuery.data?.device), - queryFn: () => getGitAuthDevice(provider), - queryKey: ["gitauth", provider, "device"], + Boolean(!getExternalAuthProviderQuery.data?.authenticated) && + Boolean(getExternalAuthProviderQuery.data?.device), + queryFn: () => getExternalAuthDevice(provider), + queryKey: ["externalauth", provider, "device"], refetchOnMount: false, }); - const exchangeGitAuthDeviceQuery = useQuery({ + const exchangeExternalAuthDeviceQuery = useQuery({ queryFn: () => - exchangeGitAuthDevice(provider, { - device_code: getGitAuthDeviceQuery.data?.device_code || "", + exchangeExternalAuthDevice(provider, { + device_code: getExternalAuthDeviceQuery.data?.device_code || "", }), - queryKey: ["gitauth", provider, getGitAuthDeviceQuery.data?.device_code], - enabled: Boolean(getGitAuthDeviceQuery.data), + queryKey: ["externalauth", provider, getExternalAuthDeviceQuery.data?.device_code], + enabled: Boolean(getExternalAuthDeviceQuery.data), onSuccess: () => { // Force a refresh of the Git auth status. - queryClient.invalidateQueries(["gitauth", provider]).catch((ex) => { + queryClient.invalidateQueries(["externalauth", provider]).catch((ex) => { console.error("invalidate queries", ex); }); }, retry: true, - retryDelay: (getGitAuthDeviceQuery.data?.interval || 5) * 1000, + retryDelay: (getExternalAuthDeviceQuery.data?.interval || 5) * 1000, refetchOnWindowFocus: (query) => query.state.status === "success" ? false : "always", }); - if (getGitAuthProviderQuery.isLoading || !getGitAuthProviderQuery.data) { + if (getExternalAuthProviderQuery.isLoading || !getExternalAuthProviderQuery.data) { return null; } let deviceExchangeError: ApiErrorResponse | undefined; - if (isAxiosError(exchangeGitAuthDeviceQuery.failureReason)) { + if (isAxiosError(exchangeExternalAuthDeviceQuery.failureReason)) { deviceExchangeError = - exchangeGitAuthDeviceQuery.failureReason.response?.data; + exchangeExternalAuthDeviceQuery.failureReason.response?.data; } if ( - !getGitAuthProviderQuery.data.authenticated && - !getGitAuthProviderQuery.data.device + !getExternalAuthProviderQuery.data.authenticated && + !getExternalAuthProviderQuery.data.device ) { - window.location.href = `/gitauth/${provider}/callback`; + window.location.href = `/externalauth/${provider}/callback`; return null; } return ( { - queryClient.setQueryData(["gitauth", provider], { - ...getGitAuthProviderQuery.data, + queryClient.setQueryData(["externalauth", provider], { + ...getExternalAuthProviderQuery.data, authenticated: false, }); }} - viewGitAuthConfig={permissions.viewGitAuthConfig} + viewExternalAuthConfig={permissions.viewGitAuthConfig} deviceExchangeError={deviceExchangeError} - gitAuthDevice={getGitAuthDeviceQuery.data} + externalAuthDevice={getExternalAuthDeviceQuery.data} /> ); }; diff --git a/site/src/pages/GitAuthPage/GitAuthPageView.stories.tsx b/site/src/pages/GitAuthPage/GitAuthPageView.stories.tsx index 99593c98d2839..abc016657cf46 100644 --- a/site/src/pages/GitAuthPage/GitAuthPageView.stories.tsx +++ b/site/src/pages/GitAuthPage/GitAuthPageView.stories.tsx @@ -12,7 +12,7 @@ const Template: StoryFn = (args) => ( export const WebAuthenticated = Template.bind({}); WebAuthenticated.args = { - gitAuth: { + externalAuth: { type: "BitBucket", authenticated: true, device: false, @@ -30,7 +30,7 @@ WebAuthenticated.args = { export const DeviceUnauthenticated = Template.bind({}); DeviceUnauthenticated.args = { - gitAuth: { + externalAuth: { type: "GitHub", authenticated: false, device: true, @@ -38,7 +38,7 @@ DeviceUnauthenticated.args = { app_install_url: "", app_installable: false, }, - gitAuthDevice: { + externalAuthDevice: { device_code: "1234-5678", expires_in: 900, interval: 5, @@ -49,7 +49,7 @@ DeviceUnauthenticated.args = { export const DeviceUnauthenticatedError = Template.bind({}); DeviceUnauthenticatedError.args = { - gitAuth: { + externalAuth: { type: "GitHub", authenticated: false, device: true, @@ -57,7 +57,7 @@ DeviceUnauthenticatedError.args = { app_install_url: "", app_installable: false, }, - gitAuthDevice: { + externalAuthDevice: { device_code: "1234-5678", expires_in: 900, interval: 5, @@ -72,8 +72,8 @@ DeviceUnauthenticatedError.args = { export const DeviceAuthenticatedNotInstalled = Template.bind({}); DeviceAuthenticatedNotInstalled.args = { - viewGitAuthConfig: true, - gitAuth: { + viewExternalAuthConfig: true, + externalAuth: { type: "GitHub", authenticated: true, device: true, @@ -91,7 +91,7 @@ DeviceAuthenticatedNotInstalled.args = { export const DeviceAuthenticatedInstalled = Template.bind({}); DeviceAuthenticatedInstalled.args = { - gitAuth: { + externalAuth: { type: "GitHub", authenticated: true, device: true, diff --git a/site/src/pages/GitAuthPage/GitAuthPageView.tsx b/site/src/pages/GitAuthPage/GitAuthPageView.tsx index 23ec8fd98ee0d..12dfee106840e 100644 --- a/site/src/pages/GitAuthPage/GitAuthPageView.tsx +++ b/site/src/pages/GitAuthPage/GitAuthPageView.tsx @@ -5,7 +5,7 @@ import Link from "@mui/material/Link"; import Tooltip from "@mui/material/Tooltip"; import { makeStyles } from "@mui/styles"; import { ApiErrorResponse } from "api/errors"; -import { GitAuth, GitAuthDevice } from "api/typesGenerated"; +import { ExternalAuth, ExternalAuthDevice } from "api/typesGenerated"; import { Alert } from "components/Alert/Alert"; import { Avatar } from "components/Avatar/Avatar"; import { CopyButton } from "components/CopyButton/CopyButton"; @@ -14,10 +14,10 @@ import { Welcome } from "components/Welcome/Welcome"; import { type FC } from "react"; export interface GitAuthPageViewProps { - gitAuth: GitAuth; - viewGitAuthConfig: boolean; + externalAuth: ExternalAuth; + viewExternalAuthConfig: boolean; - gitAuthDevice?: GitAuthDevice; + externalAuthDevice?: ExternalAuthDevice; deviceExchangeError?: ApiErrorResponse; onReauthenticate: () => void; @@ -25,10 +25,10 @@ export interface GitAuthPageViewProps { const GitAuthPageView: FC = ({ deviceExchangeError, - gitAuth, - gitAuthDevice, + externalAuth: gitAuth, + externalAuthDevice: gitAuthDevice, onReauthenticate, - viewGitAuthConfig, + viewExternalAuthConfig: viewGitAuthConfig, }) => { const styles = useStyles(); @@ -40,7 +40,7 @@ const GitAuthPageView: FC = ({ {gitAuth.device && ( )} @@ -136,9 +136,9 @@ const GitAuthPageView: FC = ({ }; const GitDeviceAuth: FC<{ - gitAuthDevice?: GitAuthDevice; + externalAuthDevice?: ExternalAuthDevice; deviceExchangeError?: ApiErrorResponse; -}> = ({ gitAuthDevice, deviceExchangeError }) => { +}> = ({ externalAuthDevice, deviceExchangeError }) => { const styles = useStyles(); let status = ( @@ -175,7 +175,7 @@ const GitDeviceAuth: FC<{ } } - if (!gitAuthDevice) { + if (!externalAuthDevice) { return ; } @@ -184,8 +184,8 @@ const GitDeviceAuth: FC<{

Copy your one-time code: 

- {gitAuthDevice.user_code} {" "} - + {externalAuthDevice.user_code} {" "} +

Then open the link below and paste it: @@ -193,7 +193,7 @@ const GitDeviceAuth: FC<{
diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index 1a72a34a64d6c..80e34ed0bcec4 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -2188,7 +2188,7 @@ export const MockTemplateVersionExternalAuthGithub: TypesGen.TemplateVersionExte { id: "github", type: "github", - authenticate_url: "https://example.com/gitauth/github", + authenticate_url: "https://example.com/externalauth/github", authenticated: false, }; @@ -2196,7 +2196,7 @@ export const MockTemplateVersionExternalAuthGithubAuthenticated: TypesGen.Templa { id: "github", type: "github", - authenticate_url: "https://example.com/gitauth/github", + authenticate_url: "https://example.com/externalauth/github", authenticated: true, }; diff --git a/site/src/testHelpers/handlers.ts b/site/src/testHelpers/handlers.ts index c1deb90054929..abce3fd2175dd 100644 --- a/site/src/testHelpers/handlers.ts +++ b/site/src/testHelpers/handlers.ts @@ -112,7 +112,7 @@ export const handlers = [ }, ), rest.get( - "/api/v2/templateversions/:templateVersionId/gitauth", + "/api/v2/templateversions/:templateVersionId/externalauth", async (req, res, ctx) => { return res(ctx.status(200), ctx.json([])); }, diff --git a/site/src/utils/gitAuth.ts b/site/src/utils/gitAuth.ts deleted file mode 100644 index 66b6ac9bc3d66..0000000000000 --- a/site/src/utils/gitAuth.ts +++ /dev/null @@ -1 +0,0 @@ -export const REFRESH_GITAUTH_BROADCAST_CHANNEL = "gitauth_refresh"; From 986bc52d6088c785fb13d5a431ac7c8a3794298c Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Fri, 29 Sep 2023 20:08:40 +0000 Subject: [PATCH 2/6] Rename FE --- site/src/AppRouter.tsx | 9 ++- site/src/api/queries/templates.ts | 8 +-- .../CreateWorkspacePage.tsx | 35 +++++----- .../CreateWorkspacePageView.stories.tsx | 6 +- .../CreateWorkspacePageView.tsx | 62 +++++++++-------- ...h.stories.tsx => ExternalAuth.stories.tsx} | 10 +-- .../{GitAuth.tsx => ExternalAuth.tsx} | 22 +++--- .../ExternalAuthPage.tsx} | 21 ++++-- .../ExternalAuthPageView.stories.tsx} | 14 ++-- .../ExternalAuthPageView.tsx} | 68 +++++++++++-------- site/src/testHelpers/entities.ts | 2 +- site/src/xServices/auth/authXService.ts | 4 +- 12 files changed, 143 insertions(+), 118 deletions(-) rename site/src/pages/CreateWorkspacePage/{GitAuth.stories.tsx => ExternalAuth.stories.tsx} (83%) rename site/src/pages/CreateWorkspacePage/{GitAuth.tsx => ExternalAuth.tsx} (83%) rename site/src/pages/{GitAuthPage/GitAuthPage.tsx => ExternalAuthPage/ExternalAuthPage.tsx} (85%) rename site/src/pages/{GitAuthPage/GitAuthPageView.stories.tsx => ExternalAuthPage/ExternalAuthPageView.stories.tsx} (88%) rename site/src/pages/{GitAuthPage/GitAuthPageView.tsx => ExternalAuthPage/ExternalAuthPageView.tsx} (78%) diff --git a/site/src/AppRouter.tsx b/site/src/AppRouter.tsx index 97b5b373032fa..84cbd8547214b 100644 --- a/site/src/AppRouter.tsx +++ b/site/src/AppRouter.tsx @@ -122,7 +122,9 @@ const NetworkSettingsPage = lazy( "./pages/DeploySettingsPage/NetworkSettingsPage/NetworkSettingsPage" ), ); -const GitAuthPage = lazy(() => import("./pages/GitAuthPage/GitAuthPage")); +const ExternalAuthPage = lazy( + () => import("./pages/ExternalAuthPage/ExternalAuthPage"), +); const TemplateVersionPage = lazy( () => import("./pages/TemplateVersionPage/TemplateVersionPage"), ); @@ -207,7 +209,10 @@ export const AppRouter: FC = () => { } /> - } /> + } + /> } /> diff --git a/site/src/api/queries/templates.ts b/site/src/api/queries/templates.ts index b021386b39d3d..15fc52db1ec1e 100644 --- a/site/src/api/queries/templates.ts +++ b/site/src/api/queries/templates.ts @@ -121,15 +121,15 @@ export const updateActiveTemplateVersion = ( }; }; -export const templateVersionGitAuthKey = (versionId: string) => [ +export const templateVersionExternalAuthKey = (versionId: string) => [ "templateVersion", versionId, - "gitAuth", + "externalAuth", ]; -export const templateVersionGitAuth = (versionId: string) => { +export const templateVersionExternalAuth = (versionId: string) => { return { - queryKey: templateVersionGitAuthKey(versionId), + queryKey: templateVersionExternalAuthKey(versionId), queryFn: () => API.getTemplateVersionExternalAuth(versionId), }; }; diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx index f7739a2acbed6..91698fdc20291 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx @@ -24,9 +24,9 @@ import { NumberDictionary, } from "unique-names-generator"; import { useQuery } from "@tanstack/react-query"; -import { templateVersionGitAuth } from "api/queries/templates"; +import { templateVersionExternalAuth } from "api/queries/templates"; -export type GitAuthPollingState = "idle" | "polling" | "abandoned"; +export type ExternalAuthPollingState = "idle" | "polling" | "abandoned"; const CreateWorkspacePage: FC = () => { const organizationId = useOrganizationId(); @@ -58,43 +58,44 @@ const CreateWorkspacePage: FC = () => { ? "Creating workspace..." : "Create workspace"; - const [gitAuthPollingState, setGitAuthPollingState] = - useState("idle"); + const [externalAuthPollingState, setExternalAuthPollingState] = + useState("idle"); - const startPollingGitAuth = useCallback(() => { - setGitAuthPollingState("polling"); + const startPollingExternalAuth = useCallback(() => { + setExternalAuthPollingState("polling"); }, []); - const { data: gitAuth, error } = useQuery( + const { data: externalAuth, error } = useQuery( versionId ? { - ...templateVersionGitAuth(versionId), - refetchInterval: gitAuthPollingState === "polling" ? 1000 : false, + ...templateVersionExternalAuth(versionId), + refetchInterval: + externalAuthPollingState === "polling" ? 1000 : false, } : { enabled: false }, ); - const allSignedIn = gitAuth?.every((it) => it.authenticated); + const allSignedIn = externalAuth?.every((it) => it.authenticated); useEffect(() => { if (allSignedIn) { - setGitAuthPollingState("idle"); + setExternalAuthPollingState("idle"); return; } - if (gitAuthPollingState !== "polling") { + if (externalAuthPollingState !== "polling") { return; } // Poll for a maximum of one minute const quitPolling = setTimeout( - () => setGitAuthPollingState("abandoned"), + () => setExternalAuthPollingState("abandoned"), 60_000, ); return () => { clearTimeout(quitPolling); }; - }, [gitAuthPollingState, allSignedIn]); + }, [externalAuthPollingState, allSignedIn]); return ( <> @@ -116,9 +117,9 @@ const CreateWorkspacePage: FC = () => { error={error} template={template!} versionId={versionId} - gitAuth={gitAuth ?? []} - gitAuthPollingState={gitAuthPollingState} - startPollingGitAuth={startPollingGitAuth} + externalAuth={externalAuth ?? []} + externalAuthPollingState={externalAuthPollingState} + startPollingExternalAuth={startPollingExternalAuth} permissions={permissions as CreateWSPermissions} parameters={parameters!} creatingWorkspace={createWorkspaceState.matches("creatingWorkspace")} diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx index f8b25451e846f..5a0478ca4dfe3 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.stories.tsx @@ -18,7 +18,7 @@ const meta: Meta = { defaultBuildParameters: [], template: MockTemplate, parameters: [], - gitAuth: [], + externalAuth: [], permissions: { createWorkspaceForUser: true, }, @@ -86,9 +86,9 @@ export const Parameters: Story = { }, }; -export const GitAuth: Story = { +export const ExternalAuth: Story = { args: { - gitAuth: [ + externalAuth: [ { id: "github", type: "github", diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx index aea3832f65917..2776a43ef3e8e 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePageView.tsx @@ -27,10 +27,10 @@ import { MutableTemplateParametersSection, } from "components/TemplateParameters/TemplateParameters"; import { CreateWSPermissions } from "xServices/createWorkspace/createWorkspaceXService"; -import { GitAuth } from "./GitAuth"; +import { ExternalAuth } from "./ExternalAuth"; import { ErrorAlert } from "components/Alert/ErrorAlert"; import { Stack } from "components/Stack/Stack"; -import { type GitAuthPollingState } from "./CreateWorkspacePage"; +import { type ExternalAuthPollingState } from "./CreateWorkspacePage"; export interface CreateWorkspacePageViewProps { error: unknown; @@ -38,9 +38,9 @@ export interface CreateWorkspacePageViewProps { defaultOwner: TypesGen.User; template: TypesGen.Template; versionId?: string; - gitAuth: TypesGen.TemplateVersionExternalAuth[]; - gitAuthPollingState: GitAuthPollingState; - startPollingGitAuth: () => void; + externalAuth: TypesGen.TemplateVersionExternalAuth[]; + externalAuthPollingState: ExternalAuthPollingState; + startPollingExternalAuth: () => void; parameters: TypesGen.TemplateVersionParameter[]; defaultBuildParameters: TypesGen.WorkspaceBuildParameter[]; permissions: CreateWSPermissions; @@ -58,9 +58,9 @@ export const CreateWorkspacePageView: FC = ({ defaultOwner, template, versionId, - gitAuth, - gitAuthPollingState, - startPollingGitAuth, + externalAuth, + externalAuthPollingState, + startPollingExternalAuth, parameters, defaultBuildParameters, permissions, @@ -70,7 +70,8 @@ export const CreateWorkspacePageView: FC = ({ }) => { const styles = useStyles(); const [owner, setOwner] = useState(defaultOwner); - const { verifyGitAuth, gitAuthErrors } = useGitAuthVerification(gitAuth); + const { verifyExternalAuth, externalAuthErrors } = + useExternalAuthVerification(externalAuth); const form: FormikContextType = useFormik({ initialValues: { @@ -87,7 +88,7 @@ export const CreateWorkspacePageView: FC = ({ }), enableReinitialize: true, onSubmit: (request) => { - if (!verifyGitAuth()) { + if (!verifyExternalAuth()) { form.setSubmitting(false); return; } @@ -160,21 +161,21 @@ export const CreateWorkspacePageView: FC = ({ )} - {gitAuth && gitAuth.length > 0 && ( + {externalAuth && externalAuth.length > 0 && ( - {gitAuth.map((auth) => ( - ( + ))} @@ -231,23 +232,24 @@ export const CreateWorkspacePageView: FC = ({ ); }; -type GitAuthErrors = Record; +type ExternalAuthErrors = Record; -const useGitAuthVerification = ( - gitAuth: TypesGen.TemplateVersionExternalAuth[], +const useExternalAuthVerification = ( + externalAuth: TypesGen.TemplateVersionExternalAuth[], ) => { - const [gitAuthErrors, setGitAuthErrors] = useState({}); + const [externalAuthErrors, setExternalAuthErrors] = + useState({}); - // Clear errors when gitAuth is refreshed + // Clear errors when externalAuth is refreshed useEffect(() => { - setGitAuthErrors({}); - }, [gitAuth]); + setExternalAuthErrors({}); + }, [externalAuth]); - const verifyGitAuth = () => { - const errors: GitAuthErrors = {}; + const verifyExternalAuth = () => { + const errors: ExternalAuthErrors = {}; - for (let i = 0; i < gitAuth.length; i++) { - const auth = gitAuth.at(i); + for (let i = 0; i < externalAuth.length; i++) { + const auth = externalAuth.at(i); if (!auth) { continue; } @@ -256,14 +258,14 @@ const useGitAuthVerification = ( } } - setGitAuthErrors(errors); + setExternalAuthErrors(errors); const isValid = Object.keys(errors).length === 0; return isValid; }; return { - gitAuthErrors, - verifyGitAuth, + externalAuthErrors, + verifyExternalAuth, }; }; diff --git a/site/src/pages/CreateWorkspacePage/GitAuth.stories.tsx b/site/src/pages/CreateWorkspacePage/ExternalAuth.stories.tsx similarity index 83% rename from site/src/pages/CreateWorkspacePage/GitAuth.stories.tsx rename to site/src/pages/CreateWorkspacePage/ExternalAuth.stories.tsx index bd6f8cf813d39..9c65abc5a0f83 100644 --- a/site/src/pages/CreateWorkspacePage/GitAuth.stories.tsx +++ b/site/src/pages/CreateWorkspacePage/ExternalAuth.stories.tsx @@ -1,13 +1,13 @@ -import { GitAuth } from "./GitAuth"; +import { ExternalAuth } from "./ExternalAuth"; import type { Meta, StoryObj } from "@storybook/react"; -const meta: Meta = { - title: "components/GitAuth", - component: GitAuth, +const meta: Meta = { + title: "components/ExternalAuth", + component: ExternalAuth, }; export default meta; -type Story = StoryObj; +type Story = StoryObj; export const GithubNotAuthenticated: Story = { args: { diff --git a/site/src/pages/CreateWorkspacePage/GitAuth.tsx b/site/src/pages/CreateWorkspacePage/ExternalAuth.tsx similarity index 83% rename from site/src/pages/CreateWorkspacePage/GitAuth.tsx rename to site/src/pages/CreateWorkspacePage/ExternalAuth.tsx index e7ab032153165..4c685089b7782 100644 --- a/site/src/pages/CreateWorkspacePage/GitAuth.tsx +++ b/site/src/pages/CreateWorkspacePage/ExternalAuth.tsx @@ -9,27 +9,27 @@ import { BitbucketIcon } from "components/Icons/BitbucketIcon"; import { GitlabIcon } from "components/Icons/GitlabIcon"; import { FC } from "react"; import { makeStyles } from "@mui/styles"; -import { type GitAuthPollingState } from "./CreateWorkspacePage"; +import { type ExternalAuthPollingState } from "./CreateWorkspacePage"; import { Stack } from "components/Stack/Stack"; import ReplayIcon from "@mui/icons-material/Replay"; import { LoadingButton } from "components/LoadingButton/LoadingButton"; -export interface GitAuthProps { +export interface ExternalAuthProps { type: TypesGen.ExternalAuthProvider; authenticated: boolean; authenticateURL: string; - gitAuthPollingState: GitAuthPollingState; - startPollingGitAuth: () => void; + externalAuthPollingState: ExternalAuthPollingState; + startPollingExternalAuth: () => void; error?: string; } -export const GitAuth: FC = (props) => { +export const ExternalAuth: FC = (props) => { const { type, authenticated, authenticateURL, - gitAuthPollingState, - startPollingGitAuth, + externalAuthPollingState, + startPollingExternalAuth, error, } = props; @@ -66,7 +66,7 @@ export const GitAuth: FC = (props) => { > = (props) => { return; } window.open(authenticateURL, "_blank", "width=900,height=600"); - startPollingGitAuth(); + startPollingExternalAuth(); }} > {authenticated @@ -90,8 +90,8 @@ export const GitAuth: FC = (props) => { : `Login with ${prettyName}`} - {gitAuthPollingState === "abandoned" && ( - )} diff --git a/site/src/pages/GitAuthPage/GitAuthPage.tsx b/site/src/pages/ExternalAuthPage/ExternalAuthPage.tsx similarity index 85% rename from site/src/pages/GitAuthPage/GitAuthPage.tsx rename to site/src/pages/ExternalAuthPage/ExternalAuthPage.tsx index 6412f9f16187a..04300803aaf05 100644 --- a/site/src/pages/GitAuthPage/GitAuthPage.tsx +++ b/site/src/pages/ExternalAuthPage/ExternalAuthPage.tsx @@ -7,11 +7,11 @@ import { import { usePermissions } from "hooks"; import { type FC } from "react"; import { useParams } from "react-router-dom"; -import GitAuthPageView from "./GitAuthPageView"; +import ExternalAuthPageView from "./ExternalAuthPageView"; import { ApiErrorResponse } from "api/errors"; import { isAxiosError } from "axios"; -const GitAuthPage: FC = () => { +const ExternalAuthPage: FC = () => { const { provider } = useParams(); if (!provider) { throw new Error("provider must exist"); @@ -37,7 +37,11 @@ const GitAuthPage: FC = () => { exchangeExternalAuthDevice(provider, { device_code: getExternalAuthDeviceQuery.data?.device_code || "", }), - queryKey: ["externalauth", provider, getExternalAuthDeviceQuery.data?.device_code], + queryKey: [ + "externalauth", + provider, + getExternalAuthDeviceQuery.data?.device_code, + ], enabled: Boolean(getExternalAuthDeviceQuery.data), onSuccess: () => { // Force a refresh of the Git auth status. @@ -51,7 +55,10 @@ const GitAuthPage: FC = () => { query.state.status === "success" ? false : "always", }); - if (getExternalAuthProviderQuery.isLoading || !getExternalAuthProviderQuery.data) { + if ( + getExternalAuthProviderQuery.isLoading || + !getExternalAuthProviderQuery.data + ) { return null; } @@ -71,7 +78,7 @@ const GitAuthPage: FC = () => { } return ( - { queryClient.setQueryData(["externalauth", provider], { @@ -79,11 +86,11 @@ const GitAuthPage: FC = () => { authenticated: false, }); }} - viewExternalAuthConfig={permissions.viewGitAuthConfig} + viewExternalAuthConfig={permissions.viewExternalAuthConfig} deviceExchangeError={deviceExchangeError} externalAuthDevice={getExternalAuthDeviceQuery.data} /> ); }; -export default GitAuthPage; +export default ExternalAuthPage; diff --git a/site/src/pages/GitAuthPage/GitAuthPageView.stories.tsx b/site/src/pages/ExternalAuthPage/ExternalAuthPageView.stories.tsx similarity index 88% rename from site/src/pages/GitAuthPage/GitAuthPageView.stories.tsx rename to site/src/pages/ExternalAuthPage/ExternalAuthPageView.stories.tsx index abc016657cf46..2d975245d50d9 100644 --- a/site/src/pages/GitAuthPage/GitAuthPageView.stories.tsx +++ b/site/src/pages/ExternalAuthPage/ExternalAuthPageView.stories.tsx @@ -1,13 +1,15 @@ import { Meta, StoryFn } from "@storybook/react"; -import GitAuthPageView, { GitAuthPageViewProps } from "./GitAuthPageView"; +import ExternalAuthPageView, { + ExternalAuthPageViewProps, +} from "./ExternalAuthPageView"; export default { - title: "pages/GitAuthPageView", - component: GitAuthPageView, -} as Meta; + title: "pages/ExternalAuthPageView", + component: ExternalAuthPageView, +} as Meta; -const Template: StoryFn = (args) => ( - +const Template: StoryFn = (args) => ( + ); export const WebAuthenticated = Template.bind({}); diff --git a/site/src/pages/GitAuthPage/GitAuthPageView.tsx b/site/src/pages/ExternalAuthPage/ExternalAuthPageView.tsx similarity index 78% rename from site/src/pages/GitAuthPage/GitAuthPageView.tsx rename to site/src/pages/ExternalAuthPage/ExternalAuthPageView.tsx index 12dfee106840e..3984f35e37b24 100644 --- a/site/src/pages/GitAuthPage/GitAuthPageView.tsx +++ b/site/src/pages/ExternalAuthPage/ExternalAuthPageView.tsx @@ -13,7 +13,7 @@ import { SignInLayout } from "components/SignInLayout/SignInLayout"; import { Welcome } from "components/Welcome/Welcome"; import { type FC } from "react"; -export interface GitAuthPageViewProps { +export interface ExternalAuthPageViewProps { externalAuth: ExternalAuth; viewExternalAuthConfig: boolean; @@ -23,37 +23,43 @@ export interface GitAuthPageViewProps { onReauthenticate: () => void; } -const GitAuthPageView: FC = ({ +const ExternalAuthPageView: FC = ({ deviceExchangeError, - externalAuth: gitAuth, - externalAuthDevice: gitAuthDevice, + externalAuth, + externalAuthDevice, onReauthenticate, - viewExternalAuthConfig: viewGitAuthConfig, + viewExternalAuthConfig, }) => { const styles = useStyles(); - if (!gitAuth.authenticated) { + if (!externalAuth.authenticated) { return ( - + - {gitAuth.device && ( + {externalAuth.device && ( )} ); } - const hasInstallations = gitAuth.installations.length > 0; + const hasInstallations = externalAuth.installations.length > 0; // We only want to wrap this with a link if an install URL is available! - let installTheApp: JSX.Element = <>{`install the ${gitAuth.type} App`}; - if (gitAuth.app_install_url) { + let installTheApp: JSX.Element = ( + <>{`install the ${externalAuth.type} App`} + ); + if (externalAuth.app_install_url) { installTheApp = ( - + {installTheApp} ); @@ -61,16 +67,17 @@ const GitAuthPageView: FC = ({ return ( - +

- Hey @{gitAuth.user?.login}! 👋{" "} - {(!gitAuth.app_installable || gitAuth.installations.length > 0) && + Hey @{externalAuth.user?.login}! 👋{" "} + {(!externalAuth.app_installable || + externalAuth.installations.length > 0) && "You are now authenticated with Git. Feel free to close this window!"}

- {gitAuth.installations.length > 0 && ( + {externalAuth.installations.length > 0 && (
- {gitAuth.installations.map((install) => { + {externalAuth.installations.map((install) => { if (!install.account) { return; } @@ -93,32 +100,33 @@ const GitAuthPageView: FC = ({ ); })}   - {gitAuth.installations.length} organization - {gitAuth.installations.length !== 1 && "s are"} authorized + {externalAuth.installations.length} organization + {externalAuth.installations.length !== 1 && "s are"} authorized
)}
- {!hasInstallations && gitAuth.app_installable && ( + {!hasInstallations && externalAuth.app_installable && ( You must {installTheApp} to clone private repositories. Accounts will appear here once authorized. )} - {viewGitAuthConfig && - gitAuth.app_install_url && - gitAuth.app_installable && ( + {viewExternalAuthConfig && + externalAuth.app_install_url && + externalAuth.app_installable && ( - {gitAuth.installations.length > 0 + {externalAuth.installations.length > 0 ? "Configure" - : "Install"} the {gitAuth.type} App + : "Install"}{" "} + the {externalAuth.type} App )} Copy your one-time code: 
- {externalAuthDevice.user_code} {" "} - + {externalAuthDevice.user_code} +  

Then open the link below and paste it: @@ -207,7 +215,7 @@ const GitDeviceAuth: FC<{ ); }; -export default GitAuthPageView; +export default ExternalAuthPageView; const useStyles = makeStyles((theme) => ({ text: { diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index 80e34ed0bcec4..d44ed976f1a5f 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -2140,7 +2140,7 @@ export const MockPermissions: Permissions = { viewDeploymentValues: true, viewUpdateCheck: true, viewDeploymentStats: true, - viewGitAuthConfig: true, + viewExternalAuthConfig: true, editWorkspaceProxies: true, }; diff --git a/site/src/xServices/auth/authXService.ts b/site/src/xServices/auth/authXService.ts index 295954402a9b8..ee4bda58de3e1 100644 --- a/site/src/xServices/auth/authXService.ts +++ b/site/src/xServices/auth/authXService.ts @@ -18,7 +18,7 @@ export const checks = { viewDeploymentValues: "viewDeploymentValues", createGroup: "createGroup", viewUpdateCheck: "viewUpdateCheck", - viewGitAuthConfig: "viewGitAuthConfig", + viewExternalAuthConfig: "viewExternalAuthConfig", viewDeploymentStats: "viewDeploymentStats", editWorkspaceProxies: "editWorkspaceProxies", } as const; @@ -84,7 +84,7 @@ export const permissionsToCheck = { }, action: "read", }, - [checks.viewGitAuthConfig]: { + [checks.viewExternalAuthConfig]: { object: { resource_type: "deployment_config", }, From 682460c8f13070625a2233ed66d8f2ec9836a205 Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Fri, 29 Sep 2023 20:17:31 +0000 Subject: [PATCH 3/6] Fix em' up --- Makefile | 2 +- site/e2e/helpers.ts | 4 ++-- site/e2e/provisionerGenerated.ts | 8 ++++---- site/e2e/tests/{gitAuth.spec.ts => externalAuth.spec.ts} | 0 4 files changed, 7 insertions(+), 7 deletions(-) rename site/e2e/tests/{gitAuth.spec.ts => externalAuth.spec.ts} (100%) diff --git a/Makefile b/Makefile index d382535030e53..64615132a556a 100644 --- a/Makefile +++ b/Makefile @@ -542,7 +542,7 @@ site/src/api/typesGenerated.ts: scripts/apitypings/main.go $(shell find ./coders cd site pnpm run format:types ./src/api/typesGenerated.ts -site/e2e/provisionerGenerated.ts: provisionerd/proto/provisionerd.pb.go +site/e2e/provisionerGenerated.ts: provisionerd/proto/provisionerd.pb.go provisionersdk/proto/provisioner.pb.go cd site ../scripts/pnpm_install.sh pnpm run gen:provisioner diff --git a/site/e2e/helpers.ts b/site/e2e/helpers.ts index 548ac9168624b..3fc8d9b52ef1c 100644 --- a/site/e2e/helpers.ts +++ b/site/e2e/helpers.ts @@ -426,7 +426,7 @@ const createTemplateVersionTar = async ( error: response.apply?.error ?? "", resources: response.apply?.resources ?? [], parameters: response.apply?.parameters ?? [], - gitAuthProviders: response.apply?.gitAuthProviders ?? [], + externalAuthProviders: response.apply?.externalAuthProviders ?? [], }, }; }); @@ -508,7 +508,7 @@ const createTemplateVersionTar = async ( state: new Uint8Array(), resources: [], parameters: [], - gitAuthProviders: [], + externalAuthProviders: [], ...response.apply, } as ApplyComplete; response.apply.resources = response.apply.resources?.map(fillResource); diff --git a/site/e2e/provisionerGenerated.ts b/site/e2e/provisionerGenerated.ts index 1ade0a9e6b2cb..5ad3fb645ad47 100644 --- a/site/e2e/provisionerGenerated.ts +++ b/site/e2e/provisionerGenerated.ts @@ -249,7 +249,7 @@ export interface PlanComplete { error: string; resources: Resource[]; parameters: RichParameter[]; - gitAuthProviders: string[]; + externalAuthProviders: string[]; } /** @@ -266,7 +266,7 @@ export interface ApplyComplete { error: string; resources: Resource[]; parameters: RichParameter[]; - gitAuthProviders: string[]; + externalAuthProviders: string[]; } /** CancelRequest requests that the previous request be canceled gracefully. */ @@ -859,7 +859,7 @@ export const PlanComplete = { for (const v of message.parameters) { RichParameter.encode(v!, writer.uint32(26).fork()).ldelim(); } - for (const v of message.gitAuthProviders) { + for (const v of message.externalAuthProviders) { writer.uint32(34).string(v!); } return writer; @@ -895,7 +895,7 @@ export const ApplyComplete = { for (const v of message.parameters) { RichParameter.encode(v!, writer.uint32(34).fork()).ldelim(); } - for (const v of message.gitAuthProviders) { + for (const v of message.externalAuthProviders) { writer.uint32(42).string(v!); } return writer; diff --git a/site/e2e/tests/gitAuth.spec.ts b/site/e2e/tests/externalAuth.spec.ts similarity index 100% rename from site/e2e/tests/gitAuth.spec.ts rename to site/e2e/tests/externalAuth.spec.ts From 0bfe63004a933c05577364bb834400dc874874b9 Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Sat, 30 Sep 2023 17:30:02 +0000 Subject: [PATCH 4/6] Fix linting error --- coderd/externalauth/config_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/coderd/externalauth/config_test.go b/coderd/externalauth/config_test.go index c7a529933d87f..4bd9e0b1628c3 100644 --- a/coderd/externalauth/config_test.go +++ b/coderd/externalauth/config_test.go @@ -26,7 +26,6 @@ import ( func TestRefreshToken(t *testing.T) { t.Parallel() - const providerID = "test-idp" expired := time.Now().Add(time.Hour * -1) t.Run("NoRefreshExpired", func(t *testing.T) { From 8e4a06035484430f4bb49800d5077decf84a5f77 Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Sat, 30 Sep 2023 17:39:49 +0000 Subject: [PATCH 5/6] Fix e2e tests --- site/e2e/helpers.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/e2e/helpers.ts b/site/e2e/helpers.ts index 3fc8d9b52ef1c..1e54d84b8082b 100644 --- a/site/e2e/helpers.ts +++ b/site/e2e/helpers.ts @@ -523,7 +523,7 @@ const createTemplateVersionTar = async ( error: "", resources: [], parameters: [], - gitAuthProviders: [], + externalAuthProviders: [], ...response.plan, } as PlanComplete; response.plan.resources = response.plan.resources?.map(fillResource); From cf143d95ea4daf1360be792a2ec8867d558a48d9 Mon Sep 17 00:00:00 2001 From: Kyle Carberry Date: Sat, 30 Sep 2023 18:31:27 +0000 Subject: [PATCH 6/6] chore: update helm golden files --- helm/coder/tests/testdata/auto_access_url_1.golden | 2 +- helm/coder/tests/testdata/auto_access_url_2.golden | 2 +- helm/coder/tests/testdata/auto_access_url_3.golden | 2 +- helm/coder/tests/testdata/command.golden | 2 +- helm/coder/tests/testdata/command_args.golden | 2 +- helm/coder/tests/testdata/default_values.golden | 2 +- helm/coder/tests/testdata/env_from.golden | 2 +- helm/coder/tests/testdata/labels_annotations.golden | 2 +- helm/coder/tests/testdata/provisionerd_psk.golden | 2 +- helm/coder/tests/testdata/sa.golden | 2 +- helm/coder/tests/testdata/tls.golden | 2 +- helm/coder/tests/testdata/workspace_proxy.golden | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/helm/coder/tests/testdata/auto_access_url_1.golden b/helm/coder/tests/testdata/auto_access_url_1.golden index 318fce2098240..a55a7413fb95b 100644 --- a/helm/coder/tests/testdata/auto_access_url_1.golden +++ b/helm/coder/tests/testdata/auto_access_url_1.golden @@ -84,7 +84,7 @@ metadata: {} spec: type: LoadBalancer - sessionAffinity: ClientIP + sessionAffinity: None ports: - name: "http" port: 80 diff --git a/helm/coder/tests/testdata/auto_access_url_2.golden b/helm/coder/tests/testdata/auto_access_url_2.golden index b4234b5925b6f..c7dd0b3c8780b 100644 --- a/helm/coder/tests/testdata/auto_access_url_2.golden +++ b/helm/coder/tests/testdata/auto_access_url_2.golden @@ -84,7 +84,7 @@ metadata: {} spec: type: LoadBalancer - sessionAffinity: ClientIP + sessionAffinity: None ports: - name: "http" port: 80 diff --git a/helm/coder/tests/testdata/auto_access_url_3.golden b/helm/coder/tests/testdata/auto_access_url_3.golden index bbc192d7c46b7..2a07c1e42f050 100644 --- a/helm/coder/tests/testdata/auto_access_url_3.golden +++ b/helm/coder/tests/testdata/auto_access_url_3.golden @@ -84,7 +84,7 @@ metadata: {} spec: type: LoadBalancer - sessionAffinity: ClientIP + sessionAffinity: None ports: - name: "http" port: 80 diff --git a/helm/coder/tests/testdata/command.golden b/helm/coder/tests/testdata/command.golden index 4e88c36d4641d..9897e34382d6c 100644 --- a/helm/coder/tests/testdata/command.golden +++ b/helm/coder/tests/testdata/command.golden @@ -84,7 +84,7 @@ metadata: {} spec: type: LoadBalancer - sessionAffinity: ClientIP + sessionAffinity: None ports: - name: "http" port: 80 diff --git a/helm/coder/tests/testdata/command_args.golden b/helm/coder/tests/testdata/command_args.golden index 9e7a9a01ee27a..126127838b89c 100644 --- a/helm/coder/tests/testdata/command_args.golden +++ b/helm/coder/tests/testdata/command_args.golden @@ -84,7 +84,7 @@ metadata: {} spec: type: LoadBalancer - sessionAffinity: ClientIP + sessionAffinity: None ports: - name: "http" port: 80 diff --git a/helm/coder/tests/testdata/default_values.golden b/helm/coder/tests/testdata/default_values.golden index ed02773c6f7bb..f5d6b2ad2c82f 100644 --- a/helm/coder/tests/testdata/default_values.golden +++ b/helm/coder/tests/testdata/default_values.golden @@ -84,7 +84,7 @@ metadata: {} spec: type: LoadBalancer - sessionAffinity: ClientIP + sessionAffinity: None ports: - name: "http" port: 80 diff --git a/helm/coder/tests/testdata/env_from.golden b/helm/coder/tests/testdata/env_from.golden index 2a4950f6ec588..caef038614e90 100644 --- a/helm/coder/tests/testdata/env_from.golden +++ b/helm/coder/tests/testdata/env_from.golden @@ -84,7 +84,7 @@ metadata: {} spec: type: LoadBalancer - sessionAffinity: ClientIP + sessionAffinity: None ports: - name: "http" port: 80 diff --git a/helm/coder/tests/testdata/labels_annotations.golden b/helm/coder/tests/testdata/labels_annotations.golden index 38812ffeab832..c6598737d2410 100644 --- a/helm/coder/tests/testdata/labels_annotations.golden +++ b/helm/coder/tests/testdata/labels_annotations.golden @@ -84,7 +84,7 @@ metadata: {} spec: type: LoadBalancer - sessionAffinity: ClientIP + sessionAffinity: None ports: - name: "http" port: 80 diff --git a/helm/coder/tests/testdata/provisionerd_psk.golden b/helm/coder/tests/testdata/provisionerd_psk.golden index 4dcde1eabe0fc..93f9e817ebc80 100644 --- a/helm/coder/tests/testdata/provisionerd_psk.golden +++ b/helm/coder/tests/testdata/provisionerd_psk.golden @@ -84,7 +84,7 @@ metadata: {} spec: type: LoadBalancer - sessionAffinity: ClientIP + sessionAffinity: None ports: - name: "http" port: 80 diff --git a/helm/coder/tests/testdata/sa.golden b/helm/coder/tests/testdata/sa.golden index cf3b2df693835..386131531bef4 100644 --- a/helm/coder/tests/testdata/sa.golden +++ b/helm/coder/tests/testdata/sa.golden @@ -85,7 +85,7 @@ metadata: {} spec: type: LoadBalancer - sessionAffinity: ClientIP + sessionAffinity: None ports: - name: "http" port: 80 diff --git a/helm/coder/tests/testdata/tls.golden b/helm/coder/tests/testdata/tls.golden index fccbbec0a2aa2..33b1a85b9d56b 100644 --- a/helm/coder/tests/testdata/tls.golden +++ b/helm/coder/tests/testdata/tls.golden @@ -84,7 +84,7 @@ metadata: {} spec: type: LoadBalancer - sessionAffinity: ClientIP + sessionAffinity: None ports: - name: "http" port: 80 diff --git a/helm/coder/tests/testdata/workspace_proxy.golden b/helm/coder/tests/testdata/workspace_proxy.golden index 096b40978aac0..4ac30acbad86b 100644 --- a/helm/coder/tests/testdata/workspace_proxy.golden +++ b/helm/coder/tests/testdata/workspace_proxy.golden @@ -84,7 +84,7 @@ metadata: {} spec: type: LoadBalancer - sessionAffinity: ClientIP + sessionAffinity: None ports: - name: "http" port: 80