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

Signed-off-by: Alexey Zinoviev <alexey.zinoviev@xored.com>
This commit is contained in:
Alexey Zinoviev 2024-10-15 14:03:55 +04:00 committed by GitHub
parent 2c45db6c41
commit 6b112fc1be
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 148 additions and 61 deletions

3
.vscode/launch.json vendored
View File

@ -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",
}, },

View File

@ -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

View File

@ -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">

View File

@ -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'}

View File

@ -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>

View File

@ -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}

View File

@ -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

View File

@ -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">

View File

@ -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>

View File

@ -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 () => {

View File

@ -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'}

View File

@ -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,

View File

@ -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 })

View File

@ -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 })
} }

View File

@ -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)
} }

View File

@ -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 })

View File

@ -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',

View File

@ -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) => {

View File

@ -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),

View File

@ -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)

View File

@ -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)