UBERF-9400: Show name on login screen (#8013)

Signed-off-by: Alexey Zinoviev <alexey.zinoviev@xored.com>
This commit is contained in:
Alexey Zinoviev 2025-02-17 15:42:01 +04:00 committed by GitHub
parent b487cb949b
commit 5165ae71f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 137 additions and 14 deletions

View File

@ -1,7 +1,16 @@
import { WorkspaceDataId, WorkspaceUuid, type AccountRole, type PersonUuid, type Timestamp } from '@hcengineering/core'
import {
PersonId,
WorkspaceDataId,
WorkspaceUuid,
type AccountRole,
type PersonUuid,
type Timestamp
} from '@hcengineering/core'
export interface LoginInfo {
account: PersonUuid
name?: string
socialId?: PersonId
token?: string
}

View File

@ -20,7 +20,15 @@
import { workbenchId } from '@hcengineering/workbench'
import { onMount } from 'svelte'
import login from '../plugin'
import { createWorkspace, getAccount, getRegionInfo, goTo, setLoginInfo, type RegionInfo } from '../utils'
import {
createWorkspace,
getAccount,
getRegionInfo,
goTo,
setLoginInfo,
getAccountDisplayName,
type RegionInfo
} from '../utils'
import Form from './Form.svelte'
const fields = [
@ -77,7 +85,7 @@
{fields}
{object}
{action}
subtitle={loginInfo?.account}
subtitle={getAccountDisplayName(loginInfo)}
bottomActions={[
{
caption: login.string.HaveWorkspace,

View File

@ -40,7 +40,8 @@
getWorkspaces,
goTo,
navigateToWorkspace,
selectWorkspace
selectWorkspace,
getAccountDisplayName
} from '../utils'
import StatusControl from './StatusControl.svelte'
@ -129,8 +130,8 @@
<form class="container" style:padding={$deviceInfo.docWidth <= 480 ? '1.25rem' : '5rem'}>
<div class="grow-separator" />
<div class="fs-title">
{#if account?.account}
{account.account}
{#if account != null}
{getAccountDisplayName(account)}
{:else}
<Label label={login.string.LoadingAccount} />
{/if}

View File

@ -21,7 +21,8 @@ import {
type Doc,
type Ref,
type WorkspaceInfoWithStatus,
type WorkspaceUserOperation
type WorkspaceUserOperation,
parseSocialIdString
} from '@hcengineering/core'
import type { LoginInfo, OtpInfo, WorkspaceLoginInfo, AccountClient, RegionInfo } from '@hcengineering/account-client'
import { getClient as getAccountClientRaw } from '@hcengineering/account-client'
@ -900,3 +901,20 @@ export async function doLoginNavigate (
export function isWorkspaceLoginInfo (info: WorkspaceLoginInfo | LoginInfo | null): info is WorkspaceLoginInfo {
return (info as any)?.workspace !== undefined
}
export function getAccountDisplayName (loginInfo: LoginInfo | null): string {
if (loginInfo == null) {
return ''
}
if (loginInfo.name != null) {
return loginInfo.name
}
if (loginInfo.socialId != null) {
const { value } = parseSocialIdString(loginInfo.socialId)
return value
}
return loginInfo.account
}

View File

@ -32,7 +32,8 @@ import {
type WorkspaceMemberInfo,
type WorkspaceMode,
type WorkspaceUuid,
type PersonId
type PersonId,
buildSocialIdString
} from '@hcengineering/core'
import platform, {
getMetadata,
@ -89,7 +90,8 @@ import {
signUpByEmail,
verifyPassword,
wrap,
verifyAllowedServices
verifyAllowedServices,
getPersonName
} from './utils'
import { isAdminEmail } from './admin'
@ -125,6 +127,11 @@ export async function login (
throw new PlatformError(new Status(Severity.ERROR, platform.status.AccountNotFound, {}))
}
const person = await db.person.findOne({ uuid: emailSocialId.personUuid })
if (person == null) {
throw new PlatformError(new Status(Severity.ERROR, platform.status.InternalServerError, {}))
}
if (!verifyPassword(password, existingAccount.hash, existingAccount.salt)) {
throw new PlatformError(new Status(Severity.ERROR, platform.status.AccountNotFound, {}))
}
@ -136,7 +143,9 @@ export async function login (
return {
account: existingAccount.uuid,
token: isConfirmed ? generateToken(existingAccount.uuid, undefined, extraToken) : undefined
token: isConfirmed ? generateToken(existingAccount.uuid, undefined, extraToken) : undefined,
name: getPersonName(person),
socialId: emailSocialId.key
}
} catch (err: any) {
Analytics.handleError(err)
@ -185,6 +194,10 @@ export async function signUp (
lastName: string
): Promise<LoginInfo> {
const account = await signUpByEmail(ctx, db, branding, email, password, firstName, lastName)
const person = await db.person.findOne({ uuid: account })
if (person == null) {
throw new PlatformError(new Status(Severity.ERROR, platform.status.InternalServerError, {}))
}
const sesURL = getMetadata(accountPlugin.metadata.SES_URL)
const forceConfirmation = sesURL !== undefined && sesURL !== ''
@ -199,6 +212,8 @@ export async function signUp (
return {
account,
name: getPersonName(person),
socialId: buildSocialIdString({ type: SocialIdType.EMAIL, value: email }),
token: !forceConfirmation ? generateToken(account) : undefined
}
}
@ -277,8 +292,15 @@ export async function validateOtp (
ctx.info('OTP login success', emailSocialId)
}
const person = await db.person.findOne({ uuid: emailSocialId.personUuid })
if (person == null) {
throw new PlatformError(new Status(Severity.ERROR, platform.status.InternalServerError, {}))
}
return {
account: emailSocialId.personUuid,
name: getPersonName(person),
socialId: emailSocialId.key,
token: generateToken(emailSocialId.personUuid)
}
}
@ -308,8 +330,15 @@ export async function createWorkspace (
ctx.info('Creating workspace record done', { workspaceName, region, account: socialId.personUuid })
const person = await db.person.findOne({ uuid: socialId.personUuid })
if (person == null) {
throw new PlatformError(new Status(Severity.ERROR, platform.status.InternalServerError, {}))
}
return {
account,
socialId: socialId.key,
name: getPersonName(person),
token: generateToken(account, workspaceUuid),
endpoint: getEndpoint(ctx, workspaceUuid, region, EndpointKind.External),
workspace: workspaceUuid,
@ -535,8 +564,15 @@ export async function confirm (
await confirmEmail(ctx, db, account, email)
const person = await db.person.findOne({ uuid: account })
if (person == null) {
throw new PlatformError(new Status(Severity.ERROR, platform.status.InternalServerError, {}))
}
const result = {
account,
name: getPersonName(person),
socialId: buildSocialIdString({ type: SocialIdType.EMAIL, value: email }),
token: generateToken(account)
}
@ -696,8 +732,14 @@ export async function leaveWorkspace (
ctx.info('Account removed from workspace', { targetAccount, workspace })
if (account === targetAccount) {
const person = await db.person.findOne({ uuid: account })
if (person == null) {
throw new PlatformError(new Status(Severity.ERROR, platform.status.InternalServerError, {}))
}
return {
account,
name: getPersonName(person),
token: generateToken(account, undefined)
}
}
@ -973,11 +1015,11 @@ export async function getLoginInfoByToken (
const isDocGuest = accountUuid === GUEST_ACCOUNT && extra?.guest === 'true'
const isSystem = accountUuid === systemAccountUuid
let socialId: SocialId | null = null
if (!isDocGuest && !isSystem) {
// Any confirmed social ID will do
const socialId = await db.socialId.findOne({ personUuid: accountUuid, verifiedOn: { $gt: 0 } })
socialId = await db.socialId.findOne({ personUuid: accountUuid, verifiedOn: { $gt: 0 } })
if (socialId == null) {
return {
account: accountUuid
@ -985,8 +1027,31 @@ export async function getLoginInfoByToken (
}
}
let person: Person | null
if (isDocGuest) {
person = {
uuid: accountUuid,
firstName: 'Guest',
lastName: 'User'
}
} else if (isSystem) {
person = {
uuid: accountUuid,
firstName: 'System',
lastName: 'User'
}
} else {
person = await db.person.findOne({ uuid: accountUuid })
}
if (person == null) {
throw new PlatformError(new Status(Severity.ERROR, platform.status.InternalServerError, {}))
}
const loginInfo = {
account: accountUuid,
name: getPersonName(person),
socialId: socialId?.key,
token
}
@ -1080,7 +1145,7 @@ export async function getPersonInfo (
return {
personUuid: account,
name: `${person?.firstName} ${person?.lastName}`, // Should we control the order by config?
name: getPersonName(person),
socialIds: verifiedSocialIds.map((it) => it.key)
}
}

View File

@ -227,6 +227,8 @@ export type WorkspaceEvent =
export type WorkspaceOperation = 'create' | 'upgrade' | 'all' | 'all+backup'
export interface LoginInfo {
account: PersonUuid
name?: string
socialId?: PersonId
token?: string
}

View File

@ -28,7 +28,9 @@ import {
type WorkspaceInfoWithStatus as WorkspaceInfoWithStatusCore,
isActiveMode,
type PersonUuid,
type PersonId
type PersonId,
type Person,
buildSocialIdString
} from '@hcengineering/core'
import { getMongoClient } from '@hcengineering/mongo' // TODO: get rid of this import later
import platform, { getMetadata, PlatformError, Severity, Status, translate } from '@hcengineering/platform'
@ -563,6 +565,11 @@ export async function selectWorkspace (
}
}
const person = await db.person.findOne({ uuid: accountUuid })
if (person == null) {
throw new PlatformError(new Status(Severity.ERROR, platform.status.InternalServerError, {}))
}
return {
account: accountUuid,
token: generateToken(accountUuid, workspace.uuid, extra),
@ -970,6 +977,12 @@ export async function loginOrSignUpWithProvider (
throw new PlatformError(new Status(Severity.ERROR, platform.status.InternalServerError, {}))
}
const person = await db.person.findOne({ uuid: personUuid })
if (person == null) {
throw new PlatformError(new Status(Severity.ERROR, platform.status.InternalServerError, {}))
}
const account = await db.account.findOne({ uuid: personUuid })
if (account == null) {
@ -1011,6 +1024,8 @@ export async function loginOrSignUpWithProvider (
return {
account: personUuid,
socialId: buildSocialIdString(socialId),
name: getPersonName(person),
token: generateToken(personUuid)
}
}
@ -1119,3 +1134,8 @@ export function verifyAllowedServices (services: string[], extra: any): void {
throw new PlatformError(new Status(Severity.ERROR, platform.status.Forbidden, {}))
}
}
export function getPersonName (person: Person): string {
// Should we control the order by config?
return `${person.firstName} ${person.lastName}`
}