diff --git a/shared/studio/tabs/auth/authAdmin.module.scss b/shared/studio/tabs/auth/authAdmin.module.scss
index c4e5ca6b..e00e2aed 100644
--- a/shared/studio/tabs/auth/authAdmin.module.scss
+++ b/shared/studio/tabs/auth/authAdmin.module.scss
@@ -258,6 +258,32 @@
}
}
+.checkbox {
+ display: flex;
+ padding: 7px;
+ margin: 0 -7px;
+ cursor: pointer;
+
+ input {
+ appearance: none;
+ width: 20px;
+ height: 20px;
+ margin: 0;
+ outline: 0;
+ border: 2px solid #9a9a9a;
+ border-radius: 4px;
+ background: transparent no-repeat center center;
+ box-sizing: border-box;
+ cursor: pointer;
+
+ &:checked {
+ background-color: #1f8aed;
+ border: none;
+ background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14'%3E%3Cpath fill='%23fff' d='M0,8 5,13 14,4 12,2 5,9 2,6z'/%3E%3C/svg%3E");
+ }
+ }
+}
+
.providersList {
display: flex;
flex-direction: column;
@@ -368,6 +394,13 @@
@include hideScrollbar;
}
+ .providerConfigValue {
+ span {
+ opacity: 0.7;
+ font-style: italic;
+ }
+ }
+
@include darkTheme {
background-color: #2f2f2f;
diff --git a/shared/studio/tabs/auth/index.tsx b/shared/studio/tabs/auth/index.tsx
index f23a2faa..bf19fdea 100644
--- a/shared/studio/tabs/auth/index.tsx
+++ b/shared/studio/tabs/auth/index.tsx
@@ -19,6 +19,7 @@ import {
DraftUIConfig,
ProviderKind,
OAuthProviderData,
+ LocalEmailPasswordProviderData,
} from "./state";
import {useTabState} from "../../state";
import {encodeB64} from "edgedb/dist/primitives/buffer";
@@ -268,7 +269,26 @@ const UIConfigForm = observer(function UIConfig({
/>
- The url to redirect to after successful login.
+ The url to redirect to after successful sign in.
+
+
+
+
+
+
redirect_to_on_signup
+
+
+
+ draft.setConfigValue("redirect_to_on_signup", val)
+ }
+ />
+
+
+ The url to redirect to after a new user signs up. If not set,
+ 'redirect_to' will be used instead.
@@ -573,7 +593,44 @@ const DraftProviderConfigForm = observer(function DraftProviderConfigForm({
+
+
additional_scope
+
+
+ draftState.setAdditionalScope(val)}
+ />
+
+
+ Space-separated list of scopes to be included in the
+ authorize request to the OAuth provider.
+
+
+
>
+ ) : providerKind === "Local" ? (
+
+
require_verification
+
+
+
+
+
+ Whether the email needs to be verified before the user is
+ allowed to sign in.
+
+
+
) : null}
@@ -612,7 +669,7 @@ function ProviderCard({provider}: {provider: AuthProviderData}) {
setExpanded(!expanded)}
>
@@ -636,15 +693,39 @@ function ProviderCard({provider}: {provider: AuthProviderData}) {
}}
/>
- {expanded && kind === "OAuth" ? (
+ {expanded ? (
-
client_id
-
- {(provider as OAuthProviderData).client_id}
-
+ {kind === "OAuth" ? (
+ <>
+
client_id
+
+ {(provider as OAuthProviderData).client_id}
+
+
+
secret
+
+ {secretPlaceholder}
+
-
secret
-
{secretPlaceholder}
+
additional_scope
+
+ {(provider as OAuthProviderData).additional_scope || (
+ none
+ )}
+
+ >
+ ) : kind === "Local" ? (
+ <>
+
+ require_verification
+
+
+ {(
+ provider as LocalEmailPasswordProviderData
+ ).require_verification.toString()}
+
+ >
+ ) : null}
) : null}
diff --git a/shared/studio/tabs/auth/state/index.tsx b/shared/studio/tabs/auth/state/index.tsx
index 8ef8479e..eb30e375 100644
--- a/shared/studio/tabs/auth/state/index.tsx
+++ b/shared/studio/tabs/auth/state/index.tsx
@@ -25,13 +25,20 @@ export type OAuthProviderData = {
| "ext::auth::GitHubOAuthProvider"
| "ext::auth::GoogleOAuthProvider";
client_id: string;
+ additional_scope: string;
+};
+export type LocalEmailPasswordProviderData = {
+ name: string;
+ _typename: "ext::auth::EmailPasswordProviderConfig";
+ require_verification: boolean;
};
export type AuthProviderData =
| OAuthProviderData
- | {name: string; _typename: "ext::auth::EmailPasswordProviderConfig"};
+ | LocalEmailPasswordProviderData;
export interface AuthUIConfigData {
redirect_to: string;
+ redirect_to_on_signup: string;
app_name: string | null;
logo_url: string | null;
dark_logo_url: string | null;
@@ -187,9 +194,12 @@ export class AuthAdminState extends Model({
_typename := .__type__.name,
name,
[is OAuthProviderConfig].client_id,
+ [is OAuthProviderConfig].additional_scope,
+ [is EmailPasswordProviderConfig].require_verification,
},
ui: {
redirect_to,
+ redirect_to_on_signup,
app_name,
logo_url,
dark_logo_url,
@@ -221,6 +231,7 @@ export class AuthAdminState extends Model({
@model("AdminDraftUIConfig")
export class DraftUIConfig extends Model({
_redirect_to: prop(null),
+ _redirect_to_on_signup: prop(null),
_app_name: prop(null),
_logo_url: prop(null),
_dark_logo_url: prop(null),
@@ -257,6 +268,7 @@ export class DraftUIConfig extends Model({
get formChanged() {
return (
this._redirect_to != null ||
+ this._redirect_to_on_signup != null ||
this._app_name != null ||
this._logo_url != null ||
this._dark_logo_url != null ||
@@ -267,6 +279,7 @@ export class DraftUIConfig extends Model({
@modelAction
clearForm() {
this._redirect_to = null;
+ this._redirect_to_on_signup = null;
this._app_name = null;
this._logo_url = null;
this._dark_logo_url = null;
@@ -298,7 +311,13 @@ export class DraftUIConfig extends Model({
this.getConfigValue("redirect_to")
)},
${(
- ["app_name", "logo_url", "dark_logo_url", "brand_color"] as const
+ [
+ "redirect_to_on_signup",
+ "app_name",
+ "logo_url",
+ "dark_logo_url",
+ "brand_color",
+ ] as const
)
.map((name) => {
const val = this.getConfigValue(name);
@@ -325,6 +344,9 @@ export class DraftProviderConfig extends Model({
oauthClientId: prop("").withSetter(),
oauthSecret: prop("").withSetter(),
+ additionalScope: prop("").withSetter(),
+
+ requireEmailVerification: prop(true).withSetter(),
}) {
@computed
get oauthClientIdError() {
@@ -372,8 +394,19 @@ export class DraftProviderConfig extends Model({
provider.kind === "OAuth"
? `
client_id := ${JSON.stringify(this.oauthClientId)},
- secret := ${JSON.stringify(this.oauthSecret)}
+ secret := ${JSON.stringify(this.oauthSecret)},
+ ${
+ this.additionalScope.trim()
+ ? `additional_scope := ${JSON.stringify(
+ this.additionalScope.trim()
+ )}`
+ : ""
+ }
`
+ : provider.kind === "Local"
+ ? `require_verification := ${
+ this.requireEmailVerification ? "true" : "false"
+ },`
: ""
}
}`