@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.
- package/client/components/contact-selector.ts +5 -2
- package/client/pages/contact-list-page.ts +3 -5
- package/dist-client/components/contact-selector.js +4 -1
- package/dist-client/components/contact-selector.js.map +1 -1
- package/dist-client/pages/contact-list-page.js +3 -5
- package/dist-client/pages/contact-list-page.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/controllers/index.d.ts +1 -0
- package/dist-server/controllers/index.js +4 -0
- package/dist-server/controllers/index.js.map +1 -1
- package/dist-server/controllers/register-contact-as-system-user.d.ts +5 -0
- package/dist-server/controllers/register-contact-as-system-user.js +74 -0
- package/dist-server/controllers/register-contact-as-system-user.js.map +1 -0
- package/dist-server/index.d.ts +1 -3
- package/dist-server/index.js +1 -3
- package/dist-server/index.js.map +1 -1
- package/dist-server/routes.d.ts +0 -1
- package/dist-server/routes.js +0 -24
- package/dist-server/routes.js.map +1 -1
- package/dist-server/service/contact/contact-query.js +6 -5
- package/dist-server/service/contact/contact-query.js.map +1 -1
- package/dist-server/service/contact/contact.d.ts +1 -0
- package/dist-server/service/contact/contact.js +4 -0
- package/dist-server/service/contact/contact.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/server/controllers/index.ts +1 -0
- package/server/controllers/register-contact-as-system-user.ts +88 -0
- package/server/index.ts +1 -4
- package/server/routes.ts +0 -28
- package/server/service/contact/contact-query.ts +6 -5
- package/server/service/contact/contact.ts +4 -0
- package/translations/en.json +5 -1
- package/translations/ja.json +5 -1
- package/translations/ko.json +5 -1
- package/translations/ms.json +5 -1
- package/translations/zh.json +5 -1
- package/dist-server/middlewares/index.d.ts +0 -1
- package/dist-server/middlewares/index.js +0 -7
- package/dist-server/middlewares/index.js.map +0 -1
- package/dist-server/migrations/index.d.ts +0 -1
- package/dist-server/migrations/index.js +0 -12
- package/dist-server/migrations/index.js.map +0 -1
- package/server/middlewares/index.ts +0 -3
- 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.
|
|
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.
|
|
36
|
-
"@things-factory/auth-base": "^7.0.
|
|
37
|
-
"@things-factory/shell": "^7.0.
|
|
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": "
|
|
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
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
|
|
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 =>
|
|
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
|
}
|
package/translations/en.json
CHANGED
|
@@ -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
|
}
|
package/translations/ja.json
CHANGED
|
@@ -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
|
}
|
package/translations/ko.json
CHANGED
|
@@ -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
|
}
|
package/translations/ms.json
CHANGED
|
@@ -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
|
}
|
package/translations/zh.json
CHANGED
|
@@ -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 +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,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
|
-
})
|