Skip to content

Commit

Permalink
Add additional_scope/require_verification to providers + `redirec…
Browse files Browse the repository at this point in the history
…t_to_on_signup` to ui config (#264)

* Add `additional_scope` to providers + `redirect_to_on_signup` to ui config

* Add `require_verification` config
  • Loading branch information
jaclarke authored Oct 20, 2023
1 parent 771249a commit 695cded
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 12 deletions.
33 changes: 33 additions & 0 deletions shared/studio/tabs/auth/authAdmin.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -368,6 +394,13 @@
@include hideScrollbar;
}

.providerConfigValue {
span {
opacity: 0.7;
font-style: italic;
}
}

@include darkTheme {
background-color: #2f2f2f;

Expand Down
99 changes: 90 additions & 9 deletions shared/studio/tabs/auth/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
DraftUIConfig,
ProviderKind,
OAuthProviderData,
LocalEmailPasswordProviderData,
} from "./state";
import {useTabState} from "../../state";
import {encodeB64} from "edgedb/dist/primitives/buffer";
Expand Down Expand Up @@ -268,7 +269,26 @@ const UIConfigForm = observer(function UIConfig({
/>
</div>
<div className={styles.configExplain}>
The url to redirect to after successful login.
The url to redirect to after successful sign in.
</div>
</div>
</div>

<div className={styles.gridItem}>
<div className={styles.configName}>redirect_to_on_signup</div>
<div className={styles.configInputWrapper}>
<div className={styles.configInput}>
<Input
size={32}
value={draft.getConfigValue("redirect_to_on_signup")}
onChange={(val) =>
draft.setConfigValue("redirect_to_on_signup", val)
}
/>
</div>
<div className={styles.configExplain}>
The url to redirect to after a new user signs up. If not set,
'redirect_to' will be used instead.
</div>
</div>
</div>
Expand Down Expand Up @@ -573,7 +593,44 @@ const DraftProviderConfigForm = observer(function DraftProviderConfigForm({
</div>
</div>
</div>
<div className={styles.gridItem}>
<div className={styles.configName}>additional_scope</div>
<div className={styles.configInputWrapper}>
<div className={styles.configInput}>
<Input
size={32}
value={draftState.additionalScope}
onChange={(val) => draftState.setAdditionalScope(val)}
/>
</div>
<div className={styles.configExplain}>
Space-separated list of scopes to be included in the
authorize request to the OAuth provider.
</div>
</div>
</div>
</>
) : providerKind === "Local" ? (
<div className={styles.gridItem}>
<div className={styles.configName}>require_verification</div>
<div className={styles.configInputWrapper}>
<div className={styles.configInput}>
<label className={styles.checkbox}>
<input
type="checkbox"
checked={draftState.requireEmailVerification}
onChange={(e) =>
draftState.setRequireEmailVerification(e.target.checked)
}
/>
</label>
</div>
<div className={styles.configExplain}>
Whether the email needs to be verified before the user is
allowed to sign in.
</div>
</div>
</div>
) : null}
</div>

Expand Down Expand Up @@ -612,7 +669,7 @@ function ProviderCard({provider}: {provider: AuthProviderData}) {
<div
className={cn(styles.expandProvider, {
[styles.collapsed]: !expanded,
[styles.disabled]: kind !== "OAuth",
// [styles.disabled]: kind !== "OAuth",
})}
onClick={() => setExpanded(!expanded)}
>
Expand All @@ -636,15 +693,39 @@ function ProviderCard({provider}: {provider: AuthProviderData}) {
}}
/>
</div>
{expanded && kind === "OAuth" ? (
{expanded ? (
<div className={styles.providerDetails}>
<div className={styles.providerConfigName}>client_id</div>
<div className={styles.providerConfigValue}>
{(provider as OAuthProviderData).client_id}
</div>
{kind === "OAuth" ? (
<>
<div className={styles.providerConfigName}>client_id</div>
<div className={styles.providerConfigValue}>
{(provider as OAuthProviderData).client_id}
</div>

<div className={styles.providerConfigName}>secret</div>
<div className={styles.providerConfigValue}>
{secretPlaceholder}
</div>

<div className={styles.providerConfigName}>secret</div>
<div className={styles.providerConfigValue}>{secretPlaceholder}</div>
<div className={styles.providerConfigName}>additional_scope</div>
<div className={styles.providerConfigValue}>
{(provider as OAuthProviderData).additional_scope || (
<span>none</span>
)}
</div>
</>
) : kind === "Local" ? (
<>
<div className={styles.providerConfigName}>
require_verification
</div>
<div className={styles.providerConfigValue}>
{(
provider as LocalEmailPasswordProviderData
).require_verification.toString()}
</div>
</>
) : null}
</div>
) : null}
</div>
Expand Down
39 changes: 36 additions & 3 deletions shared/studio/tabs/auth/state/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -221,6 +231,7 @@ export class AuthAdminState extends Model({
@model("AdminDraftUIConfig")
export class DraftUIConfig extends Model({
_redirect_to: prop<string | null>(null),
_redirect_to_on_signup: prop<string | null>(null),
_app_name: prop<string | null>(null),
_logo_url: prop<string | null>(null),
_dark_logo_url: prop<string | null>(null),
Expand Down Expand Up @@ -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 ||
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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() {
Expand Down Expand Up @@ -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"
},`
: ""
}
}`
Expand Down

0 comments on commit 695cded

Please sign in to comment.