mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-26 19:44:57 +02:00
Reusable Platform (#2374)
Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// Copyright © 2022 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 { prepareTools as prepareToolsRaw } from '@hcengineering/server-tool'
|
||||
|
||||
import { Data, Tx, Version } from '@hcengineering/core'
|
||||
import { MigrateOperation } from '@hcengineering/model'
|
||||
import builder, { migrateOperations, version } from '@hcengineering/model-all'
|
||||
import { Client } from 'minio'
|
||||
import { devTool } from '.'
|
||||
|
||||
function prepareTools (): {
|
||||
mongodbUri: string
|
||||
minio: Client
|
||||
txes: Tx[]
|
||||
version: Data<Version>
|
||||
migrateOperations: MigrateOperation[]
|
||||
productId: string
|
||||
} {
|
||||
return { ...prepareToolsRaw(builder.getTxes()), version, migrateOperations, productId: '' }
|
||||
}
|
||||
|
||||
devTool(prepareTools)
|
||||
+364
-336
@@ -38,7 +38,8 @@ import {
|
||||
restore
|
||||
} from '@hcengineering/server-backup'
|
||||
import serverToken, { decodeToken, generateToken } from '@hcengineering/server-token'
|
||||
import toolPlugin, { prepareTools, version } from '@hcengineering/server-tool'
|
||||
import toolPlugin from '@hcengineering/server-tool'
|
||||
|
||||
import { program } from 'commander'
|
||||
import { Db, MongoClient } from 'mongodb'
|
||||
import { exit } from 'process'
|
||||
@@ -53,384 +54,411 @@ import { updateCandidates } from './recruit'
|
||||
import { clearTelegramHistory } from './telegram'
|
||||
import { diffWorkspace, dumpWorkspace, restoreWorkspace } from './workspace'
|
||||
|
||||
const serverSecret = process.env.SERVER_SECRET
|
||||
if (serverSecret === undefined) {
|
||||
console.error('please provide server secret')
|
||||
process.exit(1)
|
||||
}
|
||||
import { Data, Tx, Version } from '@hcengineering/core'
|
||||
import { MigrateOperation } from '@hcengineering/model'
|
||||
import { Client } from 'minio'
|
||||
|
||||
const transactorUrl = process.env.TRANSACTOR_URL
|
||||
if (transactorUrl === undefined) {
|
||||
console.error('please provide transactor url.')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
function getElasticUrl (): string {
|
||||
const elasticUrl = process.env.ELASTIC_URL
|
||||
if (elasticUrl === undefined) {
|
||||
console.error('please provide elastic url')
|
||||
/**
|
||||
* @public
|
||||
*/
|
||||
export function devTool (
|
||||
prepareTools: () => {
|
||||
mongodbUri: string
|
||||
minio: Client
|
||||
txes: Tx[]
|
||||
version: Data<Version>
|
||||
migrateOperations: MigrateOperation[]
|
||||
productId: string
|
||||
}
|
||||
): void {
|
||||
const serverSecret = process.env.SERVER_SECRET
|
||||
if (serverSecret === undefined) {
|
||||
console.error('please provide server secret')
|
||||
process.exit(1)
|
||||
}
|
||||
return elasticUrl
|
||||
}
|
||||
|
||||
setMetadata(toolPlugin.metadata.Endpoint, transactorUrl)
|
||||
setMetadata(toolPlugin.metadata.Transactor, transactorUrl)
|
||||
setMetadata(serverToken.metadata.Secret, serverSecret)
|
||||
const transactorUrl = process.env.TRANSACTOR_URL
|
||||
if (transactorUrl === undefined) {
|
||||
console.error('please provide transactor url.')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
async function withDatabase (uri: string, f: (db: Db, client: MongoClient) => Promise<any>): Promise<void> {
|
||||
console.log(`connecting to database '${uri}'...`)
|
||||
function getElasticUrl (): string {
|
||||
const elasticUrl = process.env.ELASTIC_URL
|
||||
if (elasticUrl === undefined) {
|
||||
console.error('please provide elastic url')
|
||||
process.exit(1)
|
||||
}
|
||||
return elasticUrl
|
||||
}
|
||||
|
||||
const client = await MongoClient.connect(uri)
|
||||
await f(client.db(ACCOUNT_DB), client)
|
||||
await client.close()
|
||||
}
|
||||
setMetadata(toolPlugin.metadata.Endpoint, transactorUrl)
|
||||
setMetadata(toolPlugin.metadata.Transactor, transactorUrl)
|
||||
setMetadata(serverToken.metadata.Secret, serverSecret)
|
||||
|
||||
program.version('0.0.1')
|
||||
async function withDatabase (uri: string, f: (db: Db, client: MongoClient) => Promise<any>): Promise<void> {
|
||||
console.log(`connecting to database '${uri}'...`)
|
||||
|
||||
// create-user john.appleseed@gmail.com --password 123 --workspace workspace --fullname "John Appleseed"
|
||||
program
|
||||
.command('create-account <email>')
|
||||
.description('create user and corresponding account in master database')
|
||||
.requiredOption('-p, --password <password>', 'user password')
|
||||
.requiredOption('-f, --first <first>', 'first name')
|
||||
.requiredOption('-l, --last <last>', 'last name')
|
||||
.action(async (email: string, cmd) => {
|
||||
const { mongodbUri } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
console.log(`creating account ${cmd.first as string} ${cmd.last as string} (${email})...`)
|
||||
await createAccount(db, email, cmd.password, cmd.first, cmd.last)
|
||||
const client = await MongoClient.connect(uri)
|
||||
await f(client.db(ACCOUNT_DB), client)
|
||||
await client.close()
|
||||
}
|
||||
|
||||
program.version('0.0.1')
|
||||
|
||||
// create-user john.appleseed@gmail.com --password 123 --workspace workspace --fullname "John Appleseed"
|
||||
program
|
||||
.command('create-account <email>')
|
||||
.description('create user and corresponding account in master database')
|
||||
.requiredOption('-p, --password <password>', 'user password')
|
||||
.requiredOption('-f, --first <first>', 'first name')
|
||||
.requiredOption('-l, --last <last>', 'last name')
|
||||
.action(async (email: string, cmd) => {
|
||||
const { mongodbUri } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
console.log(`creating account ${cmd.first as string} ${cmd.last as string} (${email})...`)
|
||||
await createAccount(db, email, cmd.password, cmd.first, cmd.last)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
program
|
||||
.command('reset-account <email>')
|
||||
.description('create user and corresponding account in master database')
|
||||
.option('-p, --password <password>', 'new user password')
|
||||
.action(async (email: string, cmd) => {
|
||||
const { mongodbUri } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
console.log(`update account ${email} ${cmd.first as string} ${cmd.last as string}...`)
|
||||
await replacePassword(db, email, cmd.password)
|
||||
program
|
||||
.command('reset-account <email>')
|
||||
.description('create user and corresponding account in master database')
|
||||
.option('-p, --password <password>', 'new user password')
|
||||
.action(async (email: string, cmd) => {
|
||||
const { mongodbUri } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
console.log(`update account ${email} ${cmd.first as string} ${cmd.last as string}...`)
|
||||
await replacePassword(db, email, cmd.password)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
program
|
||||
.command('assign-workspace <email> <workspace>')
|
||||
.description('assign workspace')
|
||||
.action(async (email: string, workspace: string, cmd) => {
|
||||
const { mongodbUri } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db, client) => {
|
||||
console.log(`assigning user ${email} to ${workspace}...`)
|
||||
await assignWorkspace(db, email, workspace)
|
||||
program
|
||||
.command('assign-workspace <email> <workspace>')
|
||||
.description('assign workspace')
|
||||
.action(async (email: string, workspace: string, cmd) => {
|
||||
const { mongodbUri } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db, client) => {
|
||||
console.log(`assigning user ${email} to ${workspace}...`)
|
||||
await assignWorkspace(db, email, workspace)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
program
|
||||
.command('show-user <email>')
|
||||
.description('show user')
|
||||
.action(async (email) => {
|
||||
const { mongodbUri } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
const info = await getAccount(db, email)
|
||||
console.log(info)
|
||||
program
|
||||
.command('show-user <email>')
|
||||
.description('show user')
|
||||
.action(async (email) => {
|
||||
const { mongodbUri } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
const info = await getAccount(db, email)
|
||||
console.log(info)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
program
|
||||
.command('create-workspace <name>')
|
||||
.description('create workspace')
|
||||
.requiredOption('-o, --organization <organization>', 'organization name')
|
||||
.action(async (workspace, cmd) => {
|
||||
const { mongodbUri } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
await createWorkspace(db, workspace, cmd.organization)
|
||||
program
|
||||
.command('create-workspace <name>')
|
||||
.description('create workspace')
|
||||
.requiredOption('-o, --organization <organization>', 'organization name')
|
||||
.action(async (workspace, cmd) => {
|
||||
const { mongodbUri, txes, version, migrateOperations, productId } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
await createWorkspace(version, txes, migrateOperations, productId, db, workspace, cmd.organization)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
program
|
||||
.command('set-user-role <email> <workspace> <role>')
|
||||
.description('set user role')
|
||||
.action(async (email: string, workspace: string, role: number, cmd) => {
|
||||
console.log(`set user ${email} role for ${workspace}...`)
|
||||
await setRole(email, workspace, role)
|
||||
})
|
||||
|
||||
program
|
||||
.command('upgrade-workspace <name>')
|
||||
.description('upgrade workspace')
|
||||
.action(async (workspace, cmd) => {
|
||||
const { mongodbUri } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
await upgradeWorkspace(db, workspace)
|
||||
program
|
||||
.command('set-user-role <email> <workspace> <role>')
|
||||
.description('set user role')
|
||||
.action(async (email: string, workspace: string, role: number, cmd) => {
|
||||
console.log(`set user ${email} role for ${workspace}...`)
|
||||
await setRole(email, workspace, role)
|
||||
})
|
||||
})
|
||||
|
||||
program
|
||||
.command('upgrade')
|
||||
.description('upgrade')
|
||||
.action(async (cmd) => {
|
||||
const { mongodbUri } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
const workspaces = await listWorkspaces(db)
|
||||
for (const ws of workspaces) {
|
||||
console.log('---UPGRADING----', ws.workspace)
|
||||
await upgradeWorkspace(db, ws.workspace)
|
||||
}
|
||||
program
|
||||
.command('upgrade-workspace <name>')
|
||||
.description('upgrade workspace')
|
||||
.action(async (workspace, cmd) => {
|
||||
const { mongodbUri, version, txes, migrateOperations, productId } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
await upgradeWorkspace(version, txes, migrateOperations, productId, db, workspace)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
program
|
||||
.command('drop-workspace <name>')
|
||||
.description('drop workspace')
|
||||
.action(async (workspace, cmd) => {
|
||||
const { mongodbUri } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
const ws = await getWorkspace(db, workspace)
|
||||
if (ws === null) {
|
||||
console.log('no workspace exists')
|
||||
return
|
||||
}
|
||||
await dropWorkspace(db, workspace)
|
||||
program
|
||||
.command('upgrade')
|
||||
.description('upgrade')
|
||||
.action(async (cmd) => {
|
||||
const { mongodbUri, version, txes, migrateOperations, productId } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
const workspaces = await listWorkspaces(db, productId)
|
||||
for (const ws of workspaces) {
|
||||
console.log('---UPGRADING----', ws.workspace)
|
||||
await upgradeWorkspace(version, txes, migrateOperations, productId, db, ws.workspace)
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
program
|
||||
.command('list-workspaces')
|
||||
.description('List workspaces')
|
||||
.action(async () => {
|
||||
const { mongodbUri } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
const workspacesJSON = JSON.stringify(await listWorkspaces(db), null, 2)
|
||||
console.info(workspacesJSON)
|
||||
|
||||
console.log('latest model version:', JSON.stringify(version))
|
||||
program
|
||||
.command('drop-workspace <name>')
|
||||
.description('drop workspace')
|
||||
.action(async (workspace, cmd) => {
|
||||
const { mongodbUri } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
const ws = await getWorkspace(db, workspace)
|
||||
if (ws === null) {
|
||||
console.log('no workspace exists')
|
||||
return
|
||||
}
|
||||
await dropWorkspace(db, workspace)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
program
|
||||
.command('show-accounts')
|
||||
.description('Show accounts')
|
||||
.action(async () => {
|
||||
const { mongodbUri } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
const accountsJSON = JSON.stringify(await listAccounts(db), null, 2)
|
||||
console.info(accountsJSON)
|
||||
program
|
||||
.command('list-workspaces')
|
||||
.description('List workspaces')
|
||||
.action(async () => {
|
||||
const { mongodbUri, version, productId } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
const workspacesJSON = JSON.stringify(await listWorkspaces(db, productId), null, 2)
|
||||
console.info(workspacesJSON)
|
||||
|
||||
console.log('latest model version:', JSON.stringify(version))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
program
|
||||
.command('drop-account <name>')
|
||||
.description('drop account')
|
||||
.action(async (email, cmd) => {
|
||||
const { mongodbUri } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
await dropAccount(db, email)
|
||||
program
|
||||
.command('show-accounts')
|
||||
.description('Show accounts')
|
||||
.action(async () => {
|
||||
const { mongodbUri } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
const accountsJSON = JSON.stringify(await listAccounts(db), null, 2)
|
||||
console.info(accountsJSON)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
program
|
||||
.command('dump-workspace <workspace> <dirName>')
|
||||
.description('dump workspace transactions and minio resources')
|
||||
.action(async (workspace, dirName, cmd) => {
|
||||
const { mongodbUri, minio } = prepareTools()
|
||||
return await dumpWorkspace(mongodbUri, workspace, dirName, minio)
|
||||
})
|
||||
|
||||
program
|
||||
.command('backup <dirName> <workspace>')
|
||||
.description('dump workspace transactions and minio resources')
|
||||
.action(async (dirName, workspace, cmd) => {
|
||||
const storage = await createFileBackupStorage(dirName)
|
||||
return await backup(transactorUrl, workspace, storage)
|
||||
})
|
||||
|
||||
program
|
||||
.command('backup-restore <dirName> <workspace> [date]')
|
||||
.description('dump workspace transactions and minio resources')
|
||||
.action(async (dirName, workspace, date, cmd) => {
|
||||
const storage = await createFileBackupStorage(dirName)
|
||||
return await restore(transactorUrl, workspace, storage, parseInt(date ?? '-1'))
|
||||
})
|
||||
|
||||
program
|
||||
.command('backup-list <dirName>')
|
||||
.description('list snaphost ids for backup')
|
||||
.action(async (dirName, cmd) => {
|
||||
const storage = await createFileBackupStorage(dirName)
|
||||
return await backupList(storage)
|
||||
})
|
||||
|
||||
program
|
||||
.command('backup-s3 <bucketName> <dirName> <workspace>')
|
||||
.description('dump workspace transactions and minio resources')
|
||||
.action(async (bucketName, dirName, workspace, cmd) => {
|
||||
const { minio } = prepareTools()
|
||||
const storage = await createMinioBackupStorage(minio, bucketName, dirName)
|
||||
return await backup(transactorUrl, workspace, storage)
|
||||
})
|
||||
program
|
||||
.command('backup-s3-restore <bucketName>, <dirName> <workspace> [date]')
|
||||
.description('dump workspace transactions and minio resources')
|
||||
.action(async (bucketName, dirName, workspace, date, cmd) => {
|
||||
const { minio } = prepareTools()
|
||||
const storage = await createMinioBackupStorage(minio, bucketName, dirName)
|
||||
return await restore(transactorUrl, workspace, storage, parseInt(date ?? '-1'))
|
||||
})
|
||||
program
|
||||
.command('backup-s3-list <bucketName> <dirName>')
|
||||
.description('list snaphost ids for backup')
|
||||
.action(async (bucketName, dirName, cmd) => {
|
||||
const { minio } = prepareTools()
|
||||
const storage = await createMinioBackupStorage(minio, bucketName, dirName)
|
||||
return await backupList(storage)
|
||||
})
|
||||
|
||||
program
|
||||
.command('restore-workspace <workspace> <dirName>')
|
||||
.description('restore workspace transactions and minio resources from previous dump.')
|
||||
.action(async (workspace, dirName, cmd) => {
|
||||
const { mongodbUri, minio } = prepareTools()
|
||||
return await restoreWorkspace(mongodbUri, workspace, dirName, minio, getElasticUrl(), transactorUrl)
|
||||
})
|
||||
|
||||
program
|
||||
.command('diff-workspace <workspace>')
|
||||
.description('restore workspace transactions and minio resources from previous dump.')
|
||||
.action(async (workspace, cmd) => {
|
||||
const { mongodbUri } = prepareTools()
|
||||
return await diffWorkspace(mongodbUri, workspace)
|
||||
})
|
||||
|
||||
program
|
||||
.command('clear-telegram-history <workspace>')
|
||||
.description('clear telegram history')
|
||||
.option('-w, --workspace <workspace>', 'target workspace')
|
||||
.action(async (workspace: string, cmd) => {
|
||||
const { mongodbUri, minio } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
const telegramDB = process.env.TELEGRAM_DATABASE
|
||||
if (telegramDB === undefined) {
|
||||
console.error('please provide TELEGRAM_DATABASE.')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log(`clearing ${workspace} history:`)
|
||||
await clearTelegramHistory(mongodbUri, workspace, telegramDB, minio)
|
||||
program
|
||||
.command('drop-account <name>')
|
||||
.description('drop account')
|
||||
.action(async (email, cmd) => {
|
||||
const { mongodbUri } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
await dropAccount(db, email)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
program
|
||||
.command('clear-telegram-all-history')
|
||||
.description('clear telegram history')
|
||||
.action(async (cmd) => {
|
||||
const { mongodbUri, minio } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
const telegramDB = process.env.TELEGRAM_DATABASE
|
||||
if (telegramDB === undefined) {
|
||||
console.error('please provide TELEGRAM_DATABASE.')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const workspaces = await listWorkspaces(db)
|
||||
|
||||
for (const w of workspaces) {
|
||||
console.log(`clearing ${w.workspace} history:`)
|
||||
await clearTelegramHistory(mongodbUri, w.workspace, telegramDB, minio)
|
||||
}
|
||||
program
|
||||
.command('dump-workspace <workspace> <dirName>')
|
||||
.description('dump workspace transactions and minio resources')
|
||||
.action(async (workspace, dirName, cmd) => {
|
||||
const { mongodbUri, minio } = prepareTools()
|
||||
return await dumpWorkspace(mongodbUri, workspace, dirName, minio)
|
||||
})
|
||||
})
|
||||
|
||||
program
|
||||
.command('rebuild-elastic [workspace]')
|
||||
.description('rebuild elastic index')
|
||||
.action(async (workspace, cmd) => {
|
||||
const { mongodbUri, minio } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
if (workspace === undefined) {
|
||||
const workspaces = await listWorkspaces(db)
|
||||
program
|
||||
.command('backup <dirName> <workspace>')
|
||||
.description('dump workspace transactions and minio resources')
|
||||
.action(async (dirName, workspace, cmd) => {
|
||||
const storage = await createFileBackupStorage(dirName)
|
||||
return await backup(transactorUrl, workspace, storage)
|
||||
})
|
||||
|
||||
program
|
||||
.command('backup-restore <dirName> <workspace> [date]')
|
||||
.description('dump workspace transactions and minio resources')
|
||||
.action(async (dirName, workspace, date, cmd) => {
|
||||
const storage = await createFileBackupStorage(dirName)
|
||||
return await restore(transactorUrl, workspace, storage, parseInt(date ?? '-1'))
|
||||
})
|
||||
|
||||
program
|
||||
.command('backup-list <dirName>')
|
||||
.description('list snaphost ids for backup')
|
||||
.action(async (dirName, cmd) => {
|
||||
const storage = await createFileBackupStorage(dirName)
|
||||
return await backupList(storage)
|
||||
})
|
||||
|
||||
program
|
||||
.command('backup-s3 <bucketName> <dirName> <workspace>')
|
||||
.description('dump workspace transactions and minio resources')
|
||||
.action(async (bucketName, dirName, workspace, cmd) => {
|
||||
const { minio } = prepareTools()
|
||||
const storage = await createMinioBackupStorage(minio, bucketName, dirName)
|
||||
return await backup(transactorUrl, workspace, storage)
|
||||
})
|
||||
program
|
||||
.command('backup-s3-restore <bucketName>, <dirName> <workspace> [date]')
|
||||
.description('dump workspace transactions and minio resources')
|
||||
.action(async (bucketName, dirName, workspace, date, cmd) => {
|
||||
const { minio } = prepareTools()
|
||||
const storage = await createMinioBackupStorage(minio, bucketName, dirName)
|
||||
return await restore(transactorUrl, workspace, storage, parseInt(date ?? '-1'))
|
||||
})
|
||||
program
|
||||
.command('backup-s3-list <bucketName> <dirName>')
|
||||
.description('list snaphost ids for backup')
|
||||
.action(async (bucketName, dirName, cmd) => {
|
||||
const { minio } = prepareTools()
|
||||
const storage = await createMinioBackupStorage(minio, bucketName, dirName)
|
||||
return await backupList(storage)
|
||||
})
|
||||
|
||||
program
|
||||
.command('restore-workspace <workspace> <dirName>')
|
||||
.description('restore workspace transactions and minio resources from previous dump.')
|
||||
.action(async (workspace, dirName, cmd) => {
|
||||
const { mongodbUri, minio, txes, migrateOperations } = prepareTools()
|
||||
return await restoreWorkspace(
|
||||
mongodbUri,
|
||||
workspace,
|
||||
dirName,
|
||||
minio,
|
||||
getElasticUrl(),
|
||||
transactorUrl,
|
||||
txes,
|
||||
migrateOperations
|
||||
)
|
||||
})
|
||||
|
||||
program
|
||||
.command('diff-workspace <workspace>')
|
||||
.description('restore workspace transactions and minio resources from previous dump.')
|
||||
.action(async (workspace, cmd) => {
|
||||
const { mongodbUri, txes } = prepareTools()
|
||||
return await diffWorkspace(mongodbUri, workspace, txes)
|
||||
})
|
||||
|
||||
program
|
||||
.command('clear-telegram-history <workspace>')
|
||||
.description('clear telegram history')
|
||||
.option('-w, --workspace <workspace>', 'target workspace')
|
||||
.action(async (workspace: string, cmd) => {
|
||||
const { mongodbUri, minio } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
const telegramDB = process.env.TELEGRAM_DATABASE
|
||||
if (telegramDB === undefined) {
|
||||
console.error('please provide TELEGRAM_DATABASE.')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
console.log(`clearing ${workspace} history:`)
|
||||
await clearTelegramHistory(mongodbUri, workspace, telegramDB, minio)
|
||||
})
|
||||
})
|
||||
|
||||
program
|
||||
.command('clear-telegram-all-history')
|
||||
.description('clear telegram history')
|
||||
.action(async (cmd) => {
|
||||
const { mongodbUri, minio, productId } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
const telegramDB = process.env.TELEGRAM_DATABASE
|
||||
if (telegramDB === undefined) {
|
||||
console.error('please provide TELEGRAM_DATABASE.')
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
const workspaces = await listWorkspaces(db, productId)
|
||||
|
||||
for (const w of workspaces) {
|
||||
await rebuildElastic(mongodbUri, w.workspace, minio, getElasticUrl())
|
||||
console.log(`clearing ${w.workspace} history:`)
|
||||
await clearTelegramHistory(mongodbUri, w.workspace, telegramDB, minio)
|
||||
}
|
||||
} else {
|
||||
await rebuildElastic(mongodbUri, workspace, minio, getElasticUrl())
|
||||
console.log('rebuild end')
|
||||
}
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
program
|
||||
.command('import-xml <workspace> <fileName>')
|
||||
.description('Import Talants.')
|
||||
.action(async (workspace, fileName, cmd) => {
|
||||
const { mongodbUri, minio } = prepareTools()
|
||||
return await importXml(transactorUrl, workspace, minio, fileName, mongodbUri, getElasticUrl())
|
||||
})
|
||||
program
|
||||
.command('rebuild-elastic [workspace]')
|
||||
.description('rebuild elastic index')
|
||||
.action(async (workspace, cmd) => {
|
||||
const { mongodbUri, minio, productId } = prepareTools()
|
||||
return await withDatabase(mongodbUri, async (db) => {
|
||||
if (workspace === undefined) {
|
||||
const workspaces = await listWorkspaces(db, productId)
|
||||
|
||||
program
|
||||
.command('import-lead-csv <workspace> <fileName>')
|
||||
.description('Import LEAD csv customer organizations')
|
||||
.action(async (workspace, fileName, cmd) => {
|
||||
return await importLead(transactorUrl, workspace, fileName)
|
||||
})
|
||||
for (const w of workspaces) {
|
||||
await rebuildElastic(mongodbUri, w.workspace, minio, getElasticUrl())
|
||||
}
|
||||
} else {
|
||||
await rebuildElastic(mongodbUri, workspace, minio, getElasticUrl())
|
||||
console.log('rebuild end')
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
program
|
||||
.command('import-lead-csv2 <workspace> <fileName>')
|
||||
.description('Import LEAD csv customer organizations')
|
||||
.action(async (workspace, fileName, cmd) => {
|
||||
return await importLead2(transactorUrl, workspace, fileName)
|
||||
})
|
||||
program
|
||||
.command('import-xml <workspace> <fileName>')
|
||||
.description('Import Talants.')
|
||||
.action(async (workspace, fileName, cmd) => {
|
||||
const { mongodbUri, minio } = prepareTools()
|
||||
return await importXml(transactorUrl, workspace, minio, fileName, mongodbUri, getElasticUrl())
|
||||
})
|
||||
|
||||
program
|
||||
.command('import-talant-csv <workspace> <fileName>')
|
||||
.description('Import Talant csv')
|
||||
.action(async (workspace, fileName, cmd) => {
|
||||
const rekoniUrl = process.env.REKONI_URL
|
||||
if (rekoniUrl === undefined) {
|
||||
console.log('Please provide REKONI_URL environment variable')
|
||||
exit(1)
|
||||
}
|
||||
return await importTalants(transactorUrl, workspace, fileName, rekoniUrl)
|
||||
})
|
||||
program
|
||||
.command('import-lead-csv <workspace> <fileName>')
|
||||
.description('Import LEAD csv customer organizations')
|
||||
.action(async (workspace, fileName, cmd) => {
|
||||
return await importLead(transactorUrl, workspace, fileName)
|
||||
})
|
||||
|
||||
program
|
||||
.command('import-org-csv <workspace> <fileName>')
|
||||
.description('Import Organizations csv')
|
||||
.action(async (workspace, fileName, cmd) => {
|
||||
return await importOrgs(transactorUrl, workspace, fileName)
|
||||
})
|
||||
program
|
||||
.command('import-lead-csv2 <workspace> <fileName>')
|
||||
.description('Import LEAD csv customer organizations')
|
||||
.action(async (workspace, fileName, cmd) => {
|
||||
return await importLead2(transactorUrl, workspace, fileName)
|
||||
})
|
||||
|
||||
program
|
||||
.command('lead-duplicates <workspace>')
|
||||
.description('Find and remove duplicate organizations.')
|
||||
.action(async (workspace, cmd) => {
|
||||
return await removeDuplicates(transactorUrl, workspace)
|
||||
})
|
||||
program
|
||||
.command('import-talant-csv <workspace> <fileName>')
|
||||
.description('Import Talant csv')
|
||||
.action(async (workspace, fileName, cmd) => {
|
||||
const rekoniUrl = process.env.REKONI_URL
|
||||
if (rekoniUrl === undefined) {
|
||||
console.log('Please provide REKONI_URL environment variable')
|
||||
exit(1)
|
||||
}
|
||||
return await importTalants(transactorUrl, workspace, fileName, rekoniUrl)
|
||||
})
|
||||
|
||||
program
|
||||
.command('generate-token <name> <workspace>')
|
||||
.description('generate token')
|
||||
.action(async (name, workspace) => {
|
||||
console.log(generateToken(name, workspace))
|
||||
})
|
||||
program
|
||||
.command('decode-token <token>')
|
||||
.description('decode token')
|
||||
.action(async (token) => {
|
||||
console.log(decodeToken(token))
|
||||
})
|
||||
program
|
||||
.command('update-recruit <workspace>')
|
||||
.description('process pdf documents inside minio and update resumes with skills, etc.')
|
||||
.action(async (workspace) => {
|
||||
const rekoniUrl = process.env.REKONI_URL
|
||||
if (rekoniUrl === undefined) {
|
||||
console.log('Please provide REKONI_URL environment variable')
|
||||
exit(1)
|
||||
}
|
||||
const { mongodbUri, minio } = prepareTools()
|
||||
return await updateCandidates(transactorUrl, workspace, minio, mongodbUri, getElasticUrl(), rekoniUrl)
|
||||
})
|
||||
program
|
||||
.command('import-org-csv <workspace> <fileName>')
|
||||
.description('Import Organizations csv')
|
||||
.action(async (workspace, fileName, cmd) => {
|
||||
return await importOrgs(transactorUrl, workspace, fileName)
|
||||
})
|
||||
|
||||
program.parse(process.argv)
|
||||
program
|
||||
.command('lead-duplicates <workspace>')
|
||||
.description('Find and remove duplicate organizations.')
|
||||
.action(async (workspace, cmd) => {
|
||||
return await removeDuplicates(transactorUrl, workspace)
|
||||
})
|
||||
|
||||
program
|
||||
.command('generate-token <name> <workspace>')
|
||||
.description('generate token')
|
||||
.action(async (name, workspace) => {
|
||||
console.log(generateToken(name, workspace))
|
||||
})
|
||||
program
|
||||
.command('decode-token <token>')
|
||||
.description('decode token')
|
||||
.action(async (token) => {
|
||||
console.log(decodeToken(token))
|
||||
})
|
||||
program
|
||||
.command('update-recruit <workspace>')
|
||||
.description('process pdf documents inside minio and update resumes with skills, etc.')
|
||||
.action(async (workspace) => {
|
||||
const rekoniUrl = process.env.REKONI_URL
|
||||
if (rekoniUrl === undefined) {
|
||||
console.log('Please provide REKONI_URL environment variable')
|
||||
exit(1)
|
||||
}
|
||||
const { mongodbUri, minio } = prepareTools()
|
||||
return await updateCandidates(transactorUrl, workspace, minio, mongodbUri, getElasticUrl(), rekoniUrl)
|
||||
})
|
||||
|
||||
program.parse(process.argv)
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
import contact from '@hcengineering/contact'
|
||||
import core, { DOMAIN_TX, Tx } from '@hcengineering/core'
|
||||
import builder, { version } from '@hcengineering/model-all'
|
||||
import { MigrateOperation } from '@hcengineering/model'
|
||||
import { upgradeModel } from '@hcengineering/server-tool'
|
||||
import { existsSync } from 'fs'
|
||||
import { mkdir, open, readFile, writeFile } from 'fs/promises'
|
||||
@@ -54,7 +54,7 @@ export async function dumpWorkspace (mongoUrl: string, dbName: string, fileName:
|
||||
}
|
||||
|
||||
const workspaceInfo: WorkspaceInfo = {
|
||||
version: `${version.major}.${version.minor}.${version.patch}`,
|
||||
version: '0.0.0',
|
||||
collections: [],
|
||||
minioData: []
|
||||
}
|
||||
@@ -118,7 +118,9 @@ export async function restoreWorkspace (
|
||||
fileName: string,
|
||||
minio: Client,
|
||||
elasticUrl: string,
|
||||
transactorUrl: string
|
||||
transactorUrl: string,
|
||||
rawTxes: Tx[],
|
||||
migrateOperations: MigrateOperation[]
|
||||
): Promise<void> {
|
||||
console.log('Restoring workspace', mongoUrl, dbName, fileName)
|
||||
const client = new MongoClient(mongoUrl)
|
||||
@@ -170,7 +172,7 @@ export async function restoreWorkspace (
|
||||
}
|
||||
}
|
||||
|
||||
await upgradeModel(transactorUrl, dbName)
|
||||
await upgradeModel(transactorUrl, dbName, rawTxes, migrateOperations)
|
||||
|
||||
await rebuildElastic(mongoUrl, dbName, minio, elasticUrl)
|
||||
} finally {
|
||||
@@ -178,7 +180,7 @@ export async function restoreWorkspace (
|
||||
}
|
||||
}
|
||||
|
||||
export async function diffWorkspace (mongoUrl: string, dbName: string): Promise<void> {
|
||||
export async function diffWorkspace (mongoUrl: string, dbName: string, rawTxes: Tx[]): Promise<void> {
|
||||
const client = new MongoClient(mongoUrl)
|
||||
try {
|
||||
await client.connect()
|
||||
@@ -195,7 +197,7 @@ export async function diffWorkspace (mongoUrl: string, dbName: string): Promise<
|
||||
})
|
||||
.toArray()
|
||||
|
||||
const txes = builder.getTxes().filter((tx) => {
|
||||
const txes = rawTxes.filter((tx) => {
|
||||
return (
|
||||
tx.objectSpace === core.space.Model &&
|
||||
tx.modifiedBy === core.account.System &&
|
||||
|
||||
Reference in New Issue
Block a user