From 3addcaf9b2b945507c6c1d9e8c58d2aeb431bfe4 Mon Sep 17 00:00:00 2001 From: Arthur Normand Date: Tue, 15 Nov 2022 21:13:12 -0500 Subject: [PATCH 01/19] Allow hiding password entry, changing OpenID Connect text and OpenID Connect icon --- cli/deployment/config.go | 15 +++ cli/server.go | 4 + cli/testdata/coder_server_--help.golden | 10 ++ coderd/coderd.go | 1 + coderd/userauth.go | 25 ++++- codersdk/deploymentconfig.go | 3 + codersdk/users.go | 23 ++++- site/src/api/typesGenerated.ts | 25 ++++- site/src/components/SignInForm/SignInForm.tsx | 97 ++++++++++--------- 9 files changed, 145 insertions(+), 58 deletions(-) diff --git a/cli/deployment/config.go b/cli/deployment/config.go index f6c8a1555b52d..0dc20b5b995f8 100644 --- a/cli/deployment/config.go +++ b/cli/deployment/config.go @@ -157,6 +157,11 @@ func newConfig() *codersdk.DeploymentConfig { Flag: "postgres-url", Secret: true, }, + PasswordAuthHidden: &codersdk.DeploymentConfigField[bool]{ + Name: "Flag to hide password auth", + Usage: "When this flag is set to true, the user/password form in the UI will be hidden", + Flag: "password-auth-hidden", + }, OAuth2: &codersdk.OAuth2Config{ Github: &codersdk.OAuth2GithubConfig{ ClientID: &codersdk.DeploymentConfigField[string]{ @@ -231,6 +236,16 @@ func newConfig() *codersdk.DeploymentConfig { Flag: "oidc-scopes", Default: []string{oidc.ScopeOpenID, "profile", "email"}, }, + SignInText: &codersdk.DeploymentConfigField[string]{ + Name: "OpenID Connect sign in text", + Usage: "The text to show on the OpenID Connect sign in button", + Flag: "oidc-sign-in-text", + }, + IconURL: &codersdk.DeploymentConfigField[string]{ + Name: "OpenID connect icon URL", + Usage: "URL pointing to the icon to use on the OepnID Connect login button", + Flag: "oidc-icon-url", + }, }, Telemetry: &codersdk.TelemetryConfig{ diff --git a/cli/server.go b/cli/server.go index 4dfd4c5a40da1..a612fe35af027 100644 --- a/cli/server.go +++ b/cli/server.go @@ -370,6 +370,8 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co options.TLSCertificates = tlsConfig.Certificates } + options.PasswordAuthHidden = cfg.PasswordAuthHidden.Value + if cfg.OAuth2.Github.ClientSecret.Value != "" { options.GithubOAuth2Config, err = configureGithubOAuth2(accessURLParsed, cfg.OAuth2.Github.ClientID.Value, @@ -419,6 +421,8 @@ func Server(vip *viper.Viper, newAPI func(context.Context, *coderd.Options) (*co }), EmailDomain: cfg.OIDC.EmailDomain.Value, AllowSignups: cfg.OIDC.AllowSignups.Value, + SignInText: cfg.OIDC.SignInText.Value, + IconURL: cfg.OIDC.IconURL.Value, } } diff --git a/cli/testdata/coder_server_--help.golden b/cli/testdata/coder_server_--help.golden index f609657cc5bdc..33d6d1d19bec2 100644 --- a/cli/testdata/coder_server_--help.golden +++ b/cli/testdata/coder_server_--help.golden @@ -98,12 +98,22 @@ Flags: --oidc-email-domain string Email domain that clients logging in with OIDC must match. Consumes $CODER_OIDC_EMAIL_DOMAIN + --oidc-icon-url string URL pointing to the icon to use on the + OepnID Connect login button + Consumes $CODER_OIDC_ICON_URL --oidc-issuer-url string Issuer URL to use for Login with OIDC. Consumes $CODER_OIDC_ISSUER_URL --oidc-scopes strings Scopes to grant when authenticating with OIDC. Consumes $CODER_OIDC_SCOPES (default [openid,profile,email]) + --oidc-sign-in-text string The text to show on the OpenID Connect + sign in button + Consumes $CODER_OIDC_SIGN_IN_TEXT + --password-auth-hidden When this flag is set to true, the + user/password form in the UI will be + hidden + Consumes $CODER_PASSWORD_AUTH_HIDDEN --postgres-url string URL of a PostgreSQL database. If empty, PostgreSQL binaries will be downloaded from Maven diff --git a/coderd/coderd.go b/coderd/coderd.go index d695bb508db47..573c5698b7c74 100644 --- a/coderd/coderd.go +++ b/coderd/coderd.go @@ -76,6 +76,7 @@ type Options struct { Authorizer rbac.Authorizer AzureCertificates x509.VerifyOptions GoogleTokenValidator *idtoken.Validator + PasswordAuthHidden bool GithubOAuth2Config *GithubOAuth2Config OIDCConfig *OIDCConfig PrometheusRegistry *prometheus.Registry diff --git a/coderd/userauth.go b/coderd/userauth.go index deffdca9c3b42..d1575d7d005ec 100644 --- a/coderd/userauth.go +++ b/coderd/userauth.go @@ -44,10 +44,27 @@ type GithubOAuth2Config struct { } func (api *API) userAuthMethods(rw http.ResponseWriter, r *http.Request) { + var signInText string + var iconURL string + + if api.OIDCConfig != nil { + signInText = api.OIDCConfig.SignInText + } + if api.OIDCConfig != nil { + iconURL = api.OIDCConfig.IconURL + } + httpapi.Write(r.Context(), rw, http.StatusOK, codersdk.AuthMethods{ - Password: true, - Github: api.GithubOAuth2Config != nil, - OIDC: api.OIDCConfig != nil, + Password: codersdk.PasswordMethod{ + AuthMethod: codersdk.AuthMethod{Enabled: true}, + Hidden: api.PasswordAuthHidden, + }, + Github: codersdk.AuthMethod{Enabled: api.GithubOAuth2Config != nil}, + OIDC: codersdk.OIDCMethod{ + AuthMethod: codersdk.AuthMethod{Enabled: api.OIDCConfig != nil}, + SignInText: signInText, + IconURL: iconURL, + }, }) } @@ -195,6 +212,8 @@ type OIDCConfig struct { // EmailDomain is the domain to enforce when a user authenticates. EmailDomain string AllowSignups bool + SignInText string + IconURL string } func (api *API) userOIDC(rw http.ResponseWriter, r *http.Request) { diff --git a/codersdk/deploymentconfig.go b/codersdk/deploymentconfig.go index 494aff391cbf7..f48e528609cc0 100644 --- a/codersdk/deploymentconfig.go +++ b/codersdk/deploymentconfig.go @@ -24,6 +24,7 @@ type DeploymentConfig struct { CacheDirectory *DeploymentConfigField[string] `json:"cache_directory" typescript:",notnull"` InMemoryDatabase *DeploymentConfigField[bool] `json:"in_memory_database" typescript:",notnull"` PostgresURL *DeploymentConfigField[string] `json:"pg_connection_url" typescript:",notnull"` + PasswordAuthHidden *DeploymentConfigField[bool] `json:"password_auth_hidden" typescript:",notnull"` OAuth2 *OAuth2Config `json:"oauth2" typescript:",notnull"` OIDC *OIDCConfig `json:"oidc" typescript:",notnull"` Telemetry *TelemetryConfig `json:"telemetry" typescript:",notnull"` @@ -92,6 +93,8 @@ type OIDCConfig struct { EmailDomain *DeploymentConfigField[string] `json:"email_domain" typescript:",notnull"` IssuerURL *DeploymentConfigField[string] `json:"issuer_url" typescript:",notnull"` Scopes *DeploymentConfigField[[]string] `json:"scopes" typescript:",notnull"` + SignInText *DeploymentConfigField[string] `json:"sign_in_text" typescript:",notnull"` + IconURL *DeploymentConfigField[string] `json:"icon_url" typescript:",notnull"` } type TelemetryConfig struct { diff --git a/codersdk/users.go b/codersdk/users.go index d1ea338410826..c99bf9c958570 100644 --- a/codersdk/users.go +++ b/codersdk/users.go @@ -105,11 +105,26 @@ type CreateOrganizationRequest struct { Name string `json:"name" validate:"required,username"` } -// AuthMethods contains whether authentication types are enabled or not. +// AuthMethods contains authentication method information like whether they are enabled or not or hidden or not, etc. type AuthMethods struct { - Password bool `json:"password"` - Github bool `json:"github"` - OIDC bool `json:"oidc"` + Password PasswordMethod `json:"password"` + Github AuthMethod `json:"github"` + OIDC OIDCMethod `json:"oidc"` +} + +type AuthMethod struct { + Enabled bool `json:"enabled"` +} + +type PasswordMethod struct { + AuthMethod + Hidden bool `json:"hidden"` +} + +type OIDCMethod struct { + AuthMethod + SignInText string `json:"signInText"` + IconURL string `json:"iconUrl"` } // HasFirstUser returns whether the first user has been created. diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 42213934c88d8..fd2895b84db4f 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -90,11 +90,16 @@ export interface AuditLogsRequest extends Pagination { readonly q?: string } +// From codersdk/users.go +export interface AuthMethod { + readonly enabled: boolean +} + // From codersdk/users.go export interface AuthMethods { - readonly password: boolean - readonly github: boolean - readonly oidc: boolean + readonly password: PasswordMethod + readonly github: AuthMethod + readonly oidc: OIDCMethod } // From codersdk/authorization.go @@ -289,6 +294,7 @@ export interface DeploymentConfig { readonly cache_directory: DeploymentConfigField readonly in_memory_database: DeploymentConfigField readonly pg_connection_url: DeploymentConfigField + readonly password_auth_hidden: DeploymentConfigField readonly oauth2: OAuth2Config readonly oidc: OIDCConfig readonly telemetry: TelemetryConfig @@ -446,6 +452,14 @@ export interface OIDCConfig { readonly email_domain: DeploymentConfigField readonly issuer_url: DeploymentConfigField readonly scopes: DeploymentConfigField + readonly sign_in_text: DeploymentConfigField + readonly icon_url: DeploymentConfigField +} + +// From codersdk/users.go +export interface OIDCMethod extends AuthMethod { + readonly signInText: string + readonly iconUrl: string } // From codersdk/organizations.go @@ -505,6 +519,11 @@ export interface ParameterSchema { readonly validation_contains?: string[] } +// From codersdk/users.go +export interface PasswordMethod extends AuthMethod { + readonly hidden: boolean +} + // From codersdk/groups.go export interface PatchGroupRequest { readonly add_users: string[] diff --git a/site/src/components/SignInForm/SignInForm.tsx b/site/src/components/SignInForm/SignInForm.tsx index f55358375bef6..407e02b176955 100644 --- a/site/src/components/SignInForm/SignInForm.tsx +++ b/site/src/components/SignInForm/SignInForm.tsx @@ -130,8 +130,8 @@ export const SignInForm: FC> = ({ return ( <> - -
+ + {!authMethods?.password.hidden && ( {Object.keys(loginErrors).map( (errorKey: string) => @@ -174,55 +174,56 @@ export const SignInForm: FC> = ({ - - {(authMethods?.github || authMethods?.oidc) && ( - <> -
-
-
Or
-
-
- - - {authMethods.github && ( - )} + {(!authMethods?.password.hidden && (authMethods?.github.enabled || authMethods?.oidc.enabled)) && ( +
+
+
Or
+
+
+ )} + {(authMethods?.github.enabled || authMethods?.oidc.enabled) && ( + + {authMethods.github.enabled && ( + + - - )} + {Language.githubSignIn} + + + )} - {authMethods.oidc && ( - + - - )} - - + {authMethods.oidc.signInText || Language.oidcSignIn} + + + )} + )} ) From 40bc156b3961ebab5de4f8c0d319420d6ebcc059 Mon Sep 17 00:00:00 2001 From: Arthur Normand Date: Tue, 15 Nov 2022 21:32:01 -0500 Subject: [PATCH 02/19] Docs --- docs/admin/auth.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/admin/auth.md b/docs/admin/auth.md index 877ef1d8af929..add02494990bb 100644 --- a/docs/admin/auth.md +++ b/docs/admin/auth.md @@ -4,6 +4,10 @@ By default, Coder is accessible via password authentication. The following steps explain how to set up GitHub OAuth or OpenID Connect. +If after configuring another authentication method you'd like to hide password authentication, you can configure that like so: +```console +CODER_PASSWORD_AUTH_HIDDEN=true +``` ## GitHub ### Step 1: Configure the OAuth application in GitHub @@ -81,6 +85,12 @@ CODER_TLS_CLIENT_CERT_FILE=/path/to/cert.pem CODER_TLS_CLIENT_KEY_FILE=/path/to/key.pem ``` +If you'd like to change the OpenID Connect button text and/or icon, you can configure them like so: +```console +CODER_OIDC_SIGN_IN_TEXT="Sign in with Gitea" +CODER_OIDC_ICON_URL=https://gitea.io/images/gitea.png +``` + ## SCIM (enterprise) Coder supports user provisioning and deprovisioning via SCIM 2.0 with header From 0f4a40e91f8c58e5a3c97bc5f4d27a7cff15255c Mon Sep 17 00:00:00 2001 From: Arthur Normand Date: Tue, 15 Nov 2022 21:46:30 -0500 Subject: [PATCH 03/19] Cleaning --- site/src/components/SignInForm/SignInForm.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/site/src/components/SignInForm/SignInForm.tsx b/site/src/components/SignInForm/SignInForm.tsx index 407e02b176955..cd2127bf4af37 100644 --- a/site/src/components/SignInForm/SignInForm.tsx +++ b/site/src/components/SignInForm/SignInForm.tsx @@ -130,7 +130,7 @@ export const SignInForm: FC> = ({ return ( <> - + {!authMethods?.password.hidden && (
{Object.keys(loginErrors).map( From 90d900c6813d3ed43c704d577ba60d4bcc89d0f8 Mon Sep 17 00:00:00 2001 From: Arthur Normand Date: Tue, 15 Nov 2022 22:05:00 -0500 Subject: [PATCH 04/19] Fix Prettier and Go test and TS compile error --- coderd/userauth_test.go | 8 +- site/src/components/SignInForm/SignInForm.tsx | 116 ++++++++++-------- site/src/testHelpers/entities.ts | 6 +- 3 files changed, 71 insertions(+), 59 deletions(-) diff --git a/coderd/userauth_test.go b/coderd/userauth_test.go index 04abffedaa850..289f1a63268f1 100644 --- a/coderd/userauth_test.go +++ b/coderd/userauth_test.go @@ -77,8 +77,8 @@ func TestUserAuthMethods(t *testing.T) { methods, err := client.AuthMethods(ctx) require.NoError(t, err) - require.True(t, methods.Password) - require.False(t, methods.Github) + require.True(t, methods.Password.Enabled) + require.False(t, methods.Github.Enabled) }) t.Run("Github", func(t *testing.T) { t.Parallel() @@ -91,8 +91,8 @@ func TestUserAuthMethods(t *testing.T) { methods, err := client.AuthMethods(ctx) require.NoError(t, err) - require.True(t, methods.Password) - require.True(t, methods.Github) + require.True(t, methods.Password.Enabled) + require.True(t, methods.Github.Enabled) }) } diff --git a/site/src/components/SignInForm/SignInForm.tsx b/site/src/components/SignInForm/SignInForm.tsx index cd2127bf4af37..152704c1ca0cd 100644 --- a/site/src/components/SignInForm/SignInForm.tsx +++ b/site/src/components/SignInForm/SignInForm.tsx @@ -131,57 +131,60 @@ export const SignInForm: FC> = ({ return ( <> - {!authMethods?.password.hidden && ( - - {Object.keys(loginErrors).map( - (errorKey: string) => - Boolean(loginErrors[errorKey as LoginErrors]) && ( - - ), - )} - - -
- + + {Object.keys(loginErrors).map( + (errorKey: string) => + Boolean(loginErrors[errorKey as LoginErrors]) && ( + + ), + )} + - {isLoading ? "" : Language.passwordSignIn} - -
-
- )} - {(!authMethods?.password.hidden && (authMethods?.github.enabled || authMethods?.oidc.enabled)) && ( -
-
-
Or
-
-
+ label={Language.emailLabel} + type="email" + variant="outlined" + /> + +
+ + {isLoading ? "" : Language.passwordSignIn} + +
+ + )} + {!authMethods?.password.hidden && + (authMethods?.github.enabled || authMethods?.oidc.enabled) && ( +
+
+
Or
+
+
+ )} {(authMethods?.github.enabled || authMethods?.oidc.enabled) && ( {authMethods.github.enabled && ( @@ -211,9 +214,18 @@ export const SignInForm: FC> = ({ )}`} > + + )} + + {authMethods?.oidc.enabled && ( + + + + )} + + ) +} diff --git a/site/src/components/SignInForm/PasswordSignInForm.tsx b/site/src/components/SignInForm/PasswordSignInForm.tsx new file mode 100644 index 0000000000000..ba6606f26da21 --- /dev/null +++ b/site/src/components/SignInForm/PasswordSignInForm.tsx @@ -0,0 +1,99 @@ +import { Stack } from "../Stack/Stack" +import { AlertBanner } from "../AlertBanner/AlertBanner" +import TextField from "@material-ui/core/TextField" +import { getFormHelpers, onChangeTrimmed } from "../../util/formUtils" +import { LoadingButton } from "../LoadingButton/LoadingButton" +import { Language, LoginErrors } from "./SignInForm" +import { FormikContextType, FormikTouched, useFormik } from "formik" +import * as Yup from "yup" +import { FC } from "react" +import { BuiltInAuthFormValues } from "./SignInForm.types" + +type PasswordSignInFormProps = { + loginErrors: Partial> + onSubmit: (credentials: { email: string; password: string }) => void + initialTouched?: FormikTouched + isLoading: boolean +} + +export const PasswordSignInForm: FC = ({ + loginErrors, + onSubmit, + initialTouched, + isLoading, +}) => { + const validationSchema = Yup.object({ + email: Yup.string() + .trim() + .email(Language.emailInvalid) + .required(Language.emailRequired), + password: Yup.string(), + }) + + const form: FormikContextType = + useFormik({ + initialValues: { + email: "", + password: "", + }, + validationSchema, + // The email field has an autoFocus, but users may log in with a button click. + // This is set to `false` in order to keep the autoFocus, validateOnChange + // and Formik experience friendly. Validation will kick in onChange (any + // field), or after a submission attempt. + validateOnBlur: false, + onSubmit, + initialTouched, + }) + const getFieldHelpers = getFormHelpers( + form, + loginErrors.authError, + ) + + return ( +
+ + {Object.keys(loginErrors).map( + (errorKey: string) => + Boolean(loginErrors[errorKey as LoginErrors]) && ( + + ), + )} + + +
+ + {isLoading ? "" : Language.passwordSignIn} + +
+
+
+ ) +} diff --git a/site/src/components/SignInForm/SignInForm.tsx b/site/src/components/SignInForm/SignInForm.tsx index b8414722af376..d900372002747 100644 --- a/site/src/components/SignInForm/SignInForm.tsx +++ b/site/src/components/SignInForm/SignInForm.tsx @@ -1,30 +1,13 @@ -import Box from "@material-ui/core/Box" -import Button from "@material-ui/core/Button" -import Link from "@material-ui/core/Link" import { makeStyles } from "@material-ui/core/styles" import Typography from "@material-ui/core/Typography" -import TextField from "@material-ui/core/TextField" -import GitHubIcon from "@material-ui/icons/GitHub" -import KeyIcon from "@material-ui/icons/VpnKey" -import { Stack } from "components/Stack/Stack" -import { FormikContextType, FormikTouched, useFormik } from "formik" +import { FormikTouched } from "formik" import { FC, useState } from "react" -import * as Yup from "yup" import { AuthMethods } from "../../api/typesGenerated" -import { getFormHelpers, onChangeTrimmed } from "../../util/formUtils" -import { LoadingButton } from "./../LoadingButton/LoadingButton" -import { AlertBanner } from "components/AlertBanner/AlertBanner" import { useTranslation } from "react-i18next" - -/** - * BuiltInAuthFormValues describes a form using built-in (email/password) - * authentication. This form may not always be present depending on external - * auth providers available and administrative configurations - */ -interface BuiltInAuthFormValues { - email: string - password: string -} +import { Maybe } from "../Conditionals/Maybe" +import { PasswordSignInForm } from "./PasswordSignInForm" +import { OAuthSignInForm } from "./OAuthSignInForm" +import { BuiltInAuthFormValues } from "./SignInForm.types" export enum LoginErrors { AUTH_ERROR = "authError", @@ -49,14 +32,6 @@ export const Language = { oidcSignIn: "OpenID Connect", } -const validationSchema = Yup.object({ - email: Yup.string() - .trim() - .email(Language.emailInvalid) - .required(Language.emailRequired), - password: Yup.string(), -}) - const useStyles = makeStyles((theme) => ({ root: { width: "100%", @@ -72,10 +47,6 @@ const useStyles = makeStyles((theme) => ({ fontWeight: 600, }, }, - buttonIcon: { - width: 14, - height: 14, - }, divider: { paddingTop: theme.spacing(3), paddingBottom: theme.spacing(3), @@ -121,32 +92,14 @@ export const SignInForm: FC> = ({ onSubmit, initialTouched, }) => { - const nonPasswordAuthEnabled = - authMethods?.github.enabled || authMethods?.oidc.enabled - - const [showPasswordAuth, setShowPasswordAuth] = useState( - !nonPasswordAuthEnabled, + const oAuthEnabled = Boolean( + authMethods?.github.enabled || authMethods?.oidc.enabled, ) + + // Hide password auth by default if any OAuth method is enabled + const [showPasswordAuth, setShowPasswordAuth] = useState(!oAuthEnabled) const styles = useStyles() - const form: FormikContextType = - useFormik({ - initialValues: { - email: "", - password: "", - }, - validationSchema, - // The email field has an autoFocus, but users may login with a button click. - // This is set to `false` in order to keep the autoFocus, validateOnChange - // and Formik experience friendly. Validation will kick in onChange (any - // field), or after a submission attempt. - validateOnBlur: false, - onSubmit, - initialTouched, - }) - const getFieldHelpers = getFormHelpers( - form, - loginErrors.authError, - ) + const commonTranslation = useTranslation("common") const loginPageTranslation = useTranslation("loginPage") @@ -156,119 +109,36 @@ export const SignInForm: FC> = ({ {loginPageTranslation.t("signInTo")}{" "} {commonTranslation.t("coder")} - {showPasswordAuth && ( -
- - {Object.keys(loginErrors).map( - (errorKey: string) => - Boolean(loginErrors[errorKey as LoginErrors]) && ( - - ), - )} - - -
- - {isLoading ? "" : Language.passwordSignIn} - -
-
-
- )} - {showPasswordAuth && nonPasswordAuthEnabled && ( + + + +
Or
- )} - {nonPasswordAuthEnabled && ( - - {authMethods.github.enabled && ( - - - - )} - - {authMethods.oidc.enabled && ( - - - - )} - - )} - {!showPasswordAuth && ( + + + + + setShowPasswordAuth(true)} > - Show password login + {loginPageTranslation.t("showPassword")} - )} +
) } diff --git a/site/src/components/SignInForm/SignInForm.types.ts b/site/src/components/SignInForm/SignInForm.types.ts new file mode 100644 index 0000000000000..8965458bd8953 --- /dev/null +++ b/site/src/components/SignInForm/SignInForm.types.ts @@ -0,0 +1,9 @@ +/** + * BuiltInAuthFormValues describes a form using built-in (email/password) + * authentication. This form may not always be present depending on external + * auth providers available and administrative configurations + */ +export interface BuiltInAuthFormValues { + email: string + password: string +} diff --git a/site/src/i18n/en/loginPage.json b/site/src/i18n/en/loginPage.json index 329dc925a2e8e..187f6a4d141d6 100644 --- a/site/src/i18n/en/loginPage.json +++ b/site/src/i18n/en/loginPage.json @@ -1,3 +1,4 @@ { - "signInTo": "Sign in to" + "signInTo": "Sign in to", + "showPassword": "Show password login" } diff --git a/site/src/pages/LoginPage/LoginPage.test.tsx b/site/src/pages/LoginPage/LoginPage.test.tsx index b5eb6e4b41c6f..930a801af6532 100644 --- a/site/src/pages/LoginPage/LoginPage.test.tsx +++ b/site/src/pages/LoginPage/LoginPage.test.tsx @@ -10,7 +10,7 @@ import { } from "../../testHelpers/renderHelpers" import { server } from "../../testHelpers/server" import { LoginPage } from "./LoginPage" -import * as TypesGen from "../../api/typesGenerated" +import * as TypesGen from "api/typesGenerated" describe("LoginPage", () => { beforeEach(() => { From 1ed7911809be7b88189b51102655abfdc01db1d6 Mon Sep 17 00:00:00 2001 From: Arthur Date: Thu, 19 Jan 2023 23:32:52 -0500 Subject: [PATCH 15/19] Updated golden files --- cli/testdata/coder_server_--help.golden | 1 + 1 file changed, 1 insertion(+) diff --git a/cli/testdata/coder_server_--help.golden b/cli/testdata/coder_server_--help.golden index a473599454dcc..2529c1eb12b61 100644 --- a/cli/testdata/coder_server_--help.golden +++ b/cli/testdata/coder_server_--help.golden @@ -131,6 +131,7 @@ Flags: --oidc-sign-in-text string The text to show on the OpenID Connect sign in button Consumes $CODER_OIDC_SIGN_IN_TEXT + (default "OpenID Connect") --oidc-username-field string OIDC claim field to use as the username. Consumes $CODER_OIDC_USERNAME_FIELD (default "preferred_username") From e31a37e1199c984e578a1069d84ea8b8be378b98 Mon Sep 17 00:00:00 2001 From: Arthur Normand Date: Sun, 22 Jan 2023 21:21:35 -0500 Subject: [PATCH 16/19] Fix auto-genned-files --- coderd/apidoc/docs.go | 4 ++-- coderd/apidoc/swagger.json | 4 ++-- docs/api/schemas.md | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index ff2a06c7e09cf..15eb644388b43 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -5154,7 +5154,7 @@ const docTemplate = `{ "$ref": "#/definitions/codersdk.AuthMethod" }, "oidc": { - "$ref": "#/definitions/codersdk.OIDCMethod" + "$ref": "#/definitions/codersdk.OIDCAuthMethod" }, "password": { "$ref": "#/definitions/codersdk.AuthMethod" @@ -6366,7 +6366,7 @@ const docTemplate = `{ } } }, - "codersdk.OIDCMethod": { + "codersdk.OIDCAuthMethod": { "type": "object", "properties": { "enabled": { diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 23cd982fef5c3..c5123cd27be7a 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -4564,7 +4564,7 @@ "$ref": "#/definitions/codersdk.AuthMethod" }, "oidc": { - "$ref": "#/definitions/codersdk.OIDCMethod" + "$ref": "#/definitions/codersdk.OIDCAuthMethod" }, "password": { "$ref": "#/definitions/codersdk.AuthMethod" @@ -5695,7 +5695,7 @@ } } }, - "codersdk.OIDCMethod": { + "codersdk.OIDCAuthMethod": { "type": "object", "properties": { "enabled": { diff --git a/docs/api/schemas.md b/docs/api/schemas.md index 9fdc3d3970298..8bc1fa681e2ce 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -475,11 +475,11 @@ ### Properties -| Name | Type | Required | Restrictions | Description | -| ---------- | ------------------------------------------ | -------- | ------------ | ----------- | -| `github` | [codersdk.AuthMethod](#codersdkauthmethod) | false | | | -| `oidc` | [codersdk.OIDCMethod](#codersdkoidcmethod) | false | | | -| `password` | [codersdk.AuthMethod](#codersdkauthmethod) | false | | | +| Name | Type | Required | Restrictions | Description | +| ---------- | -------------------------------------------------- | -------- | ------------ | ----------- | +| `github` | [codersdk.AuthMethod](#codersdkauthmethod) | false | | | +| `oidc` | [codersdk.OIDCAuthMethod](#codersdkoidcauthmethod) | false | | | +| `password` | [codersdk.AuthMethod](#codersdkauthmethod) | false | | | ## codersdk.AuthorizationCheck @@ -3105,7 +3105,7 @@ CreateParameterRequest is a structure used to create a new parameter value for a | `sign_in_text` | [codersdk.DeploymentConfigField-string](#codersdkdeploymentconfigfield-string) | false | | | | `username_field` | [codersdk.DeploymentConfigField-string](#codersdkdeploymentconfigfield-string) | false | | | -## codersdk.OIDCMethod +## codersdk.OIDCAuthMethod ```json { From 9207175ed6a51dc8e31d98850cf5a4e94bb975c8 Mon Sep 17 00:00:00 2001 From: Arthur Date: Wed, 25 Jan 2023 23:01:39 -0500 Subject: [PATCH 17/19] make gen -B --- coderd/apidoc/docs.go | 28 ++++++++-------- coderd/apidoc/swagger.json | 28 ++++++++-------- docs/api/schemas.md | 36 ++++++++++----------- provisionerd/proto/provisionerd.pb.go | 9 ++---- provisionerd/proto/provisionerd_drpc.pb.go | 2 +- provisionersdk/proto/provisioner.pb.go | 8 ++--- provisionersdk/proto/provisioner_drpc.pb.go | 2 +- 7 files changed, 53 insertions(+), 60 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 15eb644388b43..8366a86b6d914 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -6331,6 +6331,20 @@ const docTemplate = `{ } } }, + "codersdk.OIDCAuthMethod": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "iconUrl": { + "type": "string" + }, + "signInText": { + "type": "string" + } + } + }, "codersdk.OIDCConfig": { "type": "object", "properties": { @@ -6366,20 +6380,6 @@ const docTemplate = `{ } } }, - "codersdk.OIDCAuthMethod": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean" - }, - "iconUrl": { - "type": "string" - }, - "signInText": { - "type": "string" - } - } - }, "codersdk.Organization": { "type": "object", "required": [ diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index c5123cd27be7a..07a2ca5cd3c32 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -5660,6 +5660,20 @@ } } }, + "codersdk.OIDCAuthMethod": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + }, + "iconUrl": { + "type": "string" + }, + "signInText": { + "type": "string" + } + } + }, "codersdk.OIDCConfig": { "type": "object", "properties": { @@ -5695,20 +5709,6 @@ } } }, - "codersdk.OIDCAuthMethod": { - "type": "object", - "properties": { - "enabled": { - "type": "boolean" - }, - "iconUrl": { - "type": "string" - }, - "signInText": { - "type": "string" - } - } - }, "codersdk.Organization": { "type": "object", "required": ["created_at", "id", "name", "updated_at"], diff --git a/docs/api/schemas.md b/docs/api/schemas.md index 8bc1fa681e2ce..4b7f6c4ee8aef 100644 --- a/docs/api/schemas.md +++ b/docs/api/schemas.md @@ -2973,6 +2973,24 @@ CreateParameterRequest is a structure used to create a new parameter value for a | `client_secret` | [codersdk.DeploymentConfigField-string](#codersdkdeploymentconfigfield-string) | false | | | | `enterprise_base_url` | [codersdk.DeploymentConfigField-string](#codersdkdeploymentconfigfield-string) | false | | | +## codersdk.OIDCAuthMethod + +```json +{ + "enabled": true, + "iconUrl": "string", + "signInText": "string" +} +``` + +### Properties + +| Name | Type | Required | Restrictions | Description | +| ------------ | ------- | -------- | ------------ | ----------- | +| `enabled` | boolean | false | | | +| `iconUrl` | string | false | | | +| `signInText` | string | false | | | + ## codersdk.OIDCConfig ```json @@ -3105,24 +3123,6 @@ CreateParameterRequest is a structure used to create a new parameter value for a | `sign_in_text` | [codersdk.DeploymentConfigField-string](#codersdkdeploymentconfigfield-string) | false | | | | `username_field` | [codersdk.DeploymentConfigField-string](#codersdkdeploymentconfigfield-string) | false | | | -## codersdk.OIDCAuthMethod - -```json -{ - "enabled": true, - "iconUrl": "string", - "signInText": "string" -} -``` - -### Properties - -| Name | Type | Required | Restrictions | Description | -| ------------ | ------- | -------- | ------------ | ----------- | -| `enabled` | boolean | false | | | -| `iconUrl` | string | false | | | -| `signInText` | string | false | | | - ## codersdk.Organization ```json diff --git a/provisionerd/proto/provisionerd.pb.go b/provisionerd/proto/provisionerd.pb.go index ee6f8f9e01cd2..ceb2208df7c15 100644 --- a/provisionerd/proto/provisionerd.pb.go +++ b/provisionerd/proto/provisionerd.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 -// protoc v3.21.5 +// protoc-gen-go v1.28.1 +// protoc v3.19.4 // source: provisionerd/proto/provisionerd.proto package proto @@ -119,7 +119,6 @@ type AcquiredJob struct { UserName string `protobuf:"bytes,4,opt,name=user_name,json=userName,proto3" json:"user_name,omitempty"` TemplateSourceArchive []byte `protobuf:"bytes,5,opt,name=template_source_archive,json=templateSourceArchive,proto3" json:"template_source_archive,omitempty"` // Types that are assignable to Type: - // // *AcquiredJob_WorkspaceBuild_ // *AcquiredJob_TemplateImport_ // *AcquiredJob_TemplateDryRun_ @@ -251,7 +250,6 @@ type FailedJob struct { JobId string `protobuf:"bytes,1,opt,name=job_id,json=jobId,proto3" json:"job_id,omitempty"` Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` // Types that are assignable to Type: - // // *FailedJob_WorkspaceBuild_ // *FailedJob_TemplateImport_ // *FailedJob_TemplateDryRun_ @@ -362,7 +360,6 @@ type CompletedJob struct { JobId string `protobuf:"bytes,1,opt,name=job_id,json=jobId,proto3" json:"job_id,omitempty"` // Types that are assignable to Type: - // // *CompletedJob_WorkspaceBuild_ // *CompletedJob_TemplateImport_ // *CompletedJob_TemplateDryRun_ @@ -514,7 +511,7 @@ func (x *Log) GetLevel() proto.LogLevel { if x != nil { return x.Level } - return proto.LogLevel_TRACE + return proto.LogLevel(0) } func (x *Log) GetCreatedAt() int64 { diff --git a/provisionerd/proto/provisionerd_drpc.pb.go b/provisionerd/proto/provisionerd_drpc.pb.go index 6d73176475490..058af595809b8 100644 --- a/provisionerd/proto/provisionerd_drpc.pb.go +++ b/provisionerd/proto/provisionerd_drpc.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-drpc. DO NOT EDIT. -// protoc-gen-go-drpc version: v0.0.26 +// protoc-gen-go-drpc version: (devel) // source: provisionerd/proto/provisionerd.proto package proto diff --git a/provisionersdk/proto/provisioner.pb.go b/provisionersdk/proto/provisioner.pb.go index d968dbf510e0f..0742cf54cf993 100644 --- a/provisionersdk/proto/provisioner.pb.go +++ b/provisionersdk/proto/provisioner.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.26.0 -// protoc v3.21.5 +// protoc-gen-go v1.28.1 +// protoc v3.19.4 // source: provisionersdk/proto/provisioner.proto package proto @@ -762,7 +762,6 @@ type Agent struct { Directory string `protobuf:"bytes,7,opt,name=directory,proto3" json:"directory,omitempty"` Apps []*App `protobuf:"bytes,8,rep,name=apps,proto3" json:"apps,omitempty"` // Types that are assignable to Auth: - // // *Agent_Token // *Agent_InstanceId Auth isAgent_Auth `protobuf_oneof:"auth"` @@ -1449,7 +1448,6 @@ type Parse_Response struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Type: - // // *Parse_Response_Log // *Parse_Response_Complete Type isParse_Response_Type `protobuf_oneof:"type"` @@ -1838,7 +1836,6 @@ type Provision_Request struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Type: - // // *Provision_Request_Plan // *Provision_Request_Apply // *Provision_Request_Cancel @@ -2004,7 +2001,6 @@ type Provision_Response struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Type: - // // *Provision_Response_Log // *Provision_Response_Complete Type isProvision_Response_Type `protobuf_oneof:"type"` diff --git a/provisionersdk/proto/provisioner_drpc.pb.go b/provisionersdk/proto/provisioner_drpc.pb.go index c990f6f645b7f..d307402447c78 100644 --- a/provisionersdk/proto/provisioner_drpc.pb.go +++ b/provisionersdk/proto/provisioner_drpc.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-drpc. DO NOT EDIT. -// protoc-gen-go-drpc version: v0.0.26 +// protoc-gen-go-drpc version: (devel) // source: provisionersdk/proto/provisioner.proto package proto From 201d424e40f965cde1c9221d85611b8902126901 Mon Sep 17 00:00:00 2001 From: Arthur Date: Wed, 25 Jan 2023 23:13:20 -0500 Subject: [PATCH 18/19] Revert provisioner files? --- provisionerd/proto/provisionerd.pb.go | 9 ++++++--- provisionerd/proto/provisionerd_drpc.pb.go | 2 +- provisionersdk/proto/provisioner.pb.go | 8 ++++++-- provisionersdk/proto/provisioner_drpc.pb.go | 2 +- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/provisionerd/proto/provisionerd.pb.go b/provisionerd/proto/provisionerd.pb.go index ceb2208df7c15..ee6f8f9e01cd2 100644 --- a/provisionerd/proto/provisionerd.pb.go +++ b/provisionerd/proto/provisionerd.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 -// protoc v3.19.4 +// protoc-gen-go v1.26.0 +// protoc v3.21.5 // source: provisionerd/proto/provisionerd.proto package proto @@ -119,6 +119,7 @@ type AcquiredJob struct { UserName string `protobuf:"bytes,4,opt,name=user_name,json=userName,proto3" json:"user_name,omitempty"` TemplateSourceArchive []byte `protobuf:"bytes,5,opt,name=template_source_archive,json=templateSourceArchive,proto3" json:"template_source_archive,omitempty"` // Types that are assignable to Type: + // // *AcquiredJob_WorkspaceBuild_ // *AcquiredJob_TemplateImport_ // *AcquiredJob_TemplateDryRun_ @@ -250,6 +251,7 @@ type FailedJob struct { JobId string `protobuf:"bytes,1,opt,name=job_id,json=jobId,proto3" json:"job_id,omitempty"` Error string `protobuf:"bytes,2,opt,name=error,proto3" json:"error,omitempty"` // Types that are assignable to Type: + // // *FailedJob_WorkspaceBuild_ // *FailedJob_TemplateImport_ // *FailedJob_TemplateDryRun_ @@ -360,6 +362,7 @@ type CompletedJob struct { JobId string `protobuf:"bytes,1,opt,name=job_id,json=jobId,proto3" json:"job_id,omitempty"` // Types that are assignable to Type: + // // *CompletedJob_WorkspaceBuild_ // *CompletedJob_TemplateImport_ // *CompletedJob_TemplateDryRun_ @@ -511,7 +514,7 @@ func (x *Log) GetLevel() proto.LogLevel { if x != nil { return x.Level } - return proto.LogLevel(0) + return proto.LogLevel_TRACE } func (x *Log) GetCreatedAt() int64 { diff --git a/provisionerd/proto/provisionerd_drpc.pb.go b/provisionerd/proto/provisionerd_drpc.pb.go index 058af595809b8..6d73176475490 100644 --- a/provisionerd/proto/provisionerd_drpc.pb.go +++ b/provisionerd/proto/provisionerd_drpc.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-drpc. DO NOT EDIT. -// protoc-gen-go-drpc version: (devel) +// protoc-gen-go-drpc version: v0.0.26 // source: provisionerd/proto/provisionerd.proto package proto diff --git a/provisionersdk/proto/provisioner.pb.go b/provisionersdk/proto/provisioner.pb.go index 0742cf54cf993..d968dbf510e0f 100644 --- a/provisionersdk/proto/provisioner.pb.go +++ b/provisionersdk/proto/provisioner.pb.go @@ -1,7 +1,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.28.1 -// protoc v3.19.4 +// protoc-gen-go v1.26.0 +// protoc v3.21.5 // source: provisionersdk/proto/provisioner.proto package proto @@ -762,6 +762,7 @@ type Agent struct { Directory string `protobuf:"bytes,7,opt,name=directory,proto3" json:"directory,omitempty"` Apps []*App `protobuf:"bytes,8,rep,name=apps,proto3" json:"apps,omitempty"` // Types that are assignable to Auth: + // // *Agent_Token // *Agent_InstanceId Auth isAgent_Auth `protobuf_oneof:"auth"` @@ -1448,6 +1449,7 @@ type Parse_Response struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Type: + // // *Parse_Response_Log // *Parse_Response_Complete Type isParse_Response_Type `protobuf_oneof:"type"` @@ -1836,6 +1838,7 @@ type Provision_Request struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Type: + // // *Provision_Request_Plan // *Provision_Request_Apply // *Provision_Request_Cancel @@ -2001,6 +2004,7 @@ type Provision_Response struct { unknownFields protoimpl.UnknownFields // Types that are assignable to Type: + // // *Provision_Response_Log // *Provision_Response_Complete Type isProvision_Response_Type `protobuf_oneof:"type"` diff --git a/provisionersdk/proto/provisioner_drpc.pb.go b/provisionersdk/proto/provisioner_drpc.pb.go index d307402447c78..c990f6f645b7f 100644 --- a/provisionersdk/proto/provisioner_drpc.pb.go +++ b/provisionersdk/proto/provisioner_drpc.pb.go @@ -1,5 +1,5 @@ // Code generated by protoc-gen-go-drpc. DO NOT EDIT. -// protoc-gen-go-drpc version: (devel) +// protoc-gen-go-drpc version: v0.0.26 // source: provisionersdk/proto/provisioner.proto package proto From 7ce525e41628467da6149ff4731d2e9a04d96af0 Mon Sep 17 00:00:00 2001 From: Arthur Normand Date: Mon, 30 Jan 2023 00:39:00 -0500 Subject: [PATCH 19/19] Fix lint error --- site/src/pages/LoginPage/LoginPage.test.tsx | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/site/src/pages/LoginPage/LoginPage.test.tsx b/site/src/pages/LoginPage/LoginPage.test.tsx index 930a801af6532..f272f9198c5ac 100644 --- a/site/src/pages/LoginPage/LoginPage.test.tsx +++ b/site/src/pages/LoginPage/LoginPage.test.tsx @@ -98,9 +98,7 @@ describe("LoginPage", () => { render() // Then - expect( - await screen.queryByText(Language.passwordSignIn), - ).not.toBeInTheDocument() + expect(screen.queryByText(Language.passwordSignIn)).not.toBeInTheDocument() await screen.findByText(Language.githubSignIn) }) @@ -142,9 +140,7 @@ describe("LoginPage", () => { render() // Then - expect( - await screen.queryByText(Language.passwordSignIn), - ).not.toBeInTheDocument() + expect(screen.queryByText(Language.passwordSignIn)).not.toBeInTheDocument() await screen.findByText(Language.githubSignIn) const showPasswordAuthLink = screen.getByText("Show password login")