Skip to content

Commit 7dec3cf

Browse files
authored
uberf-9383: fix ws init and import (#8005)
Signed-off-by: Alexey Zinoviev <[email protected]>
1 parent 07e9c88 commit 7dec3cf

File tree

14 files changed

+176
-89
lines changed

14 files changed

+176
-89
lines changed

.vscode/launch.json

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -138,11 +138,10 @@
138138
"env": {
139139
"MONGO_URL": "mongodb://localhost:27017",
140140
"DB_URL": "mongodb://localhost:27017",
141-
// "DB_URL": "postgresql://postgres:example@localhost:5432",
142141
// "DB_URL": "postgresql://[email protected]:26257/defaultdb?sslmode=disable",
143142
"SERVER_SECRET": "secret",
144-
"REGION_INFO":"|Mongo;pg|Postgres;cockroach|CockroachDB",
145-
"TRANSACTOR_URL": "ws://host.docker.internal:3333,ws://host.docker.internal:3331;;pg,ws://host.docker.internal:3332;;cockroach",
143+
"REGION_INFO":"|Mongo;cockroach|CockroachDB",
144+
"TRANSACTOR_URL": "ws://host.docker.internal:3333,ws://host.docker.internal:3332;;cockroach",
146145
"ACCOUNTS_URL": "http://localhost:3000",
147146
"ACCOUNT_PORT": "3000",
148147
"FRONT_URL": "http://localhost:8080",
@@ -154,8 +153,6 @@
154153
"MINIO_SECRET_KEY": "minioadmin",
155154
"MINIO_ENDPOINT": "localhost"
156155
// "DISABLE_SIGNUP": "true",
157-
// "INIT_SCRIPT_URL": "https://raw.githubusercontent.com/hcengineering/init/main/script.yaml",
158-
// "INIT_WORKSPACE": "onboarding",
159156
},
160157
"runtimeVersion": "20",
161158
"runtimeArgs": ["--nolazy", "-r", "ts-node/register"],
@@ -187,8 +184,6 @@
187184
"MINIO_SECRET_KEY": "minioadmin",
188185
"MINIO_ENDPOINT": "localhost"
189186
// "DISABLE_SIGNUP": "true",
190-
// "INIT_SCRIPT_URL": "https://raw.githubusercontent.com/hcengineering/init/main/script.yaml",
191-
// "INIT_WORKSPACE": "onboarding",
192187
},
193188
"runtimeVersion": "20",
194189
"runtimeArgs": ["--nolazy", "-r", "ts-node/register"],
@@ -236,8 +231,8 @@
236231
"WS_OPERATION": "all+backup",
237232
"BACKUP_STORAGE": "minio|minio?accessKey=minioadmin&secretKey=minioadmin",
238233
"BACKUP_BUCKET": "dev-backups",
239-
// "INIT_SCRIPT_URL": "https://raw.githubusercontent.com/hcengineering/init/main/script.yaml",
240-
// "INIT_WORKSPACE": "onboarding",
234+
// "INIT_REPO_DIR": "${workspaceRoot}/pods/workspace/init",
235+
// "INIT_WORKSPACE": "staging-dev"
241236
},
242237
"runtimeVersion": "20",
243238
"runtimeArgs": ["--nolazy", "-r", "ts-node/register"],
@@ -269,8 +264,8 @@
269264
"WS_OPERATION": "all+backup",
270265
"BACKUP_STORAGE": "minio|minio?accessKey=minioadmin&secretKey=minioadmin",
271266
"BACKUP_BUCKET": "dev-backups",
272-
// "INIT_SCRIPT_URL": "https://raw.githubusercontent.com/hcengineering/init/main/script.yaml",
273-
// "INIT_WORKSPACE": "onboarding",
267+
// "INIT_REPO_DIR": "${workspaceRoot}/pods/workspace/init",
268+
// "INIT_WORKSPACE": "staging-dev"
274269
},
275270
"runtimeVersion": "20",
276271
"runtimeArgs": ["--nolazy", "-r", "ts-node/register"],

dev/docker-compose.yaml

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ services:
8080
# Pass only one region to disallow selection for new workspaces.Ø
8181
- REGION_INFO=|Mongo;cockroach|CockroachDB
8282
# - REGION_INFO=cockroach|CockroachDB
83-
- TRANSACTOR_URL=ws://host.docker.internal:3333,ws://host.docker.internal:3331;;pg,ws://host.docker.internal:3332;;cockroach,
83+
- TRANSACTOR_URL=ws://host.docker.internal:3333,ws://host.docker.internal:3332;;cockroach,
8484
- SES_URL=
8585
- STORAGE_CONFIG=${STORAGE_CONFIG}
8686
- FRONT_URL=http://host.docker.internal:8087
@@ -91,8 +91,6 @@ services:
9191
- ACCOUNTS_URL=http://host.docker.internal:3000
9292
- BRANDING_PATH=/var/cfg/branding.json
9393
# - DISABLE_SIGNUP=true
94-
# - INIT_SCRIPT_URL=https://raw.githubusercontent.com/hcengineering/init/main/script.yaml
95-
# - INIT_WORKSPACE=onboarding
9694
restart: unless-stopped
9795
stats:
9896
image: hardcoreeng/stats
@@ -126,9 +124,9 @@ services:
126124
- ACCOUNTS_URL=http://host.docker.internal:3000
127125
- BRANDING_PATH=/var/cfg/branding.json
128126
# - PARALLEL=2
129-
- INIT_WORKSPACE=test
130127
- BACKUP_STORAGE=${BACKUP_STORAGE_CONFIG}
131128
- BACKUP_BUCKET=${BACKUP_BUCKET_NAME}
129+
# - INIT_WORKSPACE=staging-dev
132130
restart: unless-stopped
133131
workspace_cockroach:
134132
image: hardcoreeng/workspace
@@ -153,9 +151,9 @@ services:
153151
- ACCOUNTS_URL=http://host.docker.internal:3000
154152
- BRANDING_PATH=/var/cfg/branding.json
155153
# - PARALLEL=2
156-
# - INIT_WORKSPACE=onboarding
157154
- BACKUP_STORAGE=${BACKUP_STORAGE_CONFIG}
158155
- BACKUP_BUCKET=${BACKUP_BUCKET_NAME}
156+
# - INIT_WORKSPACE=staging-dev
159157
restart: unless-stopped
160158
collaborator:
161159
image: hardcoreeng/collaborator

dev/tool/src/db.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ export async function moveAccountDbFromMongoToPG (
334334
}
335335

336336
if (workspacesCount % 100 === 0) {
337-
ctx.info(`Migrated ${workspacesCount} invites...`)
337+
ctx.info(`Migrated ${workspacesCount} workspaces...`)
338338
}
339339
}
340340
ctx.info(`Migrated ${workspacesCount} workspaces with ${membersCount} member assignments`)

dev/tool/src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import {
4646
AccountRole,
4747
MeasureMetricsContext,
4848
metricsToString,
49+
type PersonId,
4950
type Data,
5051
type Tx,
5152
type Version,
@@ -304,7 +305,7 @@ export function devTool (
304305
const measureCtx = new MeasureMetricsContext('create-workspace', {})
305306
const brandingObj =
306307
cmd.branding !== undefined || cmd.init !== undefined ? { key: cmd.branding, initWorkspace: cmd.init } : null
307-
const socialId = await db.socialId.findOne({ key: socialString })
308+
const socialId = await db.socialId.findOne({ key: socialString as PersonId })
308309
if (socialId == null) {
309310
throw new Error(`Social id ${socialString} not found`)
310311
}

packages/account-client/src/client.ts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ import {
1717
BackupStatus,
1818
Data,
1919
type Person,
20-
PersonUuid,
20+
type PersonUuid,
21+
type PersonInfo,
2122
SocialId,
2223
Version,
2324
type WorkspaceInfoWithStatus,
@@ -73,6 +74,7 @@ export interface AccountClient {
7374
signUp: (email: string, password: string, first: string, last: string) => Promise<LoginInfo>
7475
login: (email: string, password: string) => Promise<LoginInfo>
7576
getPerson: () => Promise<Person>
77+
getPersonInfo: (account: PersonUuid) => Promise<PersonInfo>
7678
getSocialIds: () => Promise<SocialId[]>
7779
getWorkspaceMembers: () => Promise<WorkspaceMemberInfo[]>
7880
updateWorkspaceRole: (account: string, role: AccountRole) => Promise<void>
@@ -399,6 +401,15 @@ class AccountClientImpl implements AccountClient {
399401
return await this.rpc(request)
400402
}
401403

404+
async getPersonInfo (account: PersonUuid): Promise<PersonInfo> {
405+
const request = {
406+
method: 'getPersonInfo' as const,
407+
params: [account]
408+
}
409+
410+
return await this.rpc(request)
411+
}
412+
402413
async getSocialIds (): Promise<SocialId[]> {
403414
const request = {
404415
method: 'getSocialIds' as const,

packages/core/src/classes.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,10 @@ export interface Person {
538538
city?: string
539539
}
540540

541+
export interface PersonInfo extends BasePerson {
542+
socialIds: PersonId[]
543+
}
544+
541545
/**
542546
* @public
543547
*/

packages/importer/src/huly/unified.ts

Lines changed: 44 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@
1616
import { type Attachment } from '@hcengineering/attachment'
1717
import contact, { Employee, type Person } from '@hcengineering/contact'
1818
import {
19+
buildSocialIdString,
1920
type Class,
2021
type Doc,
2122
generateId,
2223
PersonId,
2324
type Ref,
25+
SocialIdType,
2426
type Space,
2527
type TxOperations
2628
} from '@hcengineering/core'
@@ -330,24 +332,26 @@ interface AttachmentMetadata {
330332
}
331333

332334
export class UnifiedFormatImporter {
335+
private readonly importerEmailPlaceholder = '[email protected]'
336+
private readonly importerNamePlaceholder = 'New User'
333337
private readonly pathById = new Map<Ref<Doc>, string>()
334338
private readonly refMetaByPath = new Map<string, ReferenceMetadata>()
335339
private readonly fileMetaByPath = new Map<string, AttachmentMetadata>()
336340
private readonly ctrlDocTemplateIdByPath = new Map<string, Ref<ControlledDocument>>()
337341

338342
private personsByName = new Map<string, Ref<Person>>()
339-
// private accountsByEmail = new Map<string, Ref<PersonAccount>>()
340-
// private employeesByName = new Map<string, Ref<Employee>>()
343+
private employeesByName = new Map<string, Ref<Employee>>()
341344

342345
constructor (
343346
private readonly client: TxOperations,
344347
private readonly fileUploader: FileUploader,
345-
private readonly logger: Logger
348+
private readonly logger: Logger,
349+
private readonly importerSocialId?: PersonId,
350+
private readonly importerPerson?: Ref<Person>
346351
) {}
347352

348353
private async initCaches (): Promise<void> {
349354
await this.cachePersonsByNames()
350-
await this.cacheAccountsByEmails()
351355
await this.cacheEmployeesByName()
352356
}
353357

@@ -588,31 +592,31 @@ export class UnifiedFormatImporter {
588592
if (name === undefined) {
589593
return undefined
590594
}
595+
596+
if (name === this.importerNamePlaceholder && this.importerPerson != null) {
597+
return this.importerPerson
598+
}
591599
const person = this.personsByName.get(name)
592600
if (person === undefined) {
593601
throw new Error(`Person not found: ${name}`)
594602
}
595603
return person
596604
}
597605

598-
private findAccountByEmail (email: string): PersonId {
599-
// TODO: FIXME
600-
throw new Error('Not implemented')
601-
// const account = this.accountsByEmail.get(email)
602-
// if (account === undefined) {
603-
// throw new Error(`Account not found: ${email}`)
604-
// }
605-
// return account
606+
private getSocialIdByEmail (email: string): PersonId {
607+
if (email === this.importerEmailPlaceholder && this.importerSocialId != null) {
608+
return this.importerSocialId
609+
}
610+
611+
return buildSocialIdString({ type: SocialIdType.EMAIL, value: email })
606612
}
607613

608614
private findEmployeeByName (name: string): Ref<Employee> {
609-
// TODO: FIXME
610-
throw new Error('Not implemented')
611-
// const employee = this.employeesByName.get(name)
612-
// if (employee === undefined) {
613-
// throw new Error(`Employee not found: ${name}`)
614-
// }
615-
// return employee
615+
const employee = this.employeesByName.get(name)
616+
if (employee === undefined) {
617+
throw new Error(`Employee not found: ${name}`)
618+
}
619+
return employee
616620
}
617621

618622
private async processDocumentsRecursively (
@@ -752,7 +756,7 @@ export class UnifiedFormatImporter {
752756
}
753757
return {
754758
text: comment.text,
755-
author: this.findAccountByEmail(comment.author),
759+
author: this.getSocialIdByEmail(comment.author),
756760
attachments
757761
}
758762
})
@@ -789,9 +793,9 @@ export class UnifiedFormatImporter {
789793
defaultIssueStatus:
790794
projectHeader.defaultIssueStatus !== undefined ? { name: projectHeader.defaultIssueStatus } : undefined,
791795
owners:
792-
projectHeader.owners !== undefined ? projectHeader.owners.map((email) => this.findAccountByEmail(email)) : [],
796+
projectHeader.owners !== undefined ? projectHeader.owners.map((email) => this.getSocialIdByEmail(email)) : [],
793797
members:
794-
projectHeader.members !== undefined ? projectHeader.members.map((email) => this.findAccountByEmail(email)) : [],
798+
projectHeader.members !== undefined ? projectHeader.members.map((email) => this.getSocialIdByEmail(email)) : [],
795799
docs: []
796800
}
797801
}
@@ -805,9 +809,9 @@ export class UnifiedFormatImporter {
805809
archived: spaceHeader.archived ?? false,
806810
description: spaceHeader.description,
807811
emoji: spaceHeader.emoji,
808-
owners: spaceHeader.owners !== undefined ? spaceHeader.owners.map((email) => this.findAccountByEmail(email)) : [],
812+
owners: spaceHeader.owners !== undefined ? spaceHeader.owners.map((email) => this.getSocialIdByEmail(email)) : [],
809813
members:
810-
spaceHeader.members !== undefined ? spaceHeader.members.map((email) => this.findAccountByEmail(email)) : [],
814+
spaceHeader.members !== undefined ? spaceHeader.members.map((email) => this.getSocialIdByEmail(email)) : [],
811815
docs: []
812816
}
813817
}
@@ -819,11 +823,11 @@ export class UnifiedFormatImporter {
819823
private: spaceHeader.private ?? false,
820824
archived: spaceHeader.archived ?? false,
821825
description: spaceHeader.description,
822-
owners: spaceHeader.owners?.map((email) => this.findAccountByEmail(email)) ?? [],
823-
members: spaceHeader.members?.map((email) => this.findAccountByEmail(email)) ?? [],
824-
qualified: spaceHeader.qualified !== undefined ? this.findAccountByEmail(spaceHeader.qualified) : undefined,
825-
manager: spaceHeader.manager !== undefined ? this.findAccountByEmail(spaceHeader.manager) : undefined,
826-
qara: spaceHeader.qara !== undefined ? this.findAccountByEmail(spaceHeader.qara) : undefined,
826+
owners: spaceHeader.owners?.map((email) => this.getSocialIdByEmail(email)) ?? [],
827+
members: spaceHeader.members?.map((email) => this.getSocialIdByEmail(email)) ?? [],
828+
qualified: spaceHeader.qualified !== undefined ? this.getSocialIdByEmail(spaceHeader.qualified) : undefined,
829+
manager: spaceHeader.manager !== undefined ? this.getSocialIdByEmail(spaceHeader.manager) : undefined,
830+
qara: spaceHeader.qara !== undefined ? this.getSocialIdByEmail(spaceHeader.qara) : undefined,
827831
docs: []
828832
}
829833
}
@@ -950,30 +954,18 @@ export class UnifiedFormatImporter {
950954
}, new Map())
951955
}
952956

953-
private async cacheAccountsByEmails (): Promise<void> {
954-
// TODO: FIXME
955-
throw new Error('Not implemented')
956-
// const accounts = await this.client.findAll(contact.class.PersonAccount, {})
957-
// this.accountsByEmail = accounts.reduce((map, account) => {
958-
// map.set(account.email, account._id)
959-
// return map
960-
// }, new Map())
961-
}
962-
963957
private async cacheEmployeesByName (): Promise<void> {
964-
// TODO: FIXME
965-
throw new Error('Not implemented')
966-
// this.employeesByName = (await this.client.findAll(contact.mixin.Employee, {}))
967-
// .map((employee) => {
968-
// return {
969-
// _id: employee._id,
970-
// name: employee.name.split(',').reverse().join(' ')
971-
// }
972-
// })
973-
// .reduce((refByName, employee) => {
974-
// refByName.set(employee.name, employee._id)
975-
// return refByName
976-
// }, new Map())
958+
this.employeesByName = (await this.client.findAll(contact.mixin.Employee, {}))
959+
.map((employee) => {
960+
return {
961+
_id: employee._id,
962+
name: employee.name.split(',').reverse().join(' ')
963+
}
964+
})
965+
.reduce((refByName, employee) => {
966+
refByName.set(employee.name, employee._id)
967+
return refByName
968+
}, new Map())
977969
}
978970

979971
private async collectFileMetadata (folderPath: string): Promise<void> {

pods/workspace/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
init

0 commit comments

Comments
 (0)