mirror of
https://github.com/hcengineering/platform.git
synced 2025-05-28 02:47:31 +00:00
UBERF-10303: Always sign up with OTP (#8665)
This commit is contained in:
parent
37c913f0fe
commit
26194a4dbf
@ -251,6 +251,7 @@ export async function configurePlatform (): Promise<void> {
|
||||
setMetadata(presentation.metadata.UploadConfig, parseUploadConfig(config.UPLOAD_CONFIG, config.UPLOAD_URL))
|
||||
setMetadata(presentation.metadata.FrontUrl, config.FRONT_URL)
|
||||
setMetadata(presentation.metadata.LinkPreviewUrl, config.LINK_PREVIEW_URL ?? '')
|
||||
setMetadata(presentation.metadata.MailUrl, config.MAIL_URL)
|
||||
setMetadata(recorder.metadata.StreamUrl, config.STREAM_URL ?? '')
|
||||
setMetadata(presentation.metadata.StatsUrl, config.STATS_URL)
|
||||
|
||||
|
@ -43,6 +43,7 @@ export interface Config {
|
||||
PUBLIC_SCHEDULE_URL?: string
|
||||
CALDAV_SERVER_URL?: string
|
||||
EXPORT_URL?: string
|
||||
MAIL_URL?: string
|
||||
}
|
||||
|
||||
export interface Branding {
|
||||
|
@ -186,6 +186,7 @@ export interface Config {
|
||||
PUBLIC_SCHEDULE_URL?: string
|
||||
CALDAV_SERVER_URL?: string
|
||||
EXPORT_URL?: string
|
||||
MAIL_URL?: string
|
||||
}
|
||||
|
||||
export interface Branding {
|
||||
@ -428,6 +429,7 @@ export async function configurePlatform() {
|
||||
setMetadata(presentation.metadata.UploadConfig, parseUploadConfig(config.UPLOAD_CONFIG, config.UPLOAD_URL))
|
||||
setMetadata(presentation.metadata.StatsUrl, config.STATS_URL)
|
||||
setMetadata(presentation.metadata.LinkPreviewUrl, config.LINK_PREVIEW_URL)
|
||||
setMetadata(presentation.metadata.MailUrl, config.MAIL_URL)
|
||||
setMetadata(recorder.metadata.StreamUrl, config.STREAM_URL)
|
||||
setMetadata(textEditor.metadata.Collaborator, config.COLLABORATOR)
|
||||
|
||||
|
@ -61,7 +61,7 @@ export interface AccountClient {
|
||||
kind?: 'external' | 'internal' | 'byregion',
|
||||
externalRegions?: string[]
|
||||
) => Promise<WorkspaceLoginInfo>
|
||||
validateOtp: (email: string, code: string) => Promise<LoginInfo>
|
||||
validateOtp: (email: string, code: string, password?: string) => Promise<LoginInfo>
|
||||
loginOtp: (email: string) => Promise<OtpInfo>
|
||||
getLoginInfoByToken: () => Promise<LoginInfo | WorkspaceLoginInfo>
|
||||
getLoginWithWorkspaceInfo: () => Promise<LoginInfoWithWorkspaces>
|
||||
@ -98,6 +98,9 @@ export interface AccountClient {
|
||||
getRegionInfo: () => Promise<RegionInfo[]>
|
||||
createWorkspace: (name: string, region?: string) => Promise<WorkspaceLoginInfo>
|
||||
signUpOtp: (email: string, first: string, last: string) => Promise<OtpInfo>
|
||||
/**
|
||||
* Deprecated. Only to be used for dev setups without mail service.
|
||||
*/
|
||||
signUp: (email: string, password: string, first: string, last: string) => Promise<LoginInfo>
|
||||
login: (email: string, password: string) => Promise<LoginInfo>
|
||||
getPerson: () => Promise<Person>
|
||||
@ -283,10 +286,10 @@ class AccountClientImpl implements AccountClient {
|
||||
return await this.rpc(request)
|
||||
}
|
||||
|
||||
async validateOtp (email: string, code: string): Promise<LoginInfo> {
|
||||
async validateOtp (email: string, code: string, password?: string): Promise<LoginInfo> {
|
||||
const request = {
|
||||
method: 'validateOtp' as const,
|
||||
params: { email, code }
|
||||
params: { email, code, password }
|
||||
}
|
||||
|
||||
return await this.rpc(request)
|
||||
|
@ -153,7 +153,8 @@ export default plugin(presentationId, {
|
||||
PreviewConfig: '' as Metadata<PreviewConfig | undefined>,
|
||||
ClientHook: '' as Metadata<ClientHook>,
|
||||
SessionId: '' as Metadata<string>,
|
||||
StatsUrl: '' as Metadata<string>
|
||||
StatsUrl: '' as Metadata<string>,
|
||||
MailUrl: '' as Metadata<string>
|
||||
},
|
||||
status: {
|
||||
FileTooLarge: '' as StatusCode
|
||||
|
@ -70,6 +70,8 @@
|
||||
"Hello": "Ahoj {name},",
|
||||
"ProcessingInvite": "Zpracovávám pozvánku, čekejte prosím...",
|
||||
"SignToProceed": "Přihlaste se, abyste mohli pokračovat",
|
||||
"Proceed": "Pokračovat"
|
||||
"Proceed": "Pokračovat",
|
||||
"SetPasswordLater": "Nastavím heslo později",
|
||||
"SetPasswordNow": "Nastavím heslo nyní"
|
||||
}
|
||||
}
|
||||
|
@ -70,6 +70,8 @@
|
||||
"Hello": "Hallo {name},",
|
||||
"ProcessingInvite": "Einladung wird bearbeitet, bitte warten...",
|
||||
"SignToProceed": "Bitte melden Sie sich an, um fortzufahren",
|
||||
"Proceed": "Fortfahren"
|
||||
"Proceed": "Fortfahren",
|
||||
"SetPasswordLater": "Ich werde später ein Passwort festlegen",
|
||||
"SetPasswordNow": "Ich werde jetzt ein Passwort festlegen"
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,8 @@
|
||||
"Hello": "Hello {name},",
|
||||
"ProcessingInvite": "Processing invite, please wait...",
|
||||
"SignToProceed": "Please sign in to proceed",
|
||||
"Proceed": "Proceed"
|
||||
"Proceed": "Proceed",
|
||||
"SetPasswordLater": "I'll set a password later",
|
||||
"SetPasswordNow": "I'll set a password now"
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,8 @@
|
||||
"Hello": "Hola {name},",
|
||||
"ProcessingInvite": "Procesando invitación, por favor espere...",
|
||||
"SignToProceed": "Por favor inicie sesión para continuar",
|
||||
"Proceed": "Continuar"
|
||||
"Proceed": "Continuar",
|
||||
"SetPasswordLater": "Estableceré una contraseña más tarde",
|
||||
"SetPasswordNow": "Estableceré una contraseña ahora"
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,8 @@
|
||||
"Hello": "Bonjour {name},",
|
||||
"ProcessingInvite": "Invitation en cours, veuillez patienter...",
|
||||
"SignToProceed": "Veuillez vous connecter pour continuer",
|
||||
"Proceed": "Continuer"
|
||||
"Proceed": "Continuer",
|
||||
"SetPasswordLater": "Je définirai un mot de passe plus tard",
|
||||
"SetPasswordNow": "Je définirai un mot de passe maintenant"
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,8 @@
|
||||
"Hello": "Ciao {name},",
|
||||
"ProcessingInvite": "Elaborazione invito, attendere prego...",
|
||||
"SignToProceed": "Accedi per procedere",
|
||||
"Proceed": "Procedere"
|
||||
"Proceed": "Procedere",
|
||||
"SetPasswordLater": "Imposterò una password più tardi",
|
||||
"SetPasswordNow": "Imposterò una password ora"
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,8 @@
|
||||
"Hello": "{name} さん、こんにちは",
|
||||
"ProcessingInvite": "招待を処理中です。しばらくお待ちください...",
|
||||
"SignToProceed": "続行するにはサインインしてください",
|
||||
"Proceed": "続行"
|
||||
"Proceed": "続行",
|
||||
"SetPasswordLater": "後でパスワードを設定します",
|
||||
"SetPasswordNow": "今すぐパスワードを設定します"
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,8 @@
|
||||
"Hello": "Olá {name},",
|
||||
"ProcessingInvite": "Processando convite, aguarde...",
|
||||
"SignToProceed": "Por favor, inicie sessão para continuar",
|
||||
"Proceed": "Continuar"
|
||||
"Proceed": "Continuar",
|
||||
"SetPasswordLater": "Vou definir uma senha mais tarde",
|
||||
"SetPasswordNow": "Vou definir uma senha agora"
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,8 @@
|
||||
"Hello": "Привет {name},",
|
||||
"ProcessingInvite": "Обработка приглашения, пожалуйста, подождите...",
|
||||
"SignToProceed": "Пожалуйста, войдите, чтобы продолжить",
|
||||
"Proceed": "Продолжить"
|
||||
"Proceed": "Продолжить",
|
||||
"SetPasswordLater": "Я установлю пароль позже",
|
||||
"SetPasswordNow": "Я установлю пароль сейчас"
|
||||
}
|
||||
}
|
||||
|
@ -69,6 +69,8 @@
|
||||
"Hello": "你好 {name},",
|
||||
"ProcessingInvite": "处理邀请,请稍候...",
|
||||
"SignToProceed": "请登录以继续",
|
||||
"Proceed": "继续"
|
||||
"Proceed": "继续",
|
||||
"SetPasswordLater": "稍后设置密码",
|
||||
"SetPasswordNow": "现在设置密码"
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
export const LoginEvents = {
|
||||
SignUpEmail: 'signup.viaEmail',
|
||||
SignUpOtp: 'signup.viaOtp',
|
||||
SignUpGoogle: 'signup.viaGoogle',
|
||||
SignUpGithub: 'signup.viaGitHub',
|
||||
|
||||
|
@ -55,6 +55,7 @@
|
||||
export let page: Pages = 'signup'
|
||||
|
||||
const signUpDisabled = getMetadata(login.metadata.DisableSignUp) ?? false
|
||||
const useOTP = getMetadata(presentation.metadata.MailUrl) != null && getMetadata(presentation.metadata.MailUrl) !== ''
|
||||
let navigateUrl: string | undefined
|
||||
|
||||
onDestroy(location.subscribe(updatePageLoc))
|
||||
@ -149,9 +150,9 @@
|
||||
<Scroller padding={'1rem 0'}>
|
||||
<div class="form-content">
|
||||
{#if page === 'login'}
|
||||
<LoginForm {navigateUrl} {signUpDisabled} />
|
||||
<LoginForm {navigateUrl} {signUpDisabled} {useOTP} />
|
||||
{:else if page === 'signup'}
|
||||
<SignupForm {navigateUrl} {signUpDisabled} />
|
||||
<SignupForm {navigateUrl} {signUpDisabled} {useOTP} />
|
||||
{:else if page === 'createWorkspace'}
|
||||
<CreateWorkspaceForm />
|
||||
{:else if page === 'password'}
|
||||
|
@ -25,12 +25,13 @@
|
||||
|
||||
export let navigateUrl: string | undefined = undefined
|
||||
export let signUpDisabled = false
|
||||
export let useOTP = true
|
||||
export let email: string | undefined = undefined
|
||||
export let caption: IntlString | undefined = undefined
|
||||
export let subtitle: string | undefined = undefined
|
||||
export let onLogin: ((loginInfo: LoginInfo | null, status: Status) => void | Promise<void>) | undefined = undefined
|
||||
|
||||
let method: LoginMethods = LoginMethods.Otp
|
||||
let method: LoginMethods = useOTP ? LoginMethods.Otp : LoginMethods.Password
|
||||
|
||||
function changeMethod (event: CustomEvent<LoginMethods>): void {
|
||||
method = event.detail
|
||||
|
@ -21,7 +21,7 @@
|
||||
import { LoginInfo } from '@hcengineering/account-client'
|
||||
|
||||
import Tabs from './Tabs.svelte'
|
||||
import { BottomAction, doLoginNavigate, validateOtpLogin, OtpLoginSteps, loginOtp } from '../index'
|
||||
import { BottomAction, doLoginNavigate, doValidateOtp, OtpLoginSteps, loginOtp } from '../index'
|
||||
import login from '../plugin'
|
||||
import BottomActionComponent from './BottomAction.svelte'
|
||||
import StatusControl from './StatusControl.svelte'
|
||||
@ -32,6 +32,7 @@
|
||||
export let signUpDisabled = false
|
||||
export let loginState: 'login' | 'signup' | 'none' = 'none'
|
||||
export let canChangeEmail = true
|
||||
export let password: string | undefined = undefined
|
||||
export let onLogin: ((loginInfo: LoginInfo | null, status: Status) => void | Promise<void>) | undefined = undefined
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
@ -66,7 +67,7 @@
|
||||
status = new Status(Severity.INFO, login.status.ConnectingToServer, {})
|
||||
|
||||
const otp = otpData.otp1 + otpData.otp2 + otpData.otp3 + otpData.otp4 + otpData.otp5 + otpData.otp6
|
||||
const [loginStatus, result] = await validateOtpLogin(email, otp)
|
||||
const [loginStatus, result] = await doValidateOtp(loginState === 'signup', email, otp, password)
|
||||
status = loginStatus
|
||||
|
||||
if (onLogin !== undefined) {
|
||||
|
@ -15,23 +15,24 @@
|
||||
-->
|
||||
<script lang="ts">
|
||||
import { OK, Severity, Status } from '@hcengineering/platform'
|
||||
import presentation from '@hcengineering/presentation'
|
||||
import { logIn } from '@hcengineering/workbench'
|
||||
|
||||
import BottomActionComponent from './BottomAction.svelte'
|
||||
import login from '../plugin'
|
||||
import { getPasswordValidationRules } from '../validations'
|
||||
import { goTo, signUp } from '../utils'
|
||||
import { goTo } from '../utils'
|
||||
import Form from './Form.svelte'
|
||||
import { BottomAction, LoginMethods, OtpLoginSteps, signUpOtp } from '../index'
|
||||
import { OtpLoginSteps, signUp, signUpOtp } from '../index'
|
||||
import type { Field } from '../types'
|
||||
import OtpForm from './OtpForm.svelte'
|
||||
|
||||
export let signUpDisabled = false
|
||||
export let navigateUrl: string | undefined = undefined
|
||||
export let useOTP = true // False only for dev/tests
|
||||
|
||||
let method: LoginMethods = LoginMethods.Otp
|
||||
let fields: Array<Field>
|
||||
let form: Form
|
||||
let withPassword = !useOTP
|
||||
|
||||
$: {
|
||||
fields = [
|
||||
@ -40,7 +41,7 @@
|
||||
{ id: 'email', name: 'username', i18n: login.string.Email }
|
||||
]
|
||||
|
||||
if (method === LoginMethods.Password) {
|
||||
if (withPassword) {
|
||||
fields.push({
|
||||
id: 'new-password',
|
||||
name: 'password',
|
||||
@ -71,9 +72,17 @@
|
||||
const action = {
|
||||
i18n: login.string.SignUp,
|
||||
func: async () => {
|
||||
status = new Status(Severity.INFO, login.status.ConnectingToServer, {})
|
||||
if (useOTP) {
|
||||
status = new Status(Severity.INFO, login.status.ConnectingToServer, {})
|
||||
|
||||
if (method === LoginMethods.Password) {
|
||||
const [otpStatus, result] = await signUpOtp(object.username, object.first, object.last)
|
||||
status = otpStatus
|
||||
|
||||
if (result?.sent === true && otpStatus === OK) {
|
||||
step = OtpLoginSteps.Otp
|
||||
otpRetryOn = result.retryOn
|
||||
}
|
||||
} else {
|
||||
const [loginStatus, result] = await signUp(object.username, object.password, object.first, object.last)
|
||||
|
||||
status = loginStatus
|
||||
@ -82,26 +91,17 @@
|
||||
await logIn(result)
|
||||
goTo('confirmationSend')
|
||||
}
|
||||
} else {
|
||||
const [otpStatus, result] = await signUpOtp(object.username, object.first, object.last)
|
||||
status = otpStatus
|
||||
|
||||
if (result?.sent === true && otpStatus === OK) {
|
||||
step = OtpLoginSteps.Otp
|
||||
otpRetryOn = result.retryOn
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let changeMethodAction: BottomAction
|
||||
$: changeMethodAction = {
|
||||
i18n: method === LoginMethods.Password ? login.string.SignUpWithCode : login.string.SignUpWithPassword,
|
||||
let withPasswordAction: BottomAction
|
||||
$: withPasswordAction = {
|
||||
i18n: withPassword ? login.string.SetPasswordLater : login.string.SetPasswordNow,
|
||||
func: () => {
|
||||
method = method === LoginMethods.Password ? LoginMethods.Otp : LoginMethods.Password
|
||||
if (method === LoginMethods.Password) {
|
||||
step = OtpLoginSteps.Email
|
||||
}
|
||||
withPassword = !withPassword
|
||||
step = OtpLoginSteps.Email
|
||||
|
||||
setTimeout(() => {
|
||||
if (form != null) {
|
||||
form.invalidate()
|
||||
@ -125,17 +125,27 @@
|
||||
{signUpDisabled}
|
||||
{navigateUrl}
|
||||
loginState="signup"
|
||||
password={object.password}
|
||||
retryOn={otpRetryOn}
|
||||
on:step={handleStep}
|
||||
/>
|
||||
{/if}
|
||||
|
||||
<div class="action">
|
||||
<BottomActionComponent action={changeMethodAction} />
|
||||
</div>
|
||||
{#if useOTP}
|
||||
<div class="action">
|
||||
<BottomActionComponent action={withPasswordAction} />
|
||||
</div>
|
||||
{:else}
|
||||
<div class="placeholder" />
|
||||
{/if}
|
||||
|
||||
<style lang="scss">
|
||||
.action {
|
||||
margin-left: 5rem;
|
||||
}
|
||||
|
||||
// TODO: Refactor me please
|
||||
.placeholder {
|
||||
height: 1.125rem;
|
||||
}
|
||||
</style>
|
||||
|
@ -73,6 +73,8 @@ export default mergeIds(loginId, login, {
|
||||
Hello: '' as IntlString,
|
||||
ProcessingInvite: '' as IntlString,
|
||||
SignToProceed: '' as IntlString,
|
||||
Proceed: '' as IntlString
|
||||
Proceed: '' as IntlString,
|
||||
SetPasswordLater: '' as IntlString,
|
||||
SetPasswordNow: '' as IntlString
|
||||
}
|
||||
})
|
||||
|
@ -885,23 +885,29 @@ export async function loginOtp (email: string): Promise<[Status, OtpInfo | null]
|
||||
}
|
||||
}
|
||||
|
||||
export async function validateOtpLogin (email: string, code: string): Promise<[Status, LoginInfo | null]> {
|
||||
export async function doValidateOtp (
|
||||
isSignUp: boolean,
|
||||
email: string,
|
||||
code: string,
|
||||
password?: string
|
||||
): Promise<[Status, LoginInfo | null]> {
|
||||
const telemetryEvent = isSignUp ? LoginEvents.SignUpOtp : LoginEvents.LoginOtp
|
||||
try {
|
||||
const loginInfo = await getAccountClient(null).validateOtp(email, code)
|
||||
const loginInfo = await getAccountClient(null).validateOtp(email, code, password)
|
||||
|
||||
Analytics.handleEvent(LoginEvents.LoginOtp, { email, ok: true })
|
||||
Analytics.handleEvent(telemetryEvent, { email, ok: true })
|
||||
Analytics.setUser(email)
|
||||
|
||||
return [OK, loginInfo]
|
||||
} catch (err: any) {
|
||||
if (err instanceof PlatformError) {
|
||||
Analytics.handleEvent(LoginEvents.LoginOtp, { email, ok: false })
|
||||
Analytics.handleEvent(telemetryEvent, { email, ok: false })
|
||||
await handleStatusError('Login with otp error', err.status)
|
||||
|
||||
return [err.status, null]
|
||||
} else {
|
||||
console.error('Login with otp error', err)
|
||||
Analytics.handleEvent(LoginEvents.LoginOtp, { email, ok: false })
|
||||
Analytics.handleEvent(telemetryEvent, { email, ok: false })
|
||||
Analytics.handleError(err)
|
||||
return [unknownError(err), null]
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ export class LoginPage {
|
||||
}
|
||||
|
||||
async login (email: string, password: string): Promise<void> {
|
||||
await this.loginWithPassword.click()
|
||||
await this.inputEmail.fill(email)
|
||||
await this.inputPassword.fill(password)
|
||||
expect(await this.buttonLogin.isEnabled()).toBe(true)
|
||||
|
@ -10,7 +10,6 @@ export class SignupPage {
|
||||
readonly inputRepeatNewPassword: Locator
|
||||
readonly buttonSignUp: Locator
|
||||
readonly textError: Locator
|
||||
readonly signUpPasswordBtn: Locator
|
||||
|
||||
constructor (page: Page) {
|
||||
this.page = page
|
||||
@ -21,15 +20,9 @@ export class SignupPage {
|
||||
this.inputRepeatNewPassword = page.locator('input[name="new-password"]').nth(1)
|
||||
this.buttonSignUp = page.locator('div.send button')
|
||||
this.textError = page.locator('div.ERROR > span')
|
||||
this.signUpPasswordBtn = page.locator('a', { hasText: 'Sign up with password' })
|
||||
}
|
||||
|
||||
async signupPwd (userData: UserSignUp): Promise<void> {
|
||||
const isOtp = await this.signUpPasswordBtn.isVisible()
|
||||
if (isOtp) {
|
||||
await this.signUpPasswordBtn.click()
|
||||
}
|
||||
|
||||
await this.inputFirstName.fill(userData.firstName)
|
||||
await this.inputLastName.fill(userData.lastName)
|
||||
await this.inputEmail.fill(userData.email)
|
||||
|
@ -198,6 +198,8 @@ export async function loginOtp (
|
||||
/**
|
||||
* Given an email, password, first name, and last name, creates a new account and sends a confirmation email.
|
||||
* The email confirmation is not required if the email service is not configured.
|
||||
*
|
||||
* ---------DEPRECATED. Only to be used for dev setups without mail service. Use signUpOtp instead.
|
||||
*/
|
||||
export async function signUp (
|
||||
ctx: MeasureContext,
|
||||
@ -286,9 +288,10 @@ export async function validateOtp (
|
||||
params: {
|
||||
email: string
|
||||
code: string
|
||||
password?: string
|
||||
}
|
||||
): Promise<LoginInfo> {
|
||||
const { email, code } = params
|
||||
const { email, code, password } = params
|
||||
|
||||
// Note: can support OTP based on any other social logins later
|
||||
const normalizedEmail = cleanEmail(email)
|
||||
@ -317,6 +320,9 @@ export async function validateOtp (
|
||||
if (account == null) {
|
||||
// This is a signup
|
||||
await createAccount(db, emailSocialId.personUuid, true)
|
||||
if (password != null) {
|
||||
await setPassword(ctx, db, branding, emailSocialId.personUuid as AccountUuid, password)
|
||||
}
|
||||
|
||||
ctx.info('OTP signup success', emailSocialId)
|
||||
} else {
|
||||
|
@ -273,6 +273,7 @@ export function start (
|
||||
pushPublicKey?: string
|
||||
disableSignUp?: string
|
||||
streamUrl?: string
|
||||
mailUrl?: string
|
||||
},
|
||||
port: number,
|
||||
extraConfig?: Record<string, string | undefined>
|
||||
@ -346,6 +347,7 @@ export function start (
|
||||
UPLOAD_CONFIG: config.uploadConfig,
|
||||
PUSH_PUBLIC_KEY: config.pushPublicKey,
|
||||
DISABLE_SIGNUP: config.disableSignUp,
|
||||
MAIL_URL: config.mailUrl,
|
||||
...(extraConfig ?? {})
|
||||
}
|
||||
res.status(200)
|
||||
|
@ -119,6 +119,8 @@ export function startFront (ctx: MeasureContext, extraConfig?: Record<string, st
|
||||
|
||||
const disableSignUp = process.env.DISABLE_SIGNUP
|
||||
|
||||
const mailUrl = process.env.MAIL_URL
|
||||
|
||||
const config = {
|
||||
storageAdapter,
|
||||
accountsUrl,
|
||||
@ -139,7 +141,8 @@ export function startFront (ctx: MeasureContext, extraConfig?: Record<string, st
|
||||
pushPublicKey,
|
||||
disableSignUp,
|
||||
linkPreviewUrl,
|
||||
streamUrl
|
||||
streamUrl,
|
||||
mailUrl
|
||||
}
|
||||
console.log('Starting Front service with', config)
|
||||
const shutdown = start(ctx, config, SERVER_PORT, extraConfig)
|
||||
|
@ -38,14 +38,12 @@ test.describe('login test', () => {
|
||||
test('check if user is able to go to to recovery, then login and then signup', async ({ page }) => {
|
||||
await checkIfUrlContains(page, '/login')
|
||||
await loginPage.checkIfLoginButtonIsDisabled()
|
||||
await loginPage.loginWithPassword().click()
|
||||
await loginPage.checkIfLoginButtonIsDisabled()
|
||||
await loginPage.clickOnRecover()
|
||||
await checkIfUrlContains(page, '/password')
|
||||
await loginPage.checkIfPasswordRecoveryIsVisible()
|
||||
await loginPage.clickOnRecoveryLogin()
|
||||
await checkIfUrlContains(page, '/login')
|
||||
await loginPage.loginWithPassword().click()
|
||||
await loginPage.checkIfLoginButtonIsDisabled()
|
||||
await loginPage.clickOnRecover()
|
||||
await loginPage.clickOnRecoverySignUp()
|
||||
|
@ -12,7 +12,6 @@ export class LoginPage {
|
||||
inputPassword = (): Locator => this.page.locator('input[name=current-password]')
|
||||
buttonLogin = (): Locator => this.page.locator('button', { hasText: 'Log In' })
|
||||
loginWithPassword = (): Locator => this.page.locator('a', { hasText: 'Login with password' })
|
||||
signUpWithPassword = (): Locator => this.page.locator('a', { hasText: 'Sign up with password' })
|
||||
linkSignUp = (): Locator => this.page.locator('a.title', { hasText: 'Sign Up' })
|
||||
invalidCredentialsMessage = (): Locator =>
|
||||
this.page.getByText('Account not found or the provided credentials are incorrect')
|
||||
@ -37,11 +36,8 @@ export class LoginPage {
|
||||
await (await this.page.goto(`${PlatformURI}/login/admin`))?.finished()
|
||||
}
|
||||
|
||||
async clickSignUp (usePassword: boolean = true): Promise<void> {
|
||||
async clickSignUp (): Promise<void> {
|
||||
await this.linkSignUp().click()
|
||||
if (usePassword) {
|
||||
await this.signUpWithPassword().click()
|
||||
}
|
||||
}
|
||||
|
||||
async clickOnRecover (): Promise<void> {
|
||||
@ -57,7 +53,6 @@ export class LoginPage {
|
||||
}
|
||||
|
||||
async login (email: string, password: string): Promise<void> {
|
||||
await this.loginWithPassword().click()
|
||||
await this.inputEmail().fill(email)
|
||||
await this.inputPassword().fill(password)
|
||||
expect(await this.buttonLogin().isEnabled()).toBe(true)
|
||||
|
@ -10,7 +10,6 @@ export class SignUpPage extends CommonPage {
|
||||
this.page = page
|
||||
}
|
||||
|
||||
signUpPasswordBtn = (): Locator => this.page.locator('a', { hasText: 'Sign up with password' })
|
||||
inputFirstName = (): Locator => this.page.locator('input[name="given-name"]')
|
||||
inputLastName = (): Locator => this.page.locator('input[name="family-name"]')
|
||||
inputEmail = (): Locator => this.page.locator('input[name="email"]')
|
||||
|
@ -89,9 +89,8 @@ test.describe('Workspace tests', () => {
|
||||
const newWorkspaceName = `New Workspace Name - ${generateId(2)}`
|
||||
|
||||
await loginPage.goto()
|
||||
await loginPage.clickSignUp(false)
|
||||
await loginPage.clickSignUp()
|
||||
|
||||
await signUpPage.signUpPasswordBtn().click()
|
||||
await signUpPage.checkInfo(page, 'Required field First name')
|
||||
await signUpPage.enterFirstName(newUser.firstName)
|
||||
await signUpPage.checkInfo(page, 'Required field Last name')
|
||||
|
@ -94,9 +94,8 @@ test.describe('Workspace tests', () => {
|
||||
const newWorkspaceName = `New Workspace Name - ${generateId(2)}`
|
||||
|
||||
await loginPage.goto()
|
||||
await loginPage.clickSignUp(false)
|
||||
await loginPage.clickSignUp()
|
||||
|
||||
await signUpPage.signUpPasswordBtn().click()
|
||||
await signUpPage.checkInfo(page, 'Required field First name')
|
||||
await signUpPage.enterFirstName(newUser.firstName)
|
||||
await signUpPage.checkInfo(page, 'Required field Last name')
|
||||
|
Loading…
Reference in New Issue
Block a user