tool update

Signed-off-by: Andrey Platov <andrey@hardcoreeng.com>
This commit is contained in:
Andrey Platov 2021-09-10 09:57:49 +02:00
parent f3f4013fab
commit f1f254b104
No known key found for this signature in database
GPG Key ID: C8787EFEB4B64AF0
12 changed files with 1658 additions and 55 deletions

View File

@ -91,7 +91,6 @@ specifiers:
css-loader: ^5.2.1
deep-equal: ^2.0.5
dotenv-webpack: ^7.0.2
esbuild: ^0.12.24
eslint: ^7.32.0
eslint-config-standard-with-typescript: ^20.0.0
eslint-plugin-import: '2'
@ -213,7 +212,6 @@ dependencies:
css-loader: 5.2.7_webpack@5.48.0
deep-equal: 2.0.5
dotenv-webpack: 7.0.3_webpack@5.48.0
esbuild: 0.12.24
eslint: 7.32.0
eslint-config-standard-with-typescript: 20.0.0_2e482f375e273d762fe67cbd5e194b49
eslint-plugin-import: 2.23.4_eslint@7.32.0
@ -3463,12 +3461,6 @@ packages:
resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==}
dev: false
/esbuild/0.12.24:
resolution: {integrity: sha512-C0ibY+HsXzYB6L/pLWEiWjMpghKsIc58Q5yumARwBQsHl9DXPakW+5NI/Y9w4YXiz0PEP6XTGTT/OV4Nnsmb4A==}
hasBin: true
requiresBuild: true
dev: false
/esbuild/0.12.26:
resolution: {integrity: sha512-YmTkhPKjvTJ+G5e96NyhGf69bP+hzO0DscqaVJTi5GM34uaD4Ecj7omu5lJO+NrxCUBRhy2chONLK1h/2LwoXA==}
hasBin: true
@ -9431,7 +9423,7 @@ packages:
'@types/heft-jest': 1.0.2
'@types/node': 16.7.5
'@typescript-eslint/eslint-plugin': 4.28.5_a8e83fcad666e1ba86be4b2e27a20aea
esbuild: 0.12.24
esbuild: 0.12.26
eslint: 7.32.0
eslint-plugin-import: 2.23.4_eslint@7.32.0
eslint-plugin-node: 11.1.0_eslint@7.32.0
@ -10124,12 +10116,14 @@ packages:
dev: false
file:projects/tool.tgz_6c259fadfeb3a4b20890aefe87070b8b:
resolution: {integrity: sha512-Z0BaX1B1yinHaiai353t9rj20BUpViVPFU9rX9LC0dA8wvHQ/5WY8jgEmhwrHYhq/+iauybdXG8tBCJLBQTeBQ==, tarball: file:projects/tool.tgz}
resolution: {integrity: sha512-mb2zTxDp5DHlfEi7/b+0vGiTzSkQsIpDf3A5ZgT/zjugH4VCX2j8M7N7n+ZA1+KFdhw69egzQ3Hru0gCATaWEg==, tarball: file:projects/tool.tgz}
id: file:projects/tool.tgz
name: '@rush-temp/tool'
version: 0.0.0
dependencies:
'@types/heft-jest': 1.0.2
'@types/minio': 7.0.10
'@types/node': 16.7.5
'@typescript-eslint/eslint-plugin': 4.28.5_a8e83fcad666e1ba86be4b2e27a20aea
commander: 8.1.0
esbuild: 0.12.26
@ -10137,12 +10131,13 @@ packages:
eslint-plugin-import: 2.23.4_eslint@7.32.0
eslint-plugin-node: 11.1.0_eslint@7.32.0
eslint-plugin-promise: 4.3.1
jwt-simple: 0.5.6
minio: 7.0.19
mongodb: 4.1.1
ts-node: 10.2.1_typescript@4.3.5
ts-node: 10.2.1_eb14afb1492fcd444e277f1fdb668e87
transitivePeerDependencies:
- '@swc/core'
- '@swc/wasm'
- '@types/node'
- '@typescript-eslint/parser'
- supports-color
- typescript

View File

@ -21,11 +21,19 @@
"eslint-plugin-node":"11",
"eslint":"^7.32.0",
"ts-node":"^10.2.1",
"esbuild":"^0.12.26"
"esbuild":"^0.12.26",
"@types/minio":"^7.0.10",
"@types/node":"^16.7.5"
},
"dependencies": {
"mongodb":"^4.1.1",
"commander":"^8.1.0",
"@anticrm/account":"~0.6.0"
"@anticrm/account":"~0.6.0",
"jwt-simple":"^0.5.6",
"@anticrm/contrib":"~0.6.0",
"@anticrm/core":"~0.6.11",
"@anticrm/contact":"~0.6.0",
"@anticrm/workspace":"~0.6.0",
"minio":"^7.0.19"
}
}

View File

@ -20,5 +20,7 @@ export MINIO_SECRET_KEY=$(kubectl get secret --namespace default minio -o jsonpa
kubectl run anticrm-tool --rm --tty -i --restart='Never' \
--env="MONGO_URL=mongodb://root:$MONGODB_ROOT_PASSWORD@mng-mongodb:27017/" \
--env="TRANSACTOR_URL=ws://transactor/" \
--env="MINIO_ENDPOINT=minio" \
--env="MINIO_ACCESS_KEY=$MINIO_ACCESS_KEY" \
--env="MINIO_SECRET_KEY=$MINIO_SECRET_KEY" --image anticrm/tool --command -- bash

View File

@ -17,8 +17,51 @@
import { program } from 'commander'
import { MongoClient, Db } from 'mongodb'
import { getAccount, createAccount, assignWorkspace, createWorkspace } from '@anticrm/account'
import { createContributingClient } from '@anticrm/contrib'
import core, { TxOperations } from '@anticrm/core'
import { encode } from 'jwt-simple'
import { Client } from 'minio'
import { initWorkspace } from './workspace'
const mongodbUri = process.env.MONGO_URL ?? 'mongodb://localhost:27017'
import contact from '@anticrm/contact'
const mongodbUri = process.env.MONGO_URL
if (mongodbUri === undefined) {
console.error('please provide mongodb url.')
process.exit(1)
}
const transactorUrl = process.env.TRANSACTOR_URL
if (transactorUrl === undefined) {
console.error('please provide transactor 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 Client({
endPoint: minioEndpoint,
port: 9000,
useSSL: false,
accessKey: minioAccessKey,
secretKey: minioSecretKey
})
async function withDatabase (uri: string, f: (db: Db) => Promise<any>): Promise<void> {
console.log(`connecting to database '${uri}'...`)
@ -35,21 +78,40 @@ program
.command('create-user <email>')
.description('create user and corresponding account in master database')
.requiredOption('-p, --password <password>', 'user password')
.requiredOption('-f, --fullname <fullname>', 'full user name')
.action(async (email, cmd) => {
.requiredOption('-f, --first <firstname>', 'first name')
.requiredOption('-l, --last <lastname>', 'first name')
.action(async (email: string, cmd) => {
return await withDatabase(mongodbUri, async (db) => {
await createAccount(db, email, cmd.password)
// await createContact(withTenant(client, cmd.workspace), email, cmd.fullname)
console.log(`creating account ${cmd.firstname as string} ${cmd.lastname as string} (${email})...`)
await createAccount(db, email, cmd.password, cmd.firstname, cmd.lastname)
})
})
program
.command('assign-workspace <email> <workspace>')
.description('assign workspace')
.action(async (email, workspace, cmd) => {
.action(async (email: string, workspace: string, cmd) => {
return await withDatabase(mongodbUri, async (db) => {
console.log(`assigning user ${email as string} to ${workspace as string}...`)
console.log(`retrieveing account from ${email}...`)
const account = await getAccount(db, email)
if (account === null) {
throw new Error('account not found')
}
console.log(`assigning user ${email} to ${workspace}...`)
await assignWorkspace(db, email, workspace)
const token = encode({ email: 'anticrm@hc.engineering', workspace }, 'secret')
const url = new URL(`/${token}`, transactorUrl)
const contrib = await createContributingClient(url.href)
const txop = new TxOperations(contrib, core.account.System)
await txop.createDoc(contact.class.Employee, contact.space.Employee, {
firstName: account.first,
lastName: account.last,
city: 'Mountain View',
channels: []
})
await txop.createDoc(core.class.Account, core.space.Model, {
email
})
})
})
@ -70,8 +132,7 @@ program
.action(async (workspace, cmd) => {
return await withDatabase(mongodbUri, async (db) => {
await createWorkspace(db, workspace, cmd.organization)
// await initDatabase(withTenant(client, workspace))
await initWorkspace(mongodbUri, workspace, transactorUrl, minio)
})
})

1490
dev/tool/src/model.tx.json Normal file

File diff suppressed because it is too large Load Diff

59
dev/tool/src/workspace.ts Normal file
View File

@ -0,0 +1,59 @@
//
// 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 { MongoClient, Document } from 'mongodb'
import core, { DOMAIN_TX, Tx } from '@anticrm/core'
import { createContributingClient } from '@anticrm/contrib'
import { encode } from 'jwt-simple'
import { Client } from 'minio'
import * as txJson from './model.tx.json'
const txes = (txJson as any).default as Tx[]
/**
* @public
*/
export async function initWorkspace (mongoUrl: string, dbName: string, clientUrl: string, minio: Client): Promise<void> {
const client = new MongoClient(mongoUrl)
try {
await client.connect()
const db = client.db(dbName)
console.log('dropping database...')
await db.dropDatabase()
console.log('creating model...')
const model = txes.filter(tx => tx.objectSpace === core.space.Model)
const result = await db.collection(DOMAIN_TX).insertMany(model as Document[])
console.log(`${result.insertedCount} model transactions inserted.`)
console.log('creating data...')
const data = txes.filter(tx => tx.objectSpace !== core.space.Model)
const token = encode({ email: 'anticrm@hc.engineering', workspace: dbName }, 'secret')
const url = new URL(`/${token}`, clientUrl)
const contrib = await createContributingClient(url.href)
for (const tx of data) {
await contrib.tx(tx)
}
contrib.close()
console.log('create minio bucket')
if (!await minio.bucketExists(dbName)) { await minio.makeBucket(dbName, 'k8s') }
} finally {
await client.close()
}
}

View File

@ -3,6 +3,7 @@
"compilerOptions": {
"rootDir": "./src",
"outDir": "./lib"
"outDir": "./lib",
"esModuleInterop": true
}
}

View File

@ -14,7 +14,7 @@
//
import { mergeIds } from '@anticrm/platform'
import type { Ref, Space, Class, Type } from '@anticrm/core'
import type { Ref, Class, Type } from '@anticrm/core'
import contact, { contactId } from '@anticrm/contact'
import type { ChannelProvider, Channel } from '@anticrm/contact'
import type { AnyComponent } from '@anticrm/ui'
@ -35,8 +35,5 @@ export const ids = mergeIds(contactId, contact, {
},
class: {
TypeChannels: '' as Ref<Class<Type<Channel[]>>>
},
space: {
Employee: '' as Ref<Space>
}
})

View File

@ -16,33 +16,10 @@
import { Builder } from '@anticrm/model'
import core from '@anticrm/core'
import contact from '@anticrm/model-contact'
import recruit from '@anticrm/model-recruit'
export function createDemo (builder: Builder): void {
builder.createDoc(contact.class.Employee, contact.space.Employee, {
firstName: 'Rosamund',
lastName: 'Chen',
city: 'Mountain View',
channels: []
})
builder.createDoc(core.class.Account, core.space.Model, {
email: 'rosamund@hc.engineering'
})
builder.createDoc(contact.class.Employee, contact.space.Employee, {
firstName: 'Elon',
lastName: 'Musk',
city: 'Bel Air',
channels: []
})
builder.createDoc(core.class.Account, core.space.Model, {
email: 'elon@hc.engineering'
})
builder.createDoc(recruit.class.Candidate, recruit.space.CandidatesPublic, {
firstName: 'Andrey',
lastName: 'P.',

View File

@ -15,7 +15,7 @@
import { plugin } from '@anticrm/platform'
import type { Plugin, Asset } from '@anticrm/platform'
import type { Doc, Ref, Class, UXObject } from '@anticrm/core'
import type { Doc, Ref, Class, UXObject, Space } from '@anticrm/core'
/**
* @public
@ -90,5 +90,8 @@ export default plugin(contactId, {
WhatsApp: '' as Asset,
Youtube: '' as Asset,
GitHub: '' as Asset
},
space: {
Employee: '' as Ref<Space>
}
})

View File

@ -51,6 +51,8 @@ const accountPlugin = plugin(accountId, {
export interface Account {
_id: ObjectId
email: string
first: string
last: string
hash: Binary
salt: Binary
workspaces: ObjectId[]
@ -161,7 +163,7 @@ export async function login (db: Db, email: string, password: string, workspace:
/**
* @public
*/
export async function createAccount (db: Db, email: string, password: string): Promise<AccountInfo> {
export async function createAccount (db: Db, email: string, password: string, first: string, last: string): Promise<AccountInfo> {
const salt = randomBytes(32)
const hash = hashWithSalt(password, salt)
@ -174,11 +176,15 @@ export async function createAccount (db: Db, email: string, password: string): P
email,
hash,
salt,
first,
last,
workspaces: []
})
return {
_id: insert.insertedId,
first,
last,
email,
workspaces: []
}

View File

@ -14,17 +14,21 @@
// limitations under the License.
//
import type { Tx, WithTx } from '@anticrm/core'
import { Tx, Storage, Class, Doc, DocumentQuery, FindOptions, Ref, FindResult } from '@anticrm/core'
import { serialize } from '@anticrm/platform'
import WebSocket from 'ws'
/**
* @public
*/
export class ContributingClient implements WithTx {
export class ContributingClient implements Storage {
constructor (private readonly websocket: WebSocket) {
}
findAll <T extends Doc>(_class: Ref<Class<T>>, query: DocumentQuery<T>, options?: FindOptions<T> | undefined): Promise<FindResult<T>> {
throw new Error('findAll not implemeneted for contributing client')
}
async tx (tx: Tx): Promise<void> {
this.websocket.send(serialize({
method: 'tx',