mirror of
https://github.com/hcengineering/platform.git
synced 2024-12-22 19:11:33 +03:00
UBERF-8429: Allow to disable sign-ups (#6934)
Some checks are pending
CI / build (push) Waiting to run
CI / svelte-check (push) Blocked by required conditions
CI / formatting (push) Blocked by required conditions
CI / test (push) Blocked by required conditions
CI / uitest (push) Waiting to run
CI / uitest-pg (push) Waiting to run
CI / uitest-qms (push) Waiting to run
CI / docker-build (push) Blocked by required conditions
CI / dist-build (push) Blocked by required conditions
Some checks are pending
CI / build (push) Waiting to run
CI / svelte-check (push) Blocked by required conditions
CI / formatting (push) Blocked by required conditions
CI / test (push) Blocked by required conditions
CI / uitest (push) Waiting to run
CI / uitest-pg (push) Waiting to run
CI / uitest-qms (push) Waiting to run
CI / docker-build (push) Blocked by required conditions
CI / dist-build (push) Blocked by required conditions
Signed-off-by: Alexey Zinoviev <alexey.zinoviev@xored.com>
This commit is contained in:
parent
2c45db6c41
commit
6b112fc1be
3
.vscode/launch.json
vendored
3
.vscode/launch.json
vendored
@ -97,7 +97,8 @@
|
|||||||
"SES_URL": "",
|
"SES_URL": "",
|
||||||
"MINIO_ACCESS_KEY": "minioadmin",
|
"MINIO_ACCESS_KEY": "minioadmin",
|
||||||
"MINIO_SECRET_KEY": "minioadmin",
|
"MINIO_SECRET_KEY": "minioadmin",
|
||||||
"MINIO_ENDPOINT": "localhost"
|
"MINIO_ENDPOINT": "localhost",
|
||||||
|
// "DISABLE_SIGNUP": "true",
|
||||||
// "INIT_SCRIPT_URL": "https://raw.githubusercontent.com/hcengineering/init/main/script.yaml",
|
// "INIT_SCRIPT_URL": "https://raw.githubusercontent.com/hcengineering/init/main/script.yaml",
|
||||||
// "INIT_WORKSPACE": "onboarding",
|
// "INIT_WORKSPACE": "onboarding",
|
||||||
},
|
},
|
||||||
|
@ -85,6 +85,7 @@ services:
|
|||||||
- LAST_NAME_FIRST=true
|
- LAST_NAME_FIRST=true
|
||||||
- ACCOUNTS_URL=http://host.docker.internal:3000
|
- ACCOUNTS_URL=http://host.docker.internal:3000
|
||||||
- BRANDING_PATH=/var/cfg/branding.json
|
- BRANDING_PATH=/var/cfg/branding.json
|
||||||
|
# - DISABLE_SIGNUP=true
|
||||||
# - INIT_SCRIPT_URL=https://raw.githubusercontent.com/hcengineering/init/main/script.yaml
|
# - INIT_SCRIPT_URL=https://raw.githubusercontent.com/hcengineering/init/main/script.yaml
|
||||||
# - INIT_WORKSPACE=onboarding
|
# - INIT_WORKSPACE=onboarding
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
@ -197,6 +198,7 @@ services:
|
|||||||
- DESKTOP_UPDATES_URL=https://dist.huly.io
|
- DESKTOP_UPDATES_URL=https://dist.huly.io
|
||||||
- DESKTOP_UPDATES_CHANNEL=dev
|
- DESKTOP_UPDATES_CHANNEL=dev
|
||||||
- BRANDING_URL=http://host.docker.internal:8087/branding.json
|
- BRANDING_URL=http://host.docker.internal:8087/branding.json
|
||||||
|
# - DISABLE_SIGNUP=true
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
transactor:
|
transactor:
|
||||||
image: hardcoreeng/transactor
|
image: hardcoreeng/transactor
|
||||||
|
@ -57,6 +57,7 @@
|
|||||||
export let ignoreInitialValidation: boolean = false
|
export let ignoreInitialValidation: boolean = false
|
||||||
export let withProviders: boolean = false
|
export let withProviders: boolean = false
|
||||||
export let subtitle: string | undefined = undefined
|
export let subtitle: string | undefined = undefined
|
||||||
|
export let signUpDisabled = false
|
||||||
|
|
||||||
$: $themeStore.language && validate($themeStore.language)
|
$: $themeStore.language && validate($themeStore.language)
|
||||||
|
|
||||||
@ -138,7 +139,7 @@
|
|||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{#if loginState !== 'none'}
|
{#if loginState !== 'none'}
|
||||||
<Tabs {loginState} />
|
<Tabs {loginState} {signUpDisabled} />
|
||||||
{:else}
|
{:else}
|
||||||
{#if subtitle !== undefined}
|
{#if subtitle !== undefined}
|
||||||
<div class="fs-title">
|
<div class="fs-title">
|
||||||
|
@ -54,6 +54,7 @@
|
|||||||
|
|
||||||
export let page: Pages = 'signup'
|
export let page: Pages = 'signup'
|
||||||
|
|
||||||
|
const signUpDisabled = getMetadata(login.metadata.DisableSignUp) ?? false
|
||||||
let navigateUrl: string | undefined
|
let navigateUrl: string | undefined
|
||||||
|
|
||||||
onDestroy(location.subscribe(updatePageLoc))
|
onDestroy(location.subscribe(updatePageLoc))
|
||||||
@ -134,13 +135,13 @@
|
|||||||
<Scroller padding={'1rem 0'}>
|
<Scroller padding={'1rem 0'}>
|
||||||
<div class="form-content">
|
<div class="form-content">
|
||||||
{#if page === 'login'}
|
{#if page === 'login'}
|
||||||
<LoginForm {navigateUrl} />
|
<LoginForm {navigateUrl} {signUpDisabled} />
|
||||||
{:else if page === 'signup'}
|
{:else if page === 'signup'}
|
||||||
<SignupForm />
|
<SignupForm {signUpDisabled} />
|
||||||
{:else if page === 'createWorkspace'}
|
{:else if page === 'createWorkspace'}
|
||||||
<CreateWorkspaceForm />
|
<CreateWorkspaceForm />
|
||||||
{:else if page === 'password'}
|
{:else if page === 'password'}
|
||||||
<PasswordRequest />
|
<PasswordRequest {signUpDisabled} />
|
||||||
{:else if page === 'recovery'}
|
{:else if page === 'recovery'}
|
||||||
<PasswordRestore />
|
<PasswordRestore />
|
||||||
{:else if page === 'selectWorkspace'}
|
{:else if page === 'selectWorkspace'}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
import login from '../plugin'
|
import login from '../plugin'
|
||||||
|
|
||||||
export let navigateUrl: string | undefined = undefined
|
export let navigateUrl: string | undefined = undefined
|
||||||
|
export let signUpDisabled = false
|
||||||
|
|
||||||
let method: LoginMethods = LoginMethods.Otp
|
let method: LoginMethods = LoginMethods.Otp
|
||||||
|
|
||||||
@ -44,12 +45,12 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if method === LoginMethods.Otp}
|
{#if method === LoginMethods.Otp}
|
||||||
<LoginOtpForm {navigateUrl} on:change={changeMethod} />
|
<LoginOtpForm {navigateUrl} {signUpDisabled} on:change={changeMethod} />
|
||||||
<div class="action">
|
<div class="action">
|
||||||
<BottomActionComponent action={loginWithPasswordAction} />
|
<BottomActionComponent action={loginWithPasswordAction} />
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<LoginPasswordForm {navigateUrl} on:change={changeMethod} />
|
<LoginPasswordForm {navigateUrl} {signUpDisabled} on:change={changeMethod} />
|
||||||
<div class="action">
|
<div class="action">
|
||||||
<BottomActionComponent action={loginWithCodeAction} />
|
<BottomActionComponent action={loginWithCodeAction} />
|
||||||
</div>
|
</div>
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
import { OtpLoginSteps, sendOtp } from '../index'
|
import { OtpLoginSteps, sendOtp } from '../index'
|
||||||
|
|
||||||
export let navigateUrl: string | undefined = undefined
|
export let navigateUrl: string | undefined = undefined
|
||||||
|
export let signUpDisabled = false
|
||||||
|
|
||||||
const fields = [{ id: 'email', name: 'username', i18n: login.string.Email }]
|
const fields = [{ id: 'email', name: 'username', i18n: login.string.Email }]
|
||||||
const formData = {
|
const formData = {
|
||||||
@ -57,11 +58,12 @@
|
|||||||
{fields}
|
{fields}
|
||||||
object={formData}
|
object={formData}
|
||||||
{action}
|
{action}
|
||||||
|
{signUpDisabled}
|
||||||
ignoreInitialValidation
|
ignoreInitialValidation
|
||||||
withProviders
|
withProviders
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if step === OtpLoginSteps.Otp && formData.username !== ''}
|
{#if step === OtpLoginSteps.Otp && formData.username !== ''}
|
||||||
<OtpForm email={formData.username} {navigateUrl} retryOn={otpRetryOn} on:step={handleStep} />
|
<OtpForm email={formData.username} {signUpDisabled} {navigateUrl} retryOn={otpRetryOn} on:step={handleStep} />
|
||||||
{/if}
|
{/if}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
import login from '../plugin'
|
import login from '../plugin'
|
||||||
|
|
||||||
export let navigateUrl: string | undefined = undefined
|
export let navigateUrl: string | undefined = undefined
|
||||||
|
export let signUpDisabled = false
|
||||||
|
|
||||||
const fields = [
|
const fields = [
|
||||||
{ id: 'email', name: 'username', i18n: login.string.Email },
|
{ id: 'email', name: 'username', i18n: login.string.Email },
|
||||||
@ -62,6 +63,7 @@
|
|||||||
{fields}
|
{fields}
|
||||||
{object}
|
{object}
|
||||||
{action}
|
{action}
|
||||||
|
{signUpDisabled}
|
||||||
bottomActions={[recoveryAction]}
|
bottomActions={[recoveryAction]}
|
||||||
ignoreInitialValidation
|
ignoreInitialValidation
|
||||||
withProviders
|
withProviders
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
export let navigateUrl: string | undefined = undefined
|
export let navigateUrl: string | undefined = undefined
|
||||||
export let email: string
|
export let email: string
|
||||||
export let retryOn: Timestamp
|
export let retryOn: Timestamp
|
||||||
|
export let signUpDisabled = false
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
@ -232,7 +233,7 @@
|
|||||||
style:min-height={$deviceInfo.docHeight > 720 ? '42rem' : '0'}
|
style:min-height={$deviceInfo.docHeight > 720 ? '42rem' : '0'}
|
||||||
>
|
>
|
||||||
<div class="header">
|
<div class="header">
|
||||||
<Tabs loginState="login" />
|
<Tabs loginState="login" {signUpDisabled} />
|
||||||
<div class="description">
|
<div class="description">
|
||||||
<Label label={login.string.SentTo} />
|
<Label label={login.string.SentTo} />
|
||||||
<span class="email ml-1">
|
<span class="email ml-1">
|
||||||
|
@ -23,8 +23,9 @@
|
|||||||
import { BottomAction } from '..'
|
import { BottomAction } from '..'
|
||||||
import { signUpAction } from '../actions'
|
import { signUpAction } from '../actions'
|
||||||
|
|
||||||
const fields = [{ id: 'email', name: 'username', i18n: login.string.Email }]
|
export let signUpDisabled = false
|
||||||
|
|
||||||
|
const fields = [{ id: 'email', name: 'username', i18n: login.string.Email }]
|
||||||
const object = {
|
const object = {
|
||||||
username: ''
|
username: ''
|
||||||
}
|
}
|
||||||
@ -64,7 +65,7 @@
|
|||||||
goTo('login')
|
goTo('login')
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
signUpAction
|
...(signUpDisabled ? [] : [signUpAction])
|
||||||
]
|
]
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -21,6 +21,8 @@
|
|||||||
import { goTo, signUp } from '../utils'
|
import { goTo, signUp } from '../utils'
|
||||||
import Form from './Form.svelte'
|
import Form from './Form.svelte'
|
||||||
|
|
||||||
|
export let signUpDisabled = false
|
||||||
|
|
||||||
const fields = [
|
const fields = [
|
||||||
{ id: 'given-name', name: 'first', i18n: login.string.FirstName, short: true },
|
{ id: 'given-name', name: 'first', i18n: login.string.FirstName, short: true },
|
||||||
{ id: 'family-name', name: 'last', i18n: login.string.LastName, short: true },
|
{ id: 'family-name', name: 'last', i18n: login.string.LastName, short: true },
|
||||||
@ -39,6 +41,10 @@
|
|||||||
|
|
||||||
let status: Status<any> = OK
|
let status: Status<any> = OK
|
||||||
|
|
||||||
|
if (signUpDisabled) {
|
||||||
|
goTo('login')
|
||||||
|
}
|
||||||
|
|
||||||
const action = {
|
const action = {
|
||||||
i18n: login.string.SignUp,
|
i18n: login.string.SignUp,
|
||||||
func: async () => {
|
func: async () => {
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
import login from '../plugin'
|
import login from '../plugin'
|
||||||
|
|
||||||
export let loginState: 'login' | 'signup' | 'none' = 'none'
|
export let loginState: 'login' | 'signup' | 'none' = 'none'
|
||||||
|
export let signUpDisabled = false
|
||||||
|
|
||||||
const goTab = (path: string) => {
|
const goTab = (path: string) => {
|
||||||
const loc = getCurrentLocation()
|
const loc = getCurrentLocation()
|
||||||
@ -29,16 +30,18 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="flex-row-center caption">
|
<div class="flex-row-center caption">
|
||||||
<a
|
{#if !signUpDisabled}
|
||||||
class="title"
|
<a
|
||||||
class:selected={loginState === 'signup'}
|
class="title"
|
||||||
href="."
|
class:selected={loginState === 'signup'}
|
||||||
on:click|preventDefault={() => {
|
href="."
|
||||||
if (loginState !== 'signup') goTab('signup')
|
on:click|preventDefault={() => {
|
||||||
}}
|
if (loginState !== 'signup') goTab('signup')
|
||||||
>
|
}}
|
||||||
<Label label={login.string.SignUp} />
|
>
|
||||||
</a>
|
<Label label={login.string.SignUp} />
|
||||||
|
</a>
|
||||||
|
{/if}
|
||||||
<a
|
<a
|
||||||
class="title"
|
class="title"
|
||||||
class:selected={loginState === 'login'}
|
class:selected={loginState === 'login'}
|
||||||
|
@ -72,7 +72,8 @@ export default plugin(loginId, {
|
|||||||
LoginTokens: '' as Metadata<Record<string, string>>,
|
LoginTokens: '' as Metadata<Record<string, string>>,
|
||||||
LastToken: '' as Metadata<string>,
|
LastToken: '' as Metadata<string>,
|
||||||
LoginEndpoint: '' as Metadata<string>,
|
LoginEndpoint: '' as Metadata<string>,
|
||||||
LoginEmail: '' as Metadata<string>
|
LoginEmail: '' as Metadata<string>,
|
||||||
|
DisableSignUp: '' as Metadata<boolean>
|
||||||
},
|
},
|
||||||
component: {
|
component: {
|
||||||
LoginApp: '' as AnyComponent,
|
LoginApp: '' as AnyComponent,
|
||||||
|
@ -13,7 +13,8 @@ export function registerGithub (
|
|||||||
accountsUrl: string,
|
accountsUrl: string,
|
||||||
dbPromise: Promise<AccountDB>,
|
dbPromise: Promise<AccountDB>,
|
||||||
frontUrl: string,
|
frontUrl: string,
|
||||||
brandings: BrandingMap
|
brandings: BrandingMap,
|
||||||
|
signUpDisabled?: boolean
|
||||||
): string | undefined {
|
): string | undefined {
|
||||||
const GITHUB_CLIENT_ID = process.env.GITHUB_CLIENT_ID
|
const GITHUB_CLIENT_ID = process.env.GITHUB_CLIENT_ID
|
||||||
const GITHUB_CLIENT_SECRET = process.env.GITHUB_CLIENT_SECRET
|
const GITHUB_CLIENT_SECRET = process.env.GITHUB_CLIENT_SECRET
|
||||||
@ -69,7 +70,7 @@ export function registerGithub (
|
|||||||
const [first, last] = ctx.state.user.displayName?.split(' ') ?? [ctx.state.user.username, '']
|
const [first, last] = ctx.state.user.displayName?.split(' ') ?? [ctx.state.user.username, '']
|
||||||
measureCtx.info('Provider auth handler', { email, type: 'github' })
|
measureCtx.info('Provider auth handler', { email, type: 'github' })
|
||||||
if (email !== undefined) {
|
if (email !== undefined) {
|
||||||
let loginInfo: LoginInfo
|
let loginInfo: LoginInfo | null
|
||||||
const state = safeParseAuthState(ctx.query?.state)
|
const state = safeParseAuthState(ctx.query?.state)
|
||||||
const branding = getBranding(brandings, state?.branding)
|
const branding = getBranding(brandings, state?.branding)
|
||||||
const db = await dbPromise
|
const db = await dbPromise
|
||||||
@ -78,17 +79,35 @@ export function registerGithub (
|
|||||||
githubId: ctx.state.user.id
|
githubId: ctx.state.user.id
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
loginInfo = await loginWithProvider(measureCtx, db, null, email, first, last, {
|
loginInfo = await loginWithProvider(
|
||||||
githubId: ctx.state.user.id
|
measureCtx,
|
||||||
})
|
db,
|
||||||
|
null,
|
||||||
|
email,
|
||||||
|
first,
|
||||||
|
last,
|
||||||
|
{
|
||||||
|
githubId: ctx.state.user.id
|
||||||
|
},
|
||||||
|
signUpDisabled
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const origin = concatLink(branding?.front ?? frontUrl, '/login/auth')
|
if (loginInfo === null) {
|
||||||
const query = encodeURIComponent(qs.stringify({ token: loginInfo.token }))
|
measureCtx.info('Failed to auth: no associated account found', {
|
||||||
|
email,
|
||||||
|
type: 'github',
|
||||||
|
user: ctx.state?.user
|
||||||
|
})
|
||||||
|
ctx.redirect(concatLink(branding?.front ?? frontUrl, '/login'))
|
||||||
|
} else {
|
||||||
|
const origin = concatLink(branding?.front ?? frontUrl, '/login/auth')
|
||||||
|
const query = encodeURIComponent(qs.stringify({ token: loginInfo.token }))
|
||||||
|
|
||||||
measureCtx.info('Success auth, redirect', { email, type: 'github', target: origin })
|
measureCtx.info('Success auth, redirect', { email, type: 'github', target: origin })
|
||||||
// Successful authentication, redirect to your application
|
// Successful authentication, redirect to your application
|
||||||
ctx.redirect(`${origin}?${query}`)
|
ctx.redirect(`${origin}?${query}`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
measureCtx.error('failed to auth', { err, type: 'github', user: ctx.state?.user })
|
measureCtx.error('failed to auth', { err, type: 'github', user: ctx.state?.user })
|
||||||
|
@ -13,7 +13,8 @@ export function registerGoogle (
|
|||||||
accountsUrl: string,
|
accountsUrl: string,
|
||||||
dbPromise: Promise<AccountDB>,
|
dbPromise: Promise<AccountDB>,
|
||||||
frontUrl: string,
|
frontUrl: string,
|
||||||
brandings: BrandingMap
|
brandings: BrandingMap,
|
||||||
|
signUpDisabled?: boolean
|
||||||
): string | undefined {
|
): string | undefined {
|
||||||
const GOOGLE_CLIENT_ID = process.env.GOOGLE_CLIENT_ID
|
const GOOGLE_CLIENT_ID = process.env.GOOGLE_CLIENT_ID
|
||||||
const GOOGLE_CLIENT_SECRET = process.env.GOOGLE_CLIENT_SECRET
|
const GOOGLE_CLIENT_SECRET = process.env.GOOGLE_CLIENT_SECRET
|
||||||
@ -70,22 +71,31 @@ export function registerGoogle (
|
|||||||
measureCtx.info('Provider auth handler', { email, type: 'google' })
|
measureCtx.info('Provider auth handler', { email, type: 'google' })
|
||||||
if (email !== undefined) {
|
if (email !== undefined) {
|
||||||
try {
|
try {
|
||||||
let loginInfo: LoginInfo
|
let loginInfo: LoginInfo | null
|
||||||
const state = safeParseAuthState(ctx.query?.state)
|
const state = safeParseAuthState(ctx.query?.state)
|
||||||
const branding = getBranding(brandings, state?.branding)
|
const branding = getBranding(brandings, state?.branding)
|
||||||
const db = await dbPromise
|
const db = await dbPromise
|
||||||
if (state.inviteId != null && state.inviteId !== '') {
|
if (state.inviteId != null && state.inviteId !== '') {
|
||||||
loginInfo = await joinWithProvider(measureCtx, db, null, email, first, last, state.inviteId as any)
|
loginInfo = await joinWithProvider(measureCtx, db, null, email, first, last, state.inviteId as any)
|
||||||
} else {
|
} else {
|
||||||
loginInfo = await loginWithProvider(measureCtx, db, null, email, first, last)
|
loginInfo = await loginWithProvider(measureCtx, db, null, email, first, last, undefined, signUpDisabled)
|
||||||
}
|
}
|
||||||
|
|
||||||
const origin = concatLink(branding?.front ?? frontUrl, '/login/auth')
|
if (loginInfo === null) {
|
||||||
const query = encodeURIComponent(qs.stringify({ token: loginInfo.token }))
|
measureCtx.info('Failed to auth: no associated account found', {
|
||||||
|
email,
|
||||||
|
type: 'google',
|
||||||
|
user: ctx.state?.user
|
||||||
|
})
|
||||||
|
ctx.redirect(concatLink(branding?.front ?? frontUrl, '/login'))
|
||||||
|
} else {
|
||||||
|
const origin = concatLink(branding?.front ?? frontUrl, '/login/auth')
|
||||||
|
const query = encodeURIComponent(qs.stringify({ token: loginInfo.token }))
|
||||||
|
|
||||||
// Successful authentication, redirect to your application
|
// Successful authentication, redirect to your application
|
||||||
measureCtx.info('Success auth, redirect', { email, type: 'google', target: origin })
|
measureCtx.info('Success auth, redirect', { email, type: 'google', target: origin })
|
||||||
ctx.redirect(`${origin}?${query}`)
|
ctx.redirect(`${origin}?${query}`)
|
||||||
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
measureCtx.error('failed to auth', { err, type: 'google', user: ctx.state?.user })
|
measureCtx.error('failed to auth', { err, type: 'google', user: ctx.state?.user })
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,8 @@ export type AuthProvider = (
|
|||||||
accountsUrl: string,
|
accountsUrl: string,
|
||||||
db: Promise<AccountDB>,
|
db: Promise<AccountDB>,
|
||||||
frontUrl: string,
|
frontUrl: string,
|
||||||
brandings: BrandingMap
|
brandings: BrandingMap,
|
||||||
|
signUpDisabled?: boolean
|
||||||
) => string | undefined
|
) => string | undefined
|
||||||
|
|
||||||
export function registerProviders (
|
export function registerProviders (
|
||||||
@ -28,7 +29,8 @@ export function registerProviders (
|
|||||||
db: Promise<AccountDB>,
|
db: Promise<AccountDB>,
|
||||||
serverSecret: string,
|
serverSecret: string,
|
||||||
frontUrl: string | undefined,
|
frontUrl: string | undefined,
|
||||||
brandings: BrandingMap
|
brandings: BrandingMap,
|
||||||
|
signUpDisabled: boolean = false
|
||||||
): void {
|
): void {
|
||||||
const accountsUrl = process.env.ACCOUNTS_URL
|
const accountsUrl = process.env.ACCOUNTS_URL
|
||||||
if (accountsUrl === undefined) {
|
if (accountsUrl === undefined) {
|
||||||
@ -63,7 +65,7 @@ export function registerProviders (
|
|||||||
const res: string[] = []
|
const res: string[] = []
|
||||||
const providers: AuthProvider[] = [registerGoogle, registerGithub, registerOpenid]
|
const providers: AuthProvider[] = [registerGoogle, registerGithub, registerOpenid]
|
||||||
for (const provider of providers) {
|
for (const provider of providers) {
|
||||||
const value = provider(ctx, passport, router, accountsUrl, db, frontUrl, brandings)
|
const value = provider(ctx, passport, router, accountsUrl, db, frontUrl, brandings, signUpDisabled)
|
||||||
if (value !== undefined) res.push(value)
|
if (value !== undefined) res.push(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,7 +28,8 @@ export function registerOpenid (
|
|||||||
accountsUrl: string,
|
accountsUrl: string,
|
||||||
dbPromise: Promise<AccountDB>,
|
dbPromise: Promise<AccountDB>,
|
||||||
frontUrl: string,
|
frontUrl: string,
|
||||||
brandings: BrandingMap
|
brandings: BrandingMap,
|
||||||
|
signUpDisabled?: boolean
|
||||||
): string | undefined {
|
): string | undefined {
|
||||||
const openidClientId = process.env.OPENID_CLIENT_ID
|
const openidClientId = process.env.OPENID_CLIENT_ID
|
||||||
const openidClientSecret = process.env.OPENID_CLIENT_SECRET
|
const openidClientSecret = process.env.OPENID_CLIENT_SECRET
|
||||||
@ -90,7 +91,7 @@ export function registerOpenid (
|
|||||||
const [first, last] = ctx.state.user.name?.split(' ') ?? [ctx.state.user.username, '']
|
const [first, last] = ctx.state.user.name?.split(' ') ?? [ctx.state.user.username, '']
|
||||||
measureCtx.info('Provider auth handler', { email, type: 'openid' })
|
measureCtx.info('Provider auth handler', { email, type: 'openid' })
|
||||||
if (email !== undefined) {
|
if (email !== undefined) {
|
||||||
let loginInfo: LoginInfo
|
let loginInfo: LoginInfo | null
|
||||||
const state = safeParseAuthState(ctx.query?.state)
|
const state = safeParseAuthState(ctx.query?.state)
|
||||||
const branding = getBranding(brandings, state?.branding)
|
const branding = getBranding(brandings, state?.branding)
|
||||||
const db = await dbPromise
|
const db = await dbPromise
|
||||||
@ -99,17 +100,35 @@ export function registerOpenid (
|
|||||||
openId: ctx.state.user.sub
|
openId: ctx.state.user.sub
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
loginInfo = await loginWithProvider(measureCtx, db, null, email, first, last, {
|
loginInfo = await loginWithProvider(
|
||||||
openId: ctx.state.user.sub
|
measureCtx,
|
||||||
})
|
db,
|
||||||
|
null,
|
||||||
|
email,
|
||||||
|
first,
|
||||||
|
last,
|
||||||
|
{
|
||||||
|
openId: ctx.state.user.sub
|
||||||
|
},
|
||||||
|
signUpDisabled
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const origin = concatLink(branding?.front ?? frontUrl, '/login/auth')
|
if (loginInfo === null) {
|
||||||
const query = encodeURIComponent(qs.stringify({ token: loginInfo.token }))
|
measureCtx.info('Failed to auth: no associated account found', {
|
||||||
|
email,
|
||||||
|
type: 'openid',
|
||||||
|
user: ctx.state?.user
|
||||||
|
})
|
||||||
|
ctx.redirect(concatLink(branding?.front ?? frontUrl, '/login'))
|
||||||
|
} else {
|
||||||
|
const origin = concatLink(branding?.front ?? frontUrl, '/login/auth')
|
||||||
|
const query = encodeURIComponent(qs.stringify({ token: loginInfo.token }))
|
||||||
|
|
||||||
measureCtx.info('Success auth, redirect', { email, type: 'openid', target: origin })
|
measureCtx.info('Success auth, redirect', { email, type: 'openid', target: origin })
|
||||||
// Successful authentication, redirect to your application
|
// Successful authentication, redirect to your application
|
||||||
ctx.redirect(`${origin}?${query}`)
|
ctx.redirect(`${origin}?${query}`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
measureCtx.error('failed to auth', { err, type: 'openid', user: ctx.state?.user })
|
measureCtx.error('failed to auth', { err, type: 'openid', user: ctx.state?.user })
|
||||||
|
@ -13,7 +13,8 @@ export function registerToken (
|
|||||||
accountsUrl: string,
|
accountsUrl: string,
|
||||||
dbPromise: Promise<AccountDB>,
|
dbPromise: Promise<AccountDB>,
|
||||||
frontUrl: string,
|
frontUrl: string,
|
||||||
brandings: BrandingMap
|
brandings: BrandingMap,
|
||||||
|
signUpDisabled?: boolean
|
||||||
): string | undefined {
|
): string | undefined {
|
||||||
passport.use(
|
passport.use(
|
||||||
'token',
|
'token',
|
||||||
|
@ -30,7 +30,6 @@ import os from 'os'
|
|||||||
*/
|
*/
|
||||||
export function serveAccount (measureCtx: MeasureContext, brandings: BrandingMap, onClose?: () => void): void {
|
export function serveAccount (measureCtx: MeasureContext, brandings: BrandingMap, onClose?: () => void): void {
|
||||||
console.log('Starting account service with brandings: ', brandings)
|
console.log('Starting account service with brandings: ', brandings)
|
||||||
const methods = getMethods()
|
|
||||||
const ACCOUNT_PORT = parseInt(process.env.ACCOUNT_PORT ?? '3000')
|
const ACCOUNT_PORT = parseInt(process.env.ACCOUNT_PORT ?? '3000')
|
||||||
const dbUrl = process.env.DB_URL
|
const dbUrl = process.env.DB_URL
|
||||||
if (dbUrl === undefined) {
|
if (dbUrl === undefined) {
|
||||||
@ -81,6 +80,9 @@ export function serveAccount (measureCtx: MeasureContext, brandings: BrandingMap
|
|||||||
setMetadata(toolPlugin.metadata.InitScriptURL, initScriptUrl)
|
setMetadata(toolPlugin.metadata.InitScriptURL, initScriptUrl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const hasSignUp = process.env.DISABLE_SIGNUP !== 'true'
|
||||||
|
const methods = getMethods(hasSignUp)
|
||||||
|
|
||||||
const accountsDb = getAccountDB(dbUrl)
|
const accountsDb = getAccountDB(dbUrl)
|
||||||
|
|
||||||
const app = new Koa()
|
const app = new Koa()
|
||||||
@ -105,7 +107,8 @@ export function serveAccount (measureCtx: MeasureContext, brandings: BrandingMap
|
|||||||
}),
|
}),
|
||||||
serverSecret,
|
serverSecret,
|
||||||
frontURL,
|
frontURL,
|
||||||
brandings
|
brandings,
|
||||||
|
!hasSignUp
|
||||||
)
|
)
|
||||||
|
|
||||||
void accountsDb.then((res) => {
|
void accountsDb.then((res) => {
|
||||||
|
@ -2334,8 +2334,9 @@ export async function loginWithProvider (
|
|||||||
_email: string,
|
_email: string,
|
||||||
first: string,
|
first: string,
|
||||||
last: string,
|
last: string,
|
||||||
extra?: Record<string, string>
|
extra?: Record<string, string>,
|
||||||
): Promise<LoginInfo> {
|
signUpDisabled: boolean = false
|
||||||
|
): Promise<LoginInfo | null> {
|
||||||
try {
|
try {
|
||||||
const email = cleanEmail(_email)
|
const email = cleanEmail(_email)
|
||||||
if (last == null) {
|
if (last == null) {
|
||||||
@ -2357,6 +2358,11 @@ export async function loginWithProvider (
|
|||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (signUpDisabled) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
const newAccount = await createAcc(ctx, db, branding, email, null, first, last, true, true, extra)
|
const newAccount = await createAcc(ctx, db, branding, email, null, first, last, true, true, extra)
|
||||||
|
|
||||||
const result = {
|
const result = {
|
||||||
@ -2463,7 +2469,7 @@ export async function deleteWorkspace (
|
|||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export function getMethods (): Record<string, AccountMethod> {
|
export function getMethods (hasSignUp: boolean = true): Record<string, AccountMethod> {
|
||||||
return {
|
return {
|
||||||
login: wrap(login),
|
login: wrap(login),
|
||||||
join: wrap(join),
|
join: wrap(join),
|
||||||
@ -2478,7 +2484,7 @@ export function getMethods (): Record<string, AccountMethod> {
|
|||||||
getInviteLink: wrap(getInviteLink),
|
getInviteLink: wrap(getInviteLink),
|
||||||
getAccountInfo: wrap(getAccountInfo),
|
getAccountInfo: wrap(getAccountInfo),
|
||||||
getWorkspaceInfo: wrap(getWorkspaceInfo),
|
getWorkspaceInfo: wrap(getWorkspaceInfo),
|
||||||
createAccount: wrap(createAccount),
|
...(hasSignUp ? { createAccount: wrap(createAccount) } : {}),
|
||||||
createWorkspace: wrap(createUserWorkspace),
|
createWorkspace: wrap(createUserWorkspace),
|
||||||
assignWorkspace: wrap(assignWorkspace),
|
assignWorkspace: wrap(assignWorkspace),
|
||||||
removeWorkspace: wrap(removeWorkspace),
|
removeWorkspace: wrap(removeWorkspace),
|
||||||
|
@ -257,6 +257,7 @@ export function start (
|
|||||||
brandingUrl?: string
|
brandingUrl?: string
|
||||||
previewConfig: string
|
previewConfig: string
|
||||||
pushPublicKey?: string
|
pushPublicKey?: string
|
||||||
|
disableSignUp?: string
|
||||||
},
|
},
|
||||||
port: number,
|
port: number,
|
||||||
extraConfig?: Record<string, string | undefined>
|
extraConfig?: Record<string, string | undefined>
|
||||||
@ -308,6 +309,7 @@ export function start (
|
|||||||
BRANDING_URL: config.brandingUrl,
|
BRANDING_URL: config.brandingUrl,
|
||||||
PREVIEW_CONFIG: config.previewConfig,
|
PREVIEW_CONFIG: config.previewConfig,
|
||||||
PUSH_PUBLIC_KEY: config.pushPublicKey,
|
PUSH_PUBLIC_KEY: config.pushPublicKey,
|
||||||
|
DISABLE_SIGNUP: config.disableSignUp,
|
||||||
...(extraConfig ?? {})
|
...(extraConfig ?? {})
|
||||||
}
|
}
|
||||||
res.status(200)
|
res.status(200)
|
||||||
|
@ -118,6 +118,8 @@ export function startFront (ctx: MeasureContext, extraConfig?: Record<string, st
|
|||||||
|
|
||||||
setMetadata(serverToken.metadata.Secret, serverSecret)
|
setMetadata(serverToken.metadata.Secret, serverSecret)
|
||||||
|
|
||||||
|
const disableSignUp = process.env.DISABLE_SIGNUP
|
||||||
|
|
||||||
const config = {
|
const config = {
|
||||||
elasticUrl,
|
elasticUrl,
|
||||||
storageAdapter,
|
storageAdapter,
|
||||||
@ -134,7 +136,8 @@ export function startFront (ctx: MeasureContext, extraConfig?: Record<string, st
|
|||||||
collaborator,
|
collaborator,
|
||||||
brandingUrl,
|
brandingUrl,
|
||||||
previewConfig,
|
previewConfig,
|
||||||
pushPublicKey
|
pushPublicKey,
|
||||||
|
disableSignUp
|
||||||
}
|
}
|
||||||
console.log('Starting Front service with', config)
|
console.log('Starting Front service with', config)
|
||||||
const shutdown = start(ctx, config, SERVER_PORT, extraConfig)
|
const shutdown = start(ctx, config, SERVER_PORT, extraConfig)
|
||||||
|
Loading…
Reference in New Issue
Block a user