From 81e02eb8ca8513bf36abfbcf158414887f12784a Mon Sep 17 00:00:00 2001 From: Denis Bykhov Date: Tue, 15 Oct 2024 00:44:06 +0500 Subject: [PATCH 01/19] Fix calendar and gmail services (#6918) Signed-off-by: Denis Bykhov --- .../calendar/pod-calendar/src/calendar.ts | 1 - .../pod-calendar/src/calendarController.ts | 55 +++++++++++++++--- services/calendar/pod-calendar/src/config.ts | 5 +- services/gmail/pod-gmail/src/config.ts | 5 +- services/gmail/pod-gmail/src/gmail.ts | 2 +- .../gmail/pod-gmail/src/gmailController.ts | 57 ++++++++++++++++--- .../gmail/pod-gmail/src/workspaceClient.ts | 7 ++- 7 files changed, 112 insertions(+), 20 deletions(-) diff --git a/services/calendar/pod-calendar/src/calendar.ts b/services/calendar/pod-calendar/src/calendar.ts index 05b0672ae3..3e1b75b90a 100644 --- a/services/calendar/pod-calendar/src/calendar.ts +++ b/services/calendar/pod-calendar/src/calendar.ts @@ -102,7 +102,6 @@ export class CalendarClient { await calendarClient.setToken(user) await calendarClient.refreshToken() await calendarClient.addClient() - void calendarClient.startSync() } return calendarClient } diff --git a/services/calendar/pod-calendar/src/calendarController.ts b/services/calendar/pod-calendar/src/calendarController.ts index b13d08fe23..55b5f2e3e6 100644 --- a/services/calendar/pod-calendar/src/calendarController.ts +++ b/services/calendar/pod-calendar/src/calendarController.ts @@ -13,7 +13,7 @@ // limitations under the License. // -import { Account, Ref } from '@hcengineering/core' +import { Account, RateLimiter, Ref } from '@hcengineering/core' import { type Db } from 'mongodb' import { type CalendarClient } from './calendar' import config from './config' @@ -25,6 +25,7 @@ export class CalendarController { private readonly credentials: ProjectCredentials private readonly clients: Map = new Map() + private readonly initLimitter = new RateLimiter(config.InitLimit) protected static _instance: CalendarController @@ -43,17 +44,57 @@ export class CalendarController { async startAll (): Promise { const tokens = await this.mongo.collection('tokens').find().toArray() + const groups = new Map() + console.log('start calendar service', tokens.length) for (const token of tokens) { - try { - await this.createClient(token) - } catch (err) { - console.error(`Couldn't create client for ${token.workspace} ${token.userId}`) + const group = groups.get(token.workspace) + if (group === undefined) { + groups.set(token.workspace, [token]) + } else { + group.push(token) + groups.set(token.workspace, group) } } - for (const client of this.workspaces.values()) { - void client.sync() + const limiter = new RateLimiter(config.InitLimit) + + for (const [workspace, tokens] of groups) { + await limiter.add(async () => { + const startPromise = this.startWorkspace(workspace, tokens) + const timeoutPromise = new Promise((resolve) => { + setTimeout(() => { + resolve() + }, 60000) + }) + await Promise.race([startPromise, timeoutPromise]) + }) } + + await limiter.waitProcessing() + console.log('Calendar service started') + } + + async startWorkspace (workspace: string, tokens: Token[]): Promise { + const workspaceClient = await this.getWorkspaceClient(workspace) + const clients: CalendarClient[] = [] + for (const token of tokens) { + try { + const timeout = setTimeout(() => { + console.log('init client hang', token.workspace, token.userId) + }, 60000) + const client = await workspaceClient.createCalendarClient(token) + clearTimeout(timeout) + clients.push(client) + } catch (err) { + console.error(`Couldn't create client for ${workspace} ${token.userId}`) + } + } + for (const client of clients) { + void this.initLimitter.add(async () => { + await client.startSync() + }) + } + void workspaceClient.sync() } push (email: string, mode: 'events' | 'calendar', calendarId?: string): void { diff --git a/services/calendar/pod-calendar/src/config.ts b/services/calendar/pod-calendar/src/config.ts index 1647c9cfd9..e93fb08446 100644 --- a/services/calendar/pod-calendar/src/config.ts +++ b/services/calendar/pod-calendar/src/config.ts @@ -24,6 +24,7 @@ interface Config { Credentials: string WATCH_URL: string SystemEmail: string + InitLimit: number } const envMap: { [key in keyof Config]: string } = { @@ -37,7 +38,8 @@ const envMap: { [key in keyof Config]: string } = { Secret: 'SECRET', Credentials: 'Credentials', SystemEmail: 'SYSTEM_EMAIL', - WATCH_URL: 'WATCH_URL' + WATCH_URL: 'WATCH_URL', + InitLimit: 'INIT_LIMIT' } const parseNumber = (str: string | undefined): number | undefined => (str !== undefined ? Number(str) : undefined) @@ -52,6 +54,7 @@ const config: Config = (() => { Secret: process.env[envMap.Secret], SystemEmail: process.env[envMap.SystemEmail] ?? 'anticrm@hc.engineering', Credentials: process.env[envMap.Credentials], + InitLimit: parseNumber(process.env[envMap.InitLimit]) ?? 50, WATCH_URL: process.env[envMap.WATCH_URL] } diff --git a/services/gmail/pod-gmail/src/config.ts b/services/gmail/pod-gmail/src/config.ts index faba0c357b..3d98317309 100644 --- a/services/gmail/pod-gmail/src/config.ts +++ b/services/gmail/pod-gmail/src/config.ts @@ -26,6 +26,7 @@ interface Config { WATCH_TOPIC_NAME: string SystemEmail: string FooterMessage: string + InitLimit: number } const envMap: { [key in keyof Config]: string } = { @@ -40,7 +41,8 @@ const envMap: { [key in keyof Config]: string } = { Credentials: 'Credentials', SystemEmail: 'SYSTEM_EMAIL', WATCH_TOPIC_NAME: 'WATCH_TOPIC_NAME', - FooterMessage: 'FOOTER_MESSAGE' + FooterMessage: 'FOOTER_MESSAGE', + InitLimit: 'INIT_LIMIT' } const parseNumber = (str: string | undefined): number | undefined => (str !== undefined ? Number(str) : undefined) @@ -56,6 +58,7 @@ const config: Config = (() => { SystemEmail: process.env[envMap.SystemEmail] ?? 'anticrm@hc.engineering', Credentials: process.env[envMap.Credentials], WATCH_TOPIC_NAME: process.env[envMap.WATCH_TOPIC_NAME], + InitLimit: parseNumber(process.env[envMap.InitLimit]) ?? 50, FooterMessage: process.env[envMap.FooterMessage] ?? '

Sent via Huly

' } diff --git a/services/gmail/pod-gmail/src/gmail.ts b/services/gmail/pod-gmail/src/gmail.ts index f8d84a1789..8d7c80be4e 100644 --- a/services/gmail/pod-gmail/src/gmail.ts +++ b/services/gmail/pod-gmail/src/gmail.ts @@ -211,6 +211,7 @@ export class GmailClient { await this.setToken(token.tokens) await this.refreshToken() await this.addClient() + void this.startSync() void this.getNewMessagesAfterAuth() const me = await this.getMe() @@ -385,7 +386,6 @@ export class GmailClient { private async addClient (): Promise { try { const me = await this.getMe() - void this.startSync() const controller = GmailController.getGmailController() controller.addClient(me, this) } catch (err) { diff --git a/services/gmail/pod-gmail/src/gmailController.ts b/services/gmail/pod-gmail/src/gmailController.ts index 62a29286e4..8be43cdd5c 100644 --- a/services/gmail/pod-gmail/src/gmailController.ts +++ b/services/gmail/pod-gmail/src/gmailController.ts @@ -13,7 +13,7 @@ // limitations under the License. // -import { MeasureContext } from '@hcengineering/core' +import { MeasureContext, RateLimiter } from '@hcengineering/core' import type { StorageAdapter } from '@hcengineering/server-core' import { type Db } from 'mongodb' @@ -28,6 +28,7 @@ export class GmailController { private readonly credentials: ProjectCredentials private readonly clients: Map = new Map() + private readonly initLimitter = new RateLimiter(config.InitLimit) protected static _instance: GmailController @@ -56,19 +57,57 @@ export class GmailController { async startAll (): Promise { const tokens = await this.mongo.collection('tokens').find().toArray() + const groups = new Map() + console.log('start gmail service', tokens.length) for (const token of tokens) { - try { - await this.createClient(token) - } catch (err) { - console.error(`Couldn't create client for ${token.workspace} ${token.userId}`) + const group = groups.get(token.workspace) + if (group === undefined) { + groups.set(token.workspace, [token]) + } else { + group.push(token) + groups.set(token.workspace, group) } } - for (const client of this.workspaces.values()) { - void client.checkUsers().then(async () => { - await client.getNewMessages() + const limiter = new RateLimiter(config.InitLimit) + for (const [workspace, tokens] of groups) { + await limiter.add(async () => { + const startPromise = this.startWorkspace(workspace, tokens) + const timeoutPromise = new Promise((resolve) => { + setTimeout(() => { + resolve() + }, 60000) + }) + await Promise.race([startPromise, timeoutPromise]) }) } + + await limiter.waitProcessing() + } + + async startWorkspace (workspace: string, tokens: Token[]): Promise { + const workspaceClient = await this.getWorkspaceClient(workspace) + const clients: GmailClient[] = [] + for (const token of tokens) { + try { + const timeout = setTimeout(() => { + console.log('init client hang', token.workspace, token.userId) + }, 60000) + const client = await workspaceClient.createGmailClient(token) + clearTimeout(timeout) + clients.push(client) + } catch (err) { + console.error(`Couldn't create client for ${workspace} ${token.userId}`) + } + } + for (const client of clients) { + void this.initLimitter.add(async () => { + await client.startSync() + }) + } + void workspaceClient.checkUsers().then(async () => { + await workspaceClient.getNewMessages() + }) } push (message: string): void { @@ -121,8 +160,10 @@ export class GmailController { let res = this.workspaces.get(workspace) if (res === undefined) { try { + console.log('create workspace worker for', workspace) res = await WorkspaceClient.create(this.ctx, this.credentials, this.mongo, this.storageAdapter, workspace) this.workspaces.set(workspace, res) + console.log('created workspace worker for', workspace) } catch (err) { console.error(`Couldn't create workspace worker for ${workspace}, reason: `, err) throw err diff --git a/services/gmail/pod-gmail/src/workspaceClient.ts b/services/gmail/pod-gmail/src/workspaceClient.ts index d18c7c78c5..c5df09a49a 100644 --- a/services/gmail/pod-gmail/src/workspaceClient.ts +++ b/services/gmail/pod-gmail/src/workspaceClient.ts @@ -159,11 +159,15 @@ export class WorkspaceClient { const newMessages = await this.client.findAll(gmailP.class.NewMessage, { status: 'new' }) + console.log('get new messages, recieved', this.workspace, newMessages.length) await this.subscribeMessages() for (const message of newMessages) { - const client = this.getGmailClient(message.from ?? message.createdBy ?? message.modifiedBy) + const from = message.from ?? message.createdBy ?? message.modifiedBy + const client = this.getGmailClient(from) if (client !== undefined) { await client.createMessage(message) + } else { + console.log('client not found, skip message', this.workspace, from, message._id) } } } @@ -342,6 +346,7 @@ export class WorkspaceClient { await this.txEmployeeHandler(tx) } }) + console.log('deactivate users', this.workspace, accounts.length) } private async deactivateUser (acc: PersonAccount): Promise { From a714be51e9cc8f4e3dfde31df9d8fa8aef8817f8 Mon Sep 17 00:00:00 2001 From: Andrey Sobolev Date: Tue, 15 Oct 2024 12:04:39 +0700 Subject: [PATCH 02/19] UBERF-8469: Fix exit from github service (#6921) Signed-off-by: Andrey Sobolev --- services/github/pod-github/package.json | 4 ++-- services/github/pod-github/run.sh | 13 +++++++++++++ services/github/pod-github/src/index.ts | 15 +++++++++++---- services/github/pod-github/src/platform.ts | 1 + services/github/pod-github/src/server.ts | 9 +++++++-- .../github/pod-github/src/sync/comments.ts | 6 ++++++ .../github/pod-github/src/sync/issueBase.ts | 2 +- services/github/pod-github/src/sync/issues.ts | 9 +++++++++ .../github/pod-github/src/sync/projects.ts | 6 ++++++ .../pod-github/src/sync/pullrequests.ts | 6 ++++++ services/github/pod-github/src/sync/users.ts | 6 ++++++ services/github/pod-github/src/types.ts | 2 ++ services/github/pod-github/src/worker.ts | 19 +++++++++++++++++++ 13 files changed, 89 insertions(+), 9 deletions(-) create mode 100755 services/github/pod-github/run.sh diff --git a/services/github/pod-github/package.json b/services/github/pod-github/package.json index 39de621832..3dc820dff0 100644 --- a/services/github/pod-github/package.json +++ b/services/github/pod-github/package.json @@ -17,12 +17,12 @@ "_phase:bundle": "rushx bundle", "_phase:docker-build": "rushx docker:build", "_phase:docker-staging": "rushx docker:staging", - "bundle": "mkdir -p bundle && esbuild src/index.ts --bundle --platform=node --outfile=bundle/bundle.js --log-level=error --sourcemap=external", + "bundle": "mkdir -p bundle && esbuild src/index.ts --keep-names --bundle --platform=node --outfile=bundle/bundle.js --log-level=error --sourcemap=external", "docker:build": "../../../common/scripts/docker_build.sh hardcoreeng/github", "docker:staging": "../../../common/scripts/docker_tag.sh hardcoreeng/github staging", "docker:push": "../../../common/scripts/docker_tag.sh hardcoreeng/github", "docker:tbuild": "rush bundle --to @hcengineering/pod-github && docker build -t hardcoreeng/github . --platform=linux/amd64 && ../../../common/scripts/docker_tag_push.sh hardcoreeng/github", - "run-local": "cross-env APP_ID=$(cat ../../../../uberflow_private/appid) PRIVATE_KEY=\"$(cat ../../../../uberflow_private/private-key.pem)\" CLIENT_ID=$(cat ../../../../uberflow_private/client-id) CLIENT_SECRET=$(cat ../../../../uberflow_private/client-secret) SERVER_SECRET=secret ACCOUNTS_URL=http://localhost:3000/ COLLABORATOR_URL=http://localhost:3078 MINIO_ACCESS_KEY=minioadmin MINIO_SECRET_KEY=minioadmin MINIO_ENDPOINT=localhost ts-node src/index.ts", + "run-local": "ruh.sh", "format": "format src", "_phase:build": "compile transpile src", "_phase:test": "jest --passWithNoTests --silent", diff --git a/services/github/pod-github/run.sh b/services/github/pod-github/run.sh new file mode 100755 index 0000000000..ebc9faf4f9 --- /dev/null +++ b/services/github/pod-github/run.sh @@ -0,0 +1,13 @@ +export APP_ID="$POD_GITHUB_APPID" +export CLIENT_ID="$POD_GITHUB_CLIENTID" +export CLIENT_SECRET="$POD_GITHUB_CLIENT_SECRET" +export PRIVATE_KEY="$POD_GITHUB_PRIVATE_KEY" +export SERVER_SECRET=secret +export ACCOUNTS_URL=http://localhost:3000 +export COLLABORATOR_URL=http://localhost:3078 +export MINIO_ACCESS_KEY=minioadminchmo +export MINIO_SECRET_KEY=minioadmin +export MINIO_ENDPOINT=localhost +export MONGO_URL=mongodb://localhost:27017 +rush bundle --to @hcengineering/pod-github +node $@ bundle/bundle.js \ No newline at end of file diff --git a/services/github/pod-github/src/index.ts b/services/github/pod-github/src/index.ts index fa038ef824..e154398a93 100644 --- a/services/github/pod-github/src/index.ts +++ b/services/github/pod-github/src/index.ts @@ -2,14 +2,14 @@ // Copyright © 2023 Hardcore Engineering Inc. // -import { MeasureMetricsContext, metricsToString, newMetrics } from '@hcengineering/core' +import { Analytics } from '@hcengineering/analytics' import { SplitLogger, configureAnalytics } from '@hcengineering/analytics-service' +import { MeasureMetricsContext, metricsToString, newMetrics } from '@hcengineering/core' +import { loadBrandingMap } from '@hcengineering/server-core' import { writeFile } from 'fs/promises' import { join } from 'path' import config from './config' import { start } from './server' -import { Analytics } from '@hcengineering/analytics' -import { loadBrandingMap } from '@hcengineering/server-core' // Load and inc startID, to have easy logs. @@ -39,11 +39,18 @@ const intTimer = setInterval(() => { } }, 30000) -void start(metricsContext, loadBrandingMap(config.BrandingPath)) +let doOnClose: () => Promise = async () => {} + +void start(metricsContext, loadBrandingMap(config.BrandingPath)).then((r) => { + doOnClose = r +}) const onClose = (): void => { clearInterval(intTimer) metricsContext.info('Closed') + void doOnClose().then((r) => { + process.exit(0) + }) } process.on('uncaughtException', (e) => { diff --git a/services/github/pod-github/src/platform.ts b/services/github/pod-github/src/platform.ts index f525fdf803..6b1c6ed307 100644 --- a/services/github/pod-github/src/platform.ts +++ b/services/github/pod-github/src/platform.ts @@ -96,6 +96,7 @@ export class PlatformWorker { async close (): Promise { this.canceled = true + clearInterval(this.periodicSyncInterval) await Promise.all( [...this.clients.values()].map(async (worker) => { await worker.close() diff --git a/services/github/pod-github/src/server.ts b/services/github/pod-github/src/server.ts index b0d8d0d9ae..df41cd0a25 100644 --- a/services/github/pod-github/src/server.ts +++ b/services/github/pod-github/src/server.ts @@ -18,7 +18,7 @@ import { decodeToken } from '@hcengineering/server-token' /** * @public */ -export async function start (ctx: MeasureContext, brandingMap: BrandingMap): Promise { +export async function start (ctx: MeasureContext, brandingMap: BrandingMap): Promise<() => Promise> { // Create an authenticated Octokit client authenticated as a GitHub App ctx.info('Running Huly Github integration', { appId: config.AppID, clientID: config.ClientID }) @@ -184,8 +184,13 @@ export async function start (ctx: MeasureContext, brandingMap: BrandingMap): Pro } }) - app.listen(port, () => { + const server = app.listen(port, () => { ctx.info(`Server is listening for events at: ${localWebhookUrl}`) ctx.info('Press Ctrl + C to quit.') }) + + return async () => { + await worker.close() + server.close() + } } diff --git a/services/github/pod-github/src/sync/comments.ts b/services/github/pod-github/src/sync/comments.ts index cf525d0903..3492c30599 100644 --- a/services/github/pod-github/src/sync/comments.ts +++ b/services/github/pod-github/src/sync/comments.ts @@ -457,6 +457,9 @@ export class CommentSyncManager implements DocSyncManager { repositories: GithubIntegrationRepository[] ): Promise { for (const repo of repositories) { + if (this.provider.isClosing()) { + break + } const syncKey = `${repo._id}:comment` if (repo.githubProject === undefined || !repo.enabled || integration.synchronized.has(syncKey)) { if (!repo.enabled) { @@ -487,6 +490,9 @@ export class CommentSyncManager implements DocSyncManager { }) try { for await (const data of i) { + if (this.provider.isClosing()) { + break + } const comments: CommentExternalData[] = data.data as any this.ctx.info('retrieve comments for', { repo: repo.name, diff --git a/services/github/pod-github/src/sync/issueBase.ts b/services/github/pod-github/src/sync/issueBase.ts index f2e9c9278a..0ff45f0f96 100644 --- a/services/github/pod-github/src/sync/issueBase.ts +++ b/services/github/pod-github/src/sync/issueBase.ts @@ -815,7 +815,7 @@ export abstract class IssueSyncManagerBase { // Collect field update. for (const [k, v] of Object.entries(platformUpdate)) { - const mapping = target.mappings.find((it) => it.name === k) + const mapping = target.mappings.filter((it) => it != null).find((it) => it.name === k) if (mapping === undefined) { continue } diff --git a/services/github/pod-github/src/sync/issues.ts b/services/github/pod-github/src/sync/issues.ts index c981910720..290ce7ed15 100644 --- a/services/github/pod-github/src/sync/issues.ts +++ b/services/github/pod-github/src/sync/issues.ts @@ -985,6 +985,9 @@ export class IssueSyncManager extends IssueSyncManagerBase implements DocSyncMan let partsize = 50 try { while (true) { + if (this.provider.isClosing()) { + break + } const idsPart = ids.splice(0, partsize) if (idsPart.length === 0) { break @@ -1080,6 +1083,9 @@ export class IssueSyncManager extends IssueSyncManagerBase implements DocSyncMan repositories: GithubIntegrationRepository[] ): Promise { for (const repo of repositories) { + if (this.provider.isClosing()) { + break + } const prj = projects.find((it) => repo.githubProject === it._id) if (prj === undefined) { continue @@ -1128,6 +1134,9 @@ export class IssueSyncManager extends IssueSyncManagerBase implements DocSyncMan ) try { for await (const data of i) { + if (this.provider.isClosing()) { + break + } const issues: IssueExternalData[] = data.repository.issues.nodes if (issues.some((issue) => issue.url === undefined && Object.keys(issue).length === 0)) { this.ctx.error('empty document content', { diff --git a/services/github/pod-github/src/sync/projects.ts b/services/github/pod-github/src/sync/projects.ts index 6833820794..4748b1e41a 100644 --- a/services/github/pod-github/src/sync/projects.ts +++ b/services/github/pod-github/src/sync/projects.ts @@ -376,6 +376,9 @@ export class ProjectsSyncManager implements DocSyncManager { repositories: GithubIntegrationRepository[] ): Promise { for (const prj of projects) { + if (this.provider.isClosing()) { + break + } // Wait global project sync await integration.syncLock.get(prj._id) @@ -449,6 +452,9 @@ export class ProjectsSyncManager implements DocSyncManager { (it) => it.space === prj._id ) for (const m of milestones) { + if (this.provider.isClosing()) { + break + } try { let { projectStructure, wasUpdates } = await this.ctx.withLog( 'update project structure', diff --git a/services/github/pod-github/src/sync/pullrequests.ts b/services/github/pod-github/src/sync/pullrequests.ts index 8ef9fd275d..51d3e78d54 100644 --- a/services/github/pod-github/src/sync/pullrequests.ts +++ b/services/github/pod-github/src/sync/pullrequests.ts @@ -1433,6 +1433,9 @@ export class PullRequestSyncManager extends IssueSyncManagerBase implements DocS repositories: GithubIntegrationRepository[] ): Promise { for (const repo of repositories) { + if (this.provider.isClosing()) { + break + } const prj = projects.find((it) => repo.githubProject === it._id) if (prj === undefined) { continue @@ -1518,6 +1521,9 @@ export class PullRequestSyncManager extends IssueSyncManagerBase implements DocS } ) for await (const data of pullRequestIterator) { + if (this.provider.isClosing()) { + break + } const issues: PullRequestExternalData[] = data.repository.pullRequests.nodes this.ctx.info('retrieve pull requests for', { repo: repo.name, diff --git a/services/github/pod-github/src/sync/users.ts b/services/github/pod-github/src/sync/users.ts index 94f5d43b72..b018dce4fa 100644 --- a/services/github/pod-github/src/sync/users.ts +++ b/services/github/pod-github/src/sync/users.ts @@ -60,6 +60,9 @@ export class UsersSyncManager implements DocSyncManager { repositories: GithubIntegrationRepository[] ): Promise { for (const repo of repositories) { + if (this.provider.isClosing()) { + break + } const syncKey = `${repo._id}:users` if ( repo.githubProject === undefined || @@ -107,6 +110,9 @@ export class UsersSyncManager implements DocSyncManager { ) try { for await (const data of assignableUsersIterator) { + if (this.provider.isClosing()) { + break + } const users: UserInfo[] = data.repository[key]?.nodes ?? [] for (const d of users) { if (d.login !== undefined) { diff --git a/services/github/pod-github/src/types.ts b/services/github/pod-github/src/types.ts index 13d33177b5..f4e24fddc9 100644 --- a/services/github/pod-github/src/types.ts +++ b/services/github/pod-github/src/types.ts @@ -129,6 +129,8 @@ export interface IntegrationManager { getProjectRepositories: (space: Ref) => Promise getRepositoryById: (ref?: Ref | null) => Promise + + isClosing: () => boolean } export type ExternalSyncField = 'externalVersion' | 'derivedVersion' diff --git a/services/github/pod-github/src/worker.ts b/services/github/pod-github/src/worker.ts index db5f974876..1ef7acdc63 100644 --- a/services/github/pod-github/src/worker.ts +++ b/services/github/pod-github/src/worker.ts @@ -117,11 +117,18 @@ export class GithubWorker implements IntegrationManager { personMapper: UsersSyncManager + isClosing (): boolean { + return this.closing + } + async close (): Promise { clearInterval(this.periodicTimer) this.closing = true + this.ctx.warn('Closing', { workspace: this.workspace.name }) + this.triggerSync() await this.syncPromise + this.ctx.warn('ClosingDone', { workspace: this.workspace.name }) await this.client.close() } @@ -1347,6 +1354,9 @@ export class GithubWorker implements IntegrationManager { } private async waitChanges (): Promise { + if (this.closing) { + return + } if (this.triggerRequests > 0 || this.updateRequests > 0) { this.ctx.info('Trigger check pending:', { requests: this.triggerRequests, @@ -1404,6 +1414,9 @@ export class GithubWorker implements IntegrationManager { async _performFullSync (): Promise { // Wait previous active sync for (const integration of this.integrations.values()) { + if (this.closing) { + break + } await this.ctx.withLog( 'external sync', { installation: integration.installationName, workspace: this.workspace.name }, @@ -1442,6 +1455,9 @@ export class GithubWorker implements IntegrationManager { // Cleanup broken synchronized documents while (true) { + if (this.closing) { + break + } const withError = await derivedClient.findAll( github.class.DocSyncInfo, { error: { $ne: null }, url: null }, @@ -1458,6 +1474,9 @@ export class GithubWorker implements IntegrationManager { } for (const { _class, mapper } of this.mappers) { + if (this.closing) { + break + } await this.ctx.withLog( 'external sync', { _class: _class.join(', '), workspace: this.workspace.name }, From 4303b0b63cbb9e3c55eec4036ba9c950f4c62dee Mon Sep 17 00:00:00 2001 From: Andrey Sobolev Date: Tue, 15 Oct 2024 14:50:53 +0700 Subject: [PATCH 03/19] Fix under maintenance warning message (#6930) Signed-off-by: Andrey Sobolev --- plugins/workbench-assets/lang/en.json | 2 +- plugins/workbench-assets/lang/es.json | 2 +- plugins/workbench-assets/lang/fr.json | 2 +- plugins/workbench-assets/lang/pt.json | 2 +- plugins/workbench-assets/lang/ru.json | 2 +- plugins/workbench-assets/lang/zh.json | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/workbench-assets/lang/en.json b/plugins/workbench-assets/lang/en.json index 4064971be0..101dec2088 100644 --- a/plugins/workbench-assets/lang/en.json +++ b/plugins/workbench-assets/lang/en.json @@ -24,7 +24,7 @@ "OpenInNewTab": "Open in a new tab", "NewVersionAvailable": "New version is available", "PleaseUpdate": "Please update", - "ServerUnderMaintenance": "Server is under maintenance", + "ServerUnderMaintenance": "Preparing workspace for new version...", "MobileNotSupported": "Sorry, mobile devices support coming soon. In the meantime, please use Desktop", "LogInAnyway": "Log in anyway", "WorkspaceCreating": "Creation in progress...", diff --git a/plugins/workbench-assets/lang/es.json b/plugins/workbench-assets/lang/es.json index 0bd6e7f4ef..112218c6a2 100644 --- a/plugins/workbench-assets/lang/es.json +++ b/plugins/workbench-assets/lang/es.json @@ -24,7 +24,7 @@ "OpenInNewTab": "Abrir en una nueva pestaña", "NewVersionAvailable": "Nueva versión disponible", "PleaseUpdate": "Por favor, actualice", - "ServerUnderMaintenance": "El servidor está en mantenimiento", + "ServerUnderMaintenance": "Preparando el espacio de trabajo para la nueva versión...", "MobileNotSupported": "Disculpa, el soporte para dispositivos móviles estará disponible próximamente. Mientras tanto, por favor usa el escritorio.", "LogInAnyway": "Iniciar sesión de todas formas", "WorkspaceCreating": "Creation in progress...", diff --git a/plugins/workbench-assets/lang/fr.json b/plugins/workbench-assets/lang/fr.json index f2b727f07a..5c363c5f14 100644 --- a/plugins/workbench-assets/lang/fr.json +++ b/plugins/workbench-assets/lang/fr.json @@ -24,7 +24,7 @@ "OpenInNewTab": "Ouvrir dans un nouvel onglet", "NewVersionAvailable": "Nouvelle version disponible", "PleaseUpdate": "Veuillez mettre à jour", - "ServerUnderMaintenance": "Le serveur est en maintenance", + "ServerUnderMaintenance": "Préparation de l'espace de travail pour la nouvelle version...", "MobileNotSupported": "Désolé, le support pour les appareils mobiles arrive bientôt. En attendant, veuillez utiliser un ordinateur de bureau", "LogInAnyway": "Se connecter quand même", "WorkspaceCreating": "Création en cours...", diff --git a/plugins/workbench-assets/lang/pt.json b/plugins/workbench-assets/lang/pt.json index a7df3d0e14..853411388e 100644 --- a/plugins/workbench-assets/lang/pt.json +++ b/plugins/workbench-assets/lang/pt.json @@ -24,7 +24,7 @@ "OpenInNewTab": "Abrir num novo separador", "NewVersionAvailable": "Nova versão disponível", "PleaseUpdate": "Atualize", - "ServerUnderMaintenance": "Servidor em manutenção", + "ServerUnderMaintenance": "Preparando o espaço de trabalho para a nova versão...", "MobileNotSupported": "Desculpe, o suporte para dispositivos móveis estará disponível em breve. Enquanto isso, por favor, use o Desktop.", "LogInAnyway": "Entrar de qualquer maneira", "WorkspaceCreating": "Creation in progress...", diff --git a/plugins/workbench-assets/lang/ru.json b/plugins/workbench-assets/lang/ru.json index f2da9f6c74..1eb03d0a1f 100644 --- a/plugins/workbench-assets/lang/ru.json +++ b/plugins/workbench-assets/lang/ru.json @@ -24,7 +24,7 @@ "OpenInNewTab": "Открыть в новой вкладке", "NewVersionAvailable": "Доступна новая версия", "PleaseUpdate": "Пожалуйста, обновите приложение", - "ServerUnderMaintenance": "Обслуживание сервера", + "ServerUnderMaintenance": "Подготовка рабочего пространства для новой версии...", "MobileNotSupported": "Простите, поддержка мобильных устройств скоро будет доступна. Пока воспользуйтесь компьютером.", "LogInAnyway": "Все равно войти", "WorkspaceCreating": "Пространство создается...", diff --git a/plugins/workbench-assets/lang/zh.json b/plugins/workbench-assets/lang/zh.json index 416be8dd78..12b9514576 100644 --- a/plugins/workbench-assets/lang/zh.json +++ b/plugins/workbench-assets/lang/zh.json @@ -24,7 +24,7 @@ "OpenInNewTab": "在新标签页中打开", "NewVersionAvailable": "有新版本可用", "PleaseUpdate": "请更新", - "ServerUnderMaintenance": "服务器正在维护中", + "ServerUnderMaintenance": "正在为新版本准备工作区...", "MobileNotSupported": "抱歉,移动设备支持即将推出。在此期间,请使用桌面设备", "LogInAnyway": "仍然登录", "WorkspaceCreating": "创建进行中...", From 49836dd0cf63dc104b63d19d058d3fd16f0f3943 Mon Sep 17 00:00:00 2001 From: Reynaldi Chernando <12949382+reynaldichernando@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:51:32 +0700 Subject: [PATCH 04/19] Capitalize Huly in GitHub issue template (#6927) Signed-off-by: Reynaldi Chernando <12949382+reynaldichernando@users.noreply.github.com> --- .github/issue_template.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/issue_template.md b/.github/issue_template.md index acd31ec849..c030c415fc 100644 --- a/.github/issue_template.md +++ b/.github/issue_template.md @@ -2,7 +2,7 @@ A clear and concise description of the issue. ### Your environment -* Version of huly +* Version of Huly * Browser (and version) * Your operating system (and version) From a337bb128c1edec8395f83ce25ed60f520f15a3c Mon Sep 17 00:00:00 2001 From: Alexander Onnikov Date: Tue, 15 Oct 2024 15:36:27 +0700 Subject: [PATCH 05/19] UBERF-8477 Allow to download image from text editor (#6929) Signed-off-by: Alexander Onnikov --- models/text-editor/src/index.ts | 9 +++++++++ models/text-editor/src/plugin.ts | 1 + plugins/text-editor-assets/assets/icons.svg | 8 ++++++++ plugins/text-editor-assets/lang/en.json | 1 + plugins/text-editor-assets/lang/es.json | 1 + plugins/text-editor-assets/lang/fr.json | 1 + plugins/text-editor-assets/lang/pt.json | 1 + plugins/text-editor-assets/lang/ru.json | 1 + plugins/text-editor-assets/lang/zh.json | 1 + plugins/text-editor-assets/src/index.ts | 1 + .../src/components/extension/imageExt.ts | 13 +++++++++++++ plugins/text-editor-resources/src/index.ts | 3 ++- plugins/text-editor/src/plugin.ts | 2 ++ 13 files changed, 42 insertions(+), 1 deletion(-) diff --git a/models/text-editor/src/index.ts b/models/text-editor/src/index.ts index ac7802ced6..cbf19db02e 100644 --- a/models/text-editor/src/index.ts +++ b/models/text-editor/src/index.ts @@ -331,6 +331,15 @@ export function createModel (builder: Builder): void { index: 10 }) + builder.createDoc(textEditor.class.TextEditorAction, core.space.Model, { + kind: 'image', + action: textEditor.function.DownloadImage, + icon: textEditor.icon.Download, + label: textEditor.string.Download, + category: 90, + index: 15 + }) + builder.createDoc(textEditor.class.TextEditorAction, core.space.Model, { kind: 'image', action: textEditor.function.MoreImageActions, diff --git a/models/text-editor/src/plugin.ts b/models/text-editor/src/plugin.ts index 19439fe536..ad954bb19f 100644 --- a/models/text-editor/src/plugin.ts +++ b/models/text-editor/src/plugin.ts @@ -29,6 +29,7 @@ export default mergeIds(textEditorId, textEditor, { ExpandImage: '' as Resource, MoreImageActions: '' as Resource, ConfigureNote: '' as Resource, + DownloadImage: '' as Resource, IsEditableTableActive: '' as Resource, IsEditableNote: '' as Resource, diff --git a/plugins/text-editor-assets/assets/icons.svg b/plugins/text-editor-assets/assets/icons.svg index 4b1f71cbdb..d05561e40e 100644 --- a/plugins/text-editor-assets/assets/icons.svg +++ b/plugins/text-editor-assets/assets/icons.svg @@ -183,6 +183,14 @@ d="M18.2927 19.7071C17.9022 19.3166 17.9022 18.6834 18.2927 18.2929C18.6833 17.9024 19.3164 17.9024 19.707 18.2929L26 24.586V20H28V28H20V26H24.586L18.2927 19.7071Z" /> + + + + diff --git a/plugins/text-editor-assets/lang/en.json b/plugins/text-editor-assets/lang/en.json index 5f5280c182..cbc870e082 100644 --- a/plugins/text-editor-assets/lang/en.json +++ b/plugins/text-editor-assets/lang/en.json @@ -32,6 +32,7 @@ "AlignCenter": "Align center", "AlignLeft": "Align left", "AlignRight": "Align right", + "Download": "Download", "ViewImage": "View image", "ViewOriginal": "View original", "MoreActions": "More actions", diff --git a/plugins/text-editor-assets/lang/es.json b/plugins/text-editor-assets/lang/es.json index 1e64d13dba..d10e9c46cb 100644 --- a/plugins/text-editor-assets/lang/es.json +++ b/plugins/text-editor-assets/lang/es.json @@ -32,6 +32,7 @@ "AlignCenter": "Alinear centro", "AlignLeft": "Alinear izquierda", "AlignRight": "Alinear derecha", + "Download": "Descargar", "ViewImage": "Ver imagen", "ViewOriginal": "Ver original", "MoreActions": "Más acciones", diff --git a/plugins/text-editor-assets/lang/fr.json b/plugins/text-editor-assets/lang/fr.json index 6882c9c6ba..7193686f05 100644 --- a/plugins/text-editor-assets/lang/fr.json +++ b/plugins/text-editor-assets/lang/fr.json @@ -32,6 +32,7 @@ "AlignCenter": "Aligner au centre", "AlignLeft": "Aligner à gauche", "AlignRight": "Aligner à droite", + "Download": "Télécharger", "ViewImage": "Voir l'image", "ViewOriginal": "Voir l'original", "MoreActions": "Plus d'actions", diff --git a/plugins/text-editor-assets/lang/pt.json b/plugins/text-editor-assets/lang/pt.json index 5089270bd4..b6f0b47125 100644 --- a/plugins/text-editor-assets/lang/pt.json +++ b/plugins/text-editor-assets/lang/pt.json @@ -32,6 +32,7 @@ "AlignCenter": "Alinhar centro", "AlignLeft": "Alinhar esquerda", "AlignRight": "Alinhar direita", + "Download": "Transferir", "ViewImage": "Ver imagem", "ViewOriginal": "Ver original", "MoreActions": "Mais ações", diff --git a/plugins/text-editor-assets/lang/ru.json b/plugins/text-editor-assets/lang/ru.json index 6ccdc85758..f197e3abe5 100644 --- a/plugins/text-editor-assets/lang/ru.json +++ b/plugins/text-editor-assets/lang/ru.json @@ -32,6 +32,7 @@ "AlignCenter": "По центру", "AlignLeft": "По левому краю", "AlignRight": "По правому краю", + "Download": "Скачать", "ViewImage": "Открыть изображение", "ViewOriginal": "Открыть оригинал", "MoreActions": "Дополнительные действия", diff --git a/plugins/text-editor-assets/lang/zh.json b/plugins/text-editor-assets/lang/zh.json index 3b8959c5e7..c3def4da63 100644 --- a/plugins/text-editor-assets/lang/zh.json +++ b/plugins/text-editor-assets/lang/zh.json @@ -32,6 +32,7 @@ "AlignCenter": "居中对齐", "AlignLeft": "左对齐", "AlignRight": "右对齐", + "Download": "下载", "ViewImage": "查看图片", "ViewOriginal": "查看原图", "MoreActions": "更多操作", diff --git a/plugins/text-editor-assets/src/index.ts b/plugins/text-editor-assets/src/index.ts index 8f82ee0d90..b34b337333 100644 --- a/plugins/text-editor-assets/src/index.ts +++ b/plugins/text-editor-assets/src/index.ts @@ -38,5 +38,6 @@ loadMetadata(textEditor.icon, { MoreH: `${icons}#moreH`, Expand: `${icons}#expand`, ScaleOut: `${icons}#scaleOut`, + Download: `${icons}#download`, Note: `${icons}#note` }) diff --git a/plugins/text-editor-resources/src/components/extension/imageExt.ts b/plugins/text-editor-resources/src/components/extension/imageExt.ts index f000915b34..5e02ee7a85 100644 --- a/plugins/text-editor-resources/src/components/extension/imageExt.ts +++ b/plugins/text-editor-resources/src/components/extension/imageExt.ts @@ -233,6 +233,19 @@ export async function openImage (editor: Editor): Promise { }) } +export async function downloadImage (editor: Editor): Promise { + const attributes = editor.getAttributes('image') + const fileId = attributes['file-id'] ?? attributes.src + const href = getFileUrl(fileId) + + const link = document.createElement('a') + link.style.display = 'none' + link.target = '_blank' + link.href = href + link.download = attributes.title ?? attributes.alt ?? '' + link.click() +} + export async function expandImage (editor: Editor): Promise { const attributes = editor.getAttributes('image') const fileId = attributes['file-id'] ?? attributes.src diff --git a/plugins/text-editor-resources/src/index.ts b/plugins/text-editor-resources/src/index.ts index 8f3b4be10b..056b59ec77 100644 --- a/plugins/text-editor-resources/src/index.ts +++ b/plugins/text-editor-resources/src/index.ts @@ -18,7 +18,7 @@ import { type Resources } from '@hcengineering/platform' import { formatLink } from './kits/default-kit' import { isEditable, isHeadingVisible } from './kits/editor-kit' import { openTableOptions, isEditableTableActive } from './components/extension/table/table' -import { openImage, expandImage, moreImageActions } from './components/extension/imageExt' +import { openImage, downloadImage, expandImage, moreImageActions } from './components/extension/imageExt' import { configureNote, isEditableNote } from './components/extension/note' export * from '@hcengineering/presentation/src/types' @@ -82,6 +82,7 @@ export default async (): Promise => ({ OpenTableOptions: openTableOptions, OpenImage: openImage, ExpandImage: expandImage, + DownloadImage: downloadImage, MoreImageActions: moreImageActions, ConfigureNote: configureNote, IsEditableTableActive: isEditableTableActive, diff --git a/plugins/text-editor/src/plugin.ts b/plugins/text-editor/src/plugin.ts index cb66e0025b..66fc794368 100644 --- a/plugins/text-editor/src/plugin.ts +++ b/plugins/text-editor/src/plugin.ts @@ -72,6 +72,7 @@ export default plugin(textEditorId, { AlignRight: '' as IntlString, ViewImage: '' as IntlString, ViewOriginal: '' as IntlString, + Download: '' as IntlString, MoreActions: '' as IntlString, InsertTable: '' as IntlString, @@ -115,6 +116,7 @@ export default plugin(textEditorId, { MoreH: '' as Asset, Expand: '' as Asset, ScaleOut: '' as Asset, + Download: '' as Asset, Note: '' as Asset } }) From 2c45db6c411baa2fe737879b235af934bacfa503 Mon Sep 17 00:00:00 2001 From: Alexander Onnikov Date: Tue, 15 Oct 2024 16:55:11 +0700 Subject: [PATCH 06/19] fix: use const slack link (#6935) Signed-off-by: Alexander Onnikov --- plugins/support/src/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/support/src/index.ts b/plugins/support/src/index.ts index 712abc96d4..47317ebdc8 100644 --- a/plugins/support/src/index.ts +++ b/plugins/support/src/index.ts @@ -21,7 +21,7 @@ import { SupportClientFactory, SupportConversation, SupportSystem } from './type export * from './types' export { deleteSupportConversation, updateSupportConversation } from './utils' -export const supportLink = 'https://join.slack.com/t/hulycommunity/shared_invite/zt-2cyrevz8g-AGqEDZNsujbn4wHOWd7myg' +export const supportLink = 'https://huly.link/slack' export const reportBugLink = 'https://github.com/hcengineering/platform/issues/new' export const docsLink = 'http://docs.huly.io/' export const privacyPolicyLink = 'https://v1.huly.io/legal/privacy/' From 6b112fc1be462ad353264325fac466a22c6d6675 Mon Sep 17 00:00:00 2001 From: Alexey Zinoviev Date: Tue, 15 Oct 2024 14:03:55 +0400 Subject: [PATCH 07/19] UBERF-8429: Allow to disable sign-ups (#6934) Signed-off-by: Alexey Zinoviev --- .vscode/launch.json | 3 +- dev/docker-compose.yaml | 2 + .../src/components/Form.svelte | 3 +- .../src/components/LoginApp.svelte | 7 ++-- .../src/components/LoginForm.svelte | 5 ++- .../src/components/LoginOtpForm.svelte | 4 +- .../src/components/LoginPasswordForm.svelte | 2 + .../src/components/OtpForm.svelte | 3 +- .../src/components/PasswordRequest.svelte | 5 ++- .../src/components/SignupForm.svelte | 6 +++ .../src/components/Tabs.svelte | 23 ++++++----- plugins/login/src/index.ts | 3 +- pods/authProviders/src/github.ts | 39 ++++++++++++++----- pods/authProviders/src/google.ts | 26 +++++++++---- pods/authProviders/src/index.ts | 8 ++-- pods/authProviders/src/openid.ts | 39 ++++++++++++++----- pods/authProviders/src/token.ts | 3 +- server/account-service/src/index.ts | 7 +++- server/account/src/operations.ts | 14 +++++-- server/front/src/index.ts | 2 + server/front/src/starter.ts | 5 ++- 21 files changed, 148 insertions(+), 61 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index c1f2a92066..4b97af00c9 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -97,7 +97,8 @@ "SES_URL": "", "MINIO_ACCESS_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_WORKSPACE": "onboarding", }, diff --git a/dev/docker-compose.yaml b/dev/docker-compose.yaml index b9784be4ce..d000ac9d5a 100644 --- a/dev/docker-compose.yaml +++ b/dev/docker-compose.yaml @@ -85,6 +85,7 @@ services: - LAST_NAME_FIRST=true - ACCOUNTS_URL=http://host.docker.internal:3000 - BRANDING_PATH=/var/cfg/branding.json + # - DISABLE_SIGNUP=true # - INIT_SCRIPT_URL=https://raw.githubusercontent.com/hcengineering/init/main/script.yaml # - INIT_WORKSPACE=onboarding restart: unless-stopped @@ -197,6 +198,7 @@ services: - DESKTOP_UPDATES_URL=https://dist.huly.io - DESKTOP_UPDATES_CHANNEL=dev - BRANDING_URL=http://host.docker.internal:8087/branding.json + # - DISABLE_SIGNUP=true restart: unless-stopped transactor: image: hardcoreeng/transactor diff --git a/plugins/login-resources/src/components/Form.svelte b/plugins/login-resources/src/components/Form.svelte index ab4028b92b..a9ee5d1bd6 100644 --- a/plugins/login-resources/src/components/Form.svelte +++ b/plugins/login-resources/src/components/Form.svelte @@ -57,6 +57,7 @@ export let ignoreInitialValidation: boolean = false export let withProviders: boolean = false export let subtitle: string | undefined = undefined + export let signUpDisabled = false $: $themeStore.language && validate($themeStore.language) @@ -138,7 +139,7 @@ }} > {#if loginState !== 'none'} - + {:else} {#if subtitle !== undefined}
diff --git a/plugins/login-resources/src/components/LoginApp.svelte b/plugins/login-resources/src/components/LoginApp.svelte index 77174900fa..d0c9b64ef7 100644 --- a/plugins/login-resources/src/components/LoginApp.svelte +++ b/plugins/login-resources/src/components/LoginApp.svelte @@ -54,6 +54,7 @@ export let page: Pages = 'signup' + const signUpDisabled = getMetadata(login.metadata.DisableSignUp) ?? false let navigateUrl: string | undefined onDestroy(location.subscribe(updatePageLoc)) @@ -134,13 +135,13 @@
{#if page === 'login'} - + {:else if page === 'signup'} - + {:else if page === 'createWorkspace'} {:else if page === 'password'} - + {:else if page === 'recovery'} {:else if page === 'selectWorkspace'} diff --git a/plugins/login-resources/src/components/LoginForm.svelte b/plugins/login-resources/src/components/LoginForm.svelte index 2d8973b45b..ced1085f38 100644 --- a/plugins/login-resources/src/components/LoginForm.svelte +++ b/plugins/login-resources/src/components/LoginForm.svelte @@ -21,6 +21,7 @@ import login from '../plugin' export let navigateUrl: string | undefined = undefined + export let signUpDisabled = false let method: LoginMethods = LoginMethods.Otp @@ -44,12 +45,12 @@ {#if method === LoginMethods.Otp} - +
{:else} - +
diff --git a/plugins/login-resources/src/components/LoginOtpForm.svelte b/plugins/login-resources/src/components/LoginOtpForm.svelte index 1782cc1d76..1ecf5943aa 100644 --- a/plugins/login-resources/src/components/LoginOtpForm.svelte +++ b/plugins/login-resources/src/components/LoginOtpForm.svelte @@ -21,6 +21,7 @@ import { OtpLoginSteps, sendOtp } from '../index' export let navigateUrl: string | undefined = undefined + export let signUpDisabled = false const fields = [{ id: 'email', name: 'username', i18n: login.string.Email }] const formData = { @@ -57,11 +58,12 @@ {fields} object={formData} {action} + {signUpDisabled} ignoreInitialValidation withProviders /> {/if} {#if step === OtpLoginSteps.Otp && formData.username !== ''} - + {/if} diff --git a/plugins/login-resources/src/components/LoginPasswordForm.svelte b/plugins/login-resources/src/components/LoginPasswordForm.svelte index d5ac9c37a5..29bb4169ff 100644 --- a/plugins/login-resources/src/components/LoginPasswordForm.svelte +++ b/plugins/login-resources/src/components/LoginPasswordForm.svelte @@ -21,6 +21,7 @@ import login from '../plugin' export let navigateUrl: string | undefined = undefined + export let signUpDisabled = false const fields = [ { id: 'email', name: 'username', i18n: login.string.Email }, @@ -62,6 +63,7 @@ {fields} {object} {action} + {signUpDisabled} bottomActions={[recoveryAction]} ignoreInitialValidation withProviders diff --git a/plugins/login-resources/src/components/OtpForm.svelte b/plugins/login-resources/src/components/OtpForm.svelte index 057e850cdb..dd655817be 100644 --- a/plugins/login-resources/src/components/OtpForm.svelte +++ b/plugins/login-resources/src/components/OtpForm.svelte @@ -28,6 +28,7 @@ export let navigateUrl: string | undefined = undefined export let email: string export let retryOn: Timestamp + export let signUpDisabled = false const dispatch = createEventDispatcher() @@ -232,7 +233,7 @@ style:min-height={$deviceInfo.docHeight > 720 ? '42rem' : '0'} >
- +