diff --git a/packages/core/src/operations.ts b/packages/core/src/operations.ts index 040ee91286..60fb77eb5c 100644 --- a/packages/core/src/operations.ts +++ b/packages/core/src/operations.ts @@ -272,7 +272,7 @@ export class TxOperations implements Omit { return new ApplyOperations(this, scope) } - async diffUpdate (doc: Doc, raw: Doc | Data, date: Timestamp): Promise { + async diffUpdate (doc: Doc, raw: Doc | Data, date: Timestamp, account?: Ref): Promise { // We need to update fields if they are different. const documentUpdate: DocumentUpdate = {} for (const [k, v] of Object.entries(raw)) { @@ -285,7 +285,7 @@ export class TxOperations implements Omit { } } if (Object.keys(documentUpdate).length > 0) { - await this.update(doc, documentUpdate, false, date, doc.modifiedBy) + await this.update(doc, documentUpdate, false, date, account ?? doc.modifiedBy) TxProcessor.applyUpdate(doc, documentUpdate) } return doc diff --git a/plugins/tracker-resources/src/components/projects/CreateProject.svelte b/plugins/tracker-resources/src/components/projects/CreateProject.svelte index 5837010cd6..ba642cafe2 100644 --- a/plugins/tracker-resources/src/components/projects/CreateProject.svelte +++ b/plugins/tracker-resources/src/components/projects/CreateProject.svelte @@ -50,8 +50,8 @@ export let project: Project | undefined = undefined - export let namePlaceholder: '' - export let descriptionPlaceholder: '' + export let namePlaceholder: string = '' + export let descriptionPlaceholder: string = '' export let statusFactory: ( client: TxOperations | ApplyOperations, spaceId: Status['space'], @@ -208,6 +208,8 @@ { _id: { $nin: project ? [project._id] : [] } }, (res) => (projectsIdentifiers = new Set(res.map(({ identifier }) => identifier))) ) + + $: identifier = identifier.toLocaleUpperCase().replaceAll('-', '_').replaceAll(' ', '_').substring(0, 5) { if (isNew) { - identifier = name.toLocaleUpperCase().replaceAll(' ', '_').substring(0, 5) + identifier = name.toLocaleUpperCase().replaceAll('-', '_').replaceAll(' ', '_').substring(0, 5) color = isColorSelected ? color : getColorNumberByText(name) } }} @@ -253,7 +255,6 @@
{ - console.trace('Exiting from server') - console.log('Shutdown request accepted') - shutdown() - process.exit(0) -} - -process.on('SIGINT', close) -process.on('SIGTERM', close) +import { startFront } from './starter' +startFront() diff --git a/server/front/src/index.ts b/server/front/src/index.ts index d654053a7c..cce2f01030 100644 --- a/server/front/src/index.ts +++ b/server/front/src/index.ts @@ -144,7 +144,8 @@ export function start ( title?: string defaultLanguage: string }, - port: number + port: number, + extraConfig?: Record ): () => void { const app = express() @@ -181,7 +182,8 @@ export function start ( GMAIL_URL: config.gmailUrl, CALENDAR_URL: config.calendarUrl, TITLE: config.title, - DEFAULT_LANGUAGE: config.defaultLanguage + DEFAULT_LANGUAGE: config.defaultLanguage, + ...(extraConfig ?? {}) }) }) diff --git a/server/front/src/starter.ts b/server/front/src/starter.ts new file mode 100644 index 0000000000..61b3074c44 --- /dev/null +++ b/server/front/src/starter.ts @@ -0,0 +1,149 @@ +// +// Copyright © 2020, 2021 Anticrm Platform Contributors. +// Copyright © 2021 Hardcore Engineering Inc. +// +// Licensed under the Eclipse Public License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. You may +// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import { MinioService } from '@hcengineering/minio' +import { setMetadata } from '@hcengineering/platform' +import serverToken from '@hcengineering/server-token' +import { start } from '.' + +export function startFront (extraConfig?: Record): void { + const defaultLanguage = process.env.DEFAULT_LANGUAGE ?? 'en' + const SERVER_PORT = parseInt(process.env.SERVER_PORT ?? '8080') + + const transactorEndpoint = process.env.TRANSACTOR_URL + if (transactorEndpoint === undefined) { + console.error('please provide transactor url') + process.exit(1) + } + + const elasticUrl = process.env.ELASTIC_URL + if (elasticUrl === undefined) { + console.error('please provide elastic url') + process.exit(1) + } + + const minioEndpoint = process.env.MINIO_ENDPOINT + if (minioEndpoint === undefined) { + console.error('please provide minio endpoint') + process.exit(1) + } + + const minioAccessKey = process.env.MINIO_ACCESS_KEY + if (minioAccessKey === undefined) { + console.error('please provide minio access key') + process.exit(1) + } + + const minioSecretKey = process.env.MINIO_SECRET_KEY + if (minioSecretKey === undefined) { + console.error('please provide minio secret key') + process.exit(1) + } + + const minio = new MinioService({ + endPoint: minioEndpoint, + port: 9000, + useSSL: false, + accessKey: minioAccessKey, + secretKey: minioSecretKey + }) + + const accountsUrl = process.env.ACCOUNTS_URL + if (accountsUrl === undefined) { + console.error('please provide accounts url') + process.exit(1) + } + + const uploadUrl = process.env.UPLOAD_URL + if (uploadUrl === undefined) { + console.error('please provide upload url') + process.exit(1) + } + + const collaboratorUrl = process.env.COLLABORATOR_URL + if (collaboratorUrl === undefined) { + console.error('please provide collaborator url') + process.exit(1) + } + + const gmailUrl = process.env.GMAIL_URL + if (gmailUrl === undefined) { + console.error('please provide gmail url') + process.exit(1) + } + + const calendarUrl = process.env.CALENDAR_URL + if (calendarUrl === undefined) { + console.error('please provide calendar service url') + process.exit(1) + } + + const telegramUrl = process.env.TELEGRAM_URL + if (telegramUrl === undefined) { + console.error('please provide telegram url') + process.exit(1) + } + + const rekoniUrl = process.env.REKONI_URL + if (rekoniUrl === undefined) { + console.error('please provide rekoni url') + process.exit(1) + } + + const modelVersion = process.env.MODEL_VERSION + if (modelVersion === undefined) { + console.error('please provide model version requirement') + process.exit(1) + } + + const serverSecret = process.env.SERVER_SECRET + if (serverSecret === undefined) { + console.log('Please provide server secret') + process.exit(1) + } + + const title = process.env.TITLE + + setMetadata(serverToken.metadata.Secret, serverSecret) + + const config = { + transactorEndpoint, + elasticUrl, + minio, + accountsUrl, + uploadUrl, + modelVersion, + collaboratorUrl, + gmailUrl, + telegramUrl, + rekoniUrl, + calendarUrl, + title, + defaultLanguage + } + console.log('Starting Front service with', config) + const shutdown = start(config, SERVER_PORT, extraConfig) + + const close = (): void => { + console.trace('Exiting from server') + console.log('Shutdown request accepted') + shutdown() + process.exit(0) + } + + process.on('SIGINT', close) + process.on('SIGTERM', close) +} diff --git a/server/middleware/src/modified.ts b/server/middleware/src/modified.ts index 18cf001d55..96326b789d 100644 --- a/server/middleware/src/modified.ts +++ b/server/middleware/src/modified.ts @@ -13,7 +13,7 @@ // limitations under the License. // -import core, { MeasureContext, ServerStorage, Tx } from '@hcengineering/core' +import core, { MeasureContext, ServerStorage, Tx, systemAccountEmail } from '@hcengineering/core' import { BroadcastFunc, Middleware, SessionContext, TxMiddlewareResult } from '@hcengineering/server-core' import { BaseMiddleware } from './base' @@ -35,7 +35,7 @@ export class ModifiedMiddleware extends BaseMiddleware implements Middleware { } async tx (ctx: SessionContext, tx: Tx): Promise { - if (tx.modifiedBy !== core.account.System) { + if (tx.modifiedBy !== core.account.System && ctx.userEmail !== systemAccountEmail) { tx.modifiedOn = Date.now() tx.createdOn = tx.createdOn ?? tx.modifiedOn }