@things-factory/contact 7.0.71 → 7.0.73

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/client/components/contact-selector.ts +5 -2
  2. package/client/pages/contact-list-page.ts +3 -5
  3. package/dist-client/components/contact-selector.js +4 -1
  4. package/dist-client/components/contact-selector.js.map +1 -1
  5. package/dist-client/pages/contact-list-page.js +3 -5
  6. package/dist-client/pages/contact-list-page.js.map +1 -1
  7. package/dist-client/tsconfig.tsbuildinfo +1 -1
  8. package/dist-server/controllers/index.d.ts +1 -0
  9. package/dist-server/controllers/index.js +4 -0
  10. package/dist-server/controllers/index.js.map +1 -1
  11. package/dist-server/controllers/register-contact-as-system-user.d.ts +5 -0
  12. package/dist-server/controllers/register-contact-as-system-user.js +74 -0
  13. package/dist-server/controllers/register-contact-as-system-user.js.map +1 -0
  14. package/dist-server/index.d.ts +1 -3
  15. package/dist-server/index.js +1 -3
  16. package/dist-server/index.js.map +1 -1
  17. package/dist-server/routes.d.ts +0 -1
  18. package/dist-server/routes.js +0 -24
  19. package/dist-server/routes.js.map +1 -1
  20. package/dist-server/service/contact/contact-query.js +6 -5
  21. package/dist-server/service/contact/contact-query.js.map +1 -1
  22. package/dist-server/service/contact/contact.d.ts +1 -0
  23. package/dist-server/service/contact/contact.js +4 -0
  24. package/dist-server/service/contact/contact.js.map +1 -1
  25. package/dist-server/tsconfig.tsbuildinfo +1 -1
  26. package/package.json +5 -5
  27. package/server/controllers/index.ts +1 -0
  28. package/server/controllers/register-contact-as-system-user.ts +88 -0
  29. package/server/index.ts +1 -4
  30. package/server/routes.ts +0 -28
  31. package/server/service/contact/contact-query.ts +6 -5
  32. package/server/service/contact/contact.ts +4 -0
  33. package/translations/en.json +5 -1
  34. package/translations/ja.json +5 -1
  35. package/translations/ko.json +5 -1
  36. package/translations/ms.json +5 -1
  37. package/translations/zh.json +5 -1
  38. package/dist-server/middlewares/index.d.ts +0 -1
  39. package/dist-server/middlewares/index.js +0 -7
  40. package/dist-server/middlewares/index.js.map +0 -1
  41. package/dist-server/migrations/index.d.ts +0 -1
  42. package/dist-server/migrations/index.js +0 -12
  43. package/dist-server/migrations/index.js.map +0 -1
  44. package/server/middlewares/index.ts +0 -3
  45. package/server/migrations/index.ts +0 -9
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/contact",
3
- "version": "7.0.71",
3
+ "version": "7.0.73",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "dist-client/index.js",
6
6
  "things-factory": true,
@@ -32,9 +32,9 @@
32
32
  "@operato/i18n": "^7.0.0",
33
33
  "@operato/shell": "^7.0.0",
34
34
  "@operato/styles": "^7.0.0",
35
- "@things-factory/attachment-base": "^7.0.71",
36
- "@things-factory/auth-base": "^7.0.71",
37
- "@things-factory/shell": "^7.0.70"
35
+ "@things-factory/attachment-base": "^7.0.72",
36
+ "@things-factory/auth-base": "^7.0.72",
37
+ "@things-factory/shell": "^7.0.72"
38
38
  },
39
- "gitHead": "d242e4a4415764d0d389e9dff09d2ce3a8fc317f"
39
+ "gitHead": "5ce078745084f07a5df7d1ac9de56b2699a07a34"
40
40
  }
@@ -0,0 +1 @@
1
+ export * from './register-contact-as-system-user'
@@ -0,0 +1,88 @@
1
+ import { ILike } from 'typeorm'
2
+ import { Role, User, UserStatus } from '@things-factory/auth-base'
3
+ import { getRepository } from '@things-factory/shell'
4
+ import { config } from '@things-factory/env'
5
+ import { Contact, ContactField } from '../service/contact/contact'
6
+
7
+ const { defaultPassword } = config.get('password')
8
+
9
+ export async function registerContactAsSystemUser(
10
+ { contactId, roleName }: { contactId: string; roleName?: string },
11
+ context: ResolverContext
12
+ ) {
13
+ const { domain, user, tx } = context.state
14
+
15
+ const contactRepository = getRepository(Contact, tx)
16
+
17
+ const contact = await contactRepository.findOne({
18
+ where: {
19
+ id: contactId,
20
+ domain: { id: domain.id }
21
+ }
22
+ })
23
+
24
+ if (!contact) {
25
+ throw new Error(context.t('error.contact-not-found', { contactId }))
26
+ }
27
+
28
+ const email = contact.getContactItem(ContactField.Email, 'work')
29
+
30
+ if (!email) {
31
+ throw new Error(context.t('error.contact-email-not-set', { contactId }))
32
+ }
33
+
34
+ const userRepository = getRepository(User, tx)
35
+ const existingUser = await userRepository.findOne({
36
+ where: { email: ILike(email) },
37
+ relations: ['domains', 'roles']
38
+ })
39
+
40
+ if (existingUser && !existingUser.domains.find(d => d.id === domain.id)) {
41
+ existingUser.domains = [...existingUser.domains, domain]
42
+ }
43
+
44
+ if (!existingUser && !defaultPassword) {
45
+ throw new Error(context.t('error.contact-initial-password-required'))
46
+ }
47
+
48
+ const salt = !existingUser && User.generateSalt()
49
+
50
+ const newUser: Partial<User> = existingUser
51
+ ? existingUser
52
+ : {
53
+ name: contact.name,
54
+ email,
55
+ userType: 'user',
56
+ domains: [domain],
57
+ status: UserStatus.ACTIVATED,
58
+ salt,
59
+ passwordUpdatedAt: new Date(),
60
+ password: User.encode(defaultPassword, salt),
61
+ updater: user,
62
+ creator: user
63
+ }
64
+
65
+ if (roleName) {
66
+ const roleRepository = getRepository(Role, tx)
67
+ const role = await roleRepository.findOne({
68
+ where: {
69
+ name: roleName,
70
+ domain: { id: domain.id }
71
+ }
72
+ })
73
+
74
+ if (!role) {
75
+ throw new Error(context.t('error.contact-role-not-found', { roleName }))
76
+ }
77
+
78
+ if (newUser.roles) {
79
+ if (!newUser.roles.find(role => role.name == roleName)) {
80
+ newUser.roles = [...newUser.roles, role]
81
+ }
82
+ } else {
83
+ newUser.roles = [role]
84
+ }
85
+ }
86
+
87
+ return await userRepository.save(newUser)
88
+ }
package/server/index.ts CHANGED
@@ -1,5 +1,2 @@
1
- export * from './migrations'
2
- export * from './middlewares'
1
+ export * from './controllers'
3
2
  export * from './service'
4
-
5
- import './routes'
package/server/routes.ts CHANGED
@@ -1,28 +0,0 @@
1
- const debug = require('debug')('things-factory:contact:routes')
2
-
3
- process.on('bootstrap-module-global-public-route' as any, (app, globalPublicRouter) => {
4
- /*
5
- * can add global public routes to application (auth not required, tenancy not required)
6
- *
7
- * ex) routes.get('/path', async(context, next) => {})
8
- * ex) routes.post('/path', async(context, next) => {})
9
- */
10
- })
11
-
12
- process.on('bootstrap-module-global-private-route' as any, (app, globalPrivateRouter) => {
13
- /*
14
- * can add global private routes to application (auth required, tenancy not required)
15
- */
16
- })
17
-
18
- process.on('bootstrap-module-domain-public-route' as any, (app, domainPublicRouter) => {
19
- /*
20
- * can add domain public routes to application (auth not required, tenancy required)
21
- */
22
- })
23
-
24
- process.on('bootstrap-module-domain-private-route' as any, (app, domainPrivateRouter) => {
25
- /*
26
- * can add domain private routes to application (auth required, tenancy required)
27
- */
28
- })
@@ -1,4 +1,5 @@
1
1
  import { Resolver, Query, FieldResolver, Root, Args, Arg, Ctx } from 'type-graphql'
2
+ import { GraphQLEmailAddress } from 'graphql-scalars'
2
3
  import { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'
3
4
  import { User } from '@things-factory/auth-base'
4
5
  import { Attachment } from '@things-factory/attachment-base'
@@ -20,7 +21,7 @@ function getContactItems(contact: Contact) {
20
21
  function getContactItem(contact: Contact, type: String, label: String) {
21
22
  const { items } = contact
22
23
 
23
- return items?.find(item => item.type === type && item.label === label)?.value || null
24
+ return items?.find(item => item.type === type && item.label === label)?.value
24
25
  }
25
26
 
26
27
  @Resolver(Contact)
@@ -69,22 +70,22 @@ export class ContactQuery {
69
70
  return { left, top, zoom, picture: attachment?.fullpath }
70
71
  }
71
72
 
72
- @FieldResolver(type => String)
73
+ @FieldResolver(type => String, { nullable: true })
73
74
  async phone(@Root() contact: Contact): Promise<string> {
74
75
  return getContactItem(contact, ContactField.Phone, 'work')
75
76
  }
76
77
 
77
- @FieldResolver(type => String)
78
+ @FieldResolver(type => GraphQLEmailAddress, { nullable: true })
78
79
  async email(@Root() contact: Contact): Promise<string> {
79
80
  return getContactItem(contact, ContactField.Email, 'work')
80
81
  }
81
82
 
82
- @FieldResolver(type => String)
83
+ @FieldResolver(type => String, { nullable: true })
83
84
  async address(@Root() contact: Contact): Promise<string> {
84
85
  return getContactItem(contact, ContactField.Address, 'work')
85
86
  }
86
87
 
87
- @FieldResolver(type => String)
88
+ @FieldResolver(type => String, { nullable: true })
88
89
  async department(@Root() contact: Contact): Promise<string> {
89
90
  return getContactItem(contact, ContactField.Department, 'work')
90
91
  }
@@ -110,4 +110,8 @@ export class Contact {
110
110
 
111
111
  @RelationId((contact: Contact) => contact.updater)
112
112
  updaterId?: string
113
+
114
+ getContactItem(type: ContactField, label?: string) {
115
+ return (this.items || []).find(item => item.type === type && (!item.label || item.label === label))?.value
116
+ }
113
117
  }
@@ -8,5 +8,9 @@
8
8
  "field.phone": "phone",
9
9
  "title.contact": "contact",
10
10
  "title.contact list": "contact list",
11
- "title.edit": "edit"
11
+ "title.edit": "edit",
12
+ "error.contact-not-found": "Contact with ID {contactId} could not be found.",
13
+ "error.contact-email-not-set": "The contact with ID {contactId} does not have a work email set.",
14
+ "error.contact-initial-password-required": "An initial password or default password must be provided.",
15
+ "error.contact-role-not-found": "The role '{roleName}' could not be found in the domain."
12
16
  }
@@ -8,5 +8,9 @@
8
8
  "field.phone": "電話",
9
9
  "title.contact": "連絡先",
10
10
  "title.contact list": "連絡先リスト",
11
- "title.edit": "編集"
11
+ "title.edit": "編集",
12
+ "error.contact-not-found": "ID {contactId} の連絡先が見つかりません。",
13
+ "error.contact-email-not-set": "ID {contactId} の連絡先には勤務用のメールアドレスが設定されていません。",
14
+ "error.contact-initial-password-required": "初期パスワードまたはデフォルトパスワードが提供される必要があります。",
15
+ "error.contact-role-not-found": "ドメイン内で役割'{roleName}'が見つかりませんでした。"
12
16
  }
@@ -8,5 +8,9 @@
8
8
  "field.phone": "전화",
9
9
  "title.contact": "연락처",
10
10
  "title.contact list": "연락처 목록",
11
- "title.edit": "편집"
11
+ "title.edit": "편집",
12
+ "error.contact-not-found": "연락처({contactId})를 찾을 수 없습니다.",
13
+ "error.contact-email-not-set": "연락처({contactId})에 이메일(work) 정보가 없습니다.",
14
+ "error.contact-initial-password-required": "초기 비밀번호나 디폴트 비밀번호가 제공되어야 합니다.",
15
+ "error.contact-role-not-found": "'{name}'라는 이름의 역할이 정의되어 있지 않습니다."
12
16
  }
@@ -8,5 +8,9 @@
8
8
  "field.phone": "telefon",
9
9
  "title.contact": "kenalan",
10
10
  "title.contact list": "senarai kenalan",
11
- "title.edit": "edit"
11
+ "title.edit": "edit",
12
+ "error.contact-not-found": "Kenalan dengan ID {contactId} tidak dapat ditemui.",
13
+ "error.contact-email-not-set": "Kenalan dengan ID {contactId} tidak mempunyai emel kerja yang ditetapkan.",
14
+ "error.contact-initial-password-required": "kata laluan awal atau kata laluan lalai mesti disediakan.",
15
+ "error.contact-role-not-found": "Peranan '{roleName}' tidak dapat ditemui dalam domain."
12
16
  }
@@ -8,5 +8,9 @@
8
8
  "field.phone": "电话号码",
9
9
  "title.contact": "接触",
10
10
  "title.contact list": "联系人列表",
11
- "title.edit": "编辑"
11
+ "title.edit": "编辑",
12
+ "error.contact-not-found": "无法找到ID为{contactId}的联系人。",
13
+ "error.contact-email-not-set": "ID为{contactId}的联系人没有设置工作邮箱。",
14
+ "error.contact-initial-password-required": "必须提供初始密码或默认密码。",
15
+ "error.contact-role-not-found": "在域中找不到角色'{roleName}'。"
12
16
  }
@@ -1 +0,0 @@
1
- export declare function initMiddlewares(app: any): void;
@@ -1,7 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.initMiddlewares = initMiddlewares;
4
- function initMiddlewares(app) {
5
- /* can add middlewares into app */
6
- }
7
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/middlewares/index.ts"],"names":[],"mappings":";;AAAA,0CAEC;AAFD,SAAgB,eAAe,CAAC,GAAG;IACjC,kCAAkC;AACpC,CAAC","sourcesContent":["export function initMiddlewares(app) {\n /* can add middlewares into app */\n}\n"]}
@@ -1 +0,0 @@
1
- export declare var migrations: any[];
@@ -1,12 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.migrations = void 0;
4
- const glob = require('glob');
5
- const path = require('path');
6
- exports.migrations = [];
7
- glob.sync(path.resolve(__dirname, '.', '**', '*.js')).forEach(function (file) {
8
- if (file.indexOf('index.js') !== -1)
9
- return;
10
- exports.migrations = exports.migrations.concat(Object.values(require(path.resolve(file))) || []);
11
- });
12
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/migrations/index.ts"],"names":[],"mappings":";;;AAAA,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;AAC5B,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;AAEjB,QAAA,UAAU,GAAG,EAAE,CAAA;AAE1B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,UAAS,IAAI;IACzE,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAAE,OAAM;IAC3C,kBAAU,GAAG,kBAAU,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;AAClF,CAAC,CAAC,CAAA","sourcesContent":["const glob = require('glob')\nconst path = require('path')\n\nexport var migrations = []\n\nglob.sync(path.resolve(__dirname, '.', '**', '*.js')).forEach(function(file) {\n if (file.indexOf('index.js') !== -1) return\n migrations = migrations.concat(Object.values(require(path.resolve(file))) || [])\n})\n"]}
@@ -1,3 +0,0 @@
1
- export function initMiddlewares(app) {
2
- /* can add middlewares into app */
3
- }
@@ -1,9 +0,0 @@
1
- const glob = require('glob')
2
- const path = require('path')
3
-
4
- export var migrations = []
5
-
6
- glob.sync(path.resolve(__dirname, '.', '**', '*.js')).forEach(function(file) {
7
- if (file.indexOf('index.js') !== -1) return
8
- migrations = migrations.concat(Object.values(require(path.resolve(file))) || [])
9
- })