@things-factory/auth-base 7.0.70 → 7.0.72
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/dist-server/controllers/change-pwd.js.map +1 -1
- package/dist-server/service/privilege/privilege-directive.js +8 -0
- package/dist-server/service/privilege/privilege-directive.js.map +1 -1
- package/dist-server/service/user/user-mutation.js +3 -0
- package/dist-server/service/user/user-mutation.js.map +1 -1
- package/dist-server/service/user/user-query.d.ts +4 -3
- package/dist-server/service/user/user-query.js +35 -6
- package/dist-server/service/user/user-query.js.map +1 -1
- package/dist-server/service/user/user-types.d.ts +11 -0
- package/dist-server/service/user/user-types.js +43 -1
- package/dist-server/service/user/user-types.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/server/controllers/change-pwd.ts +1 -0
- package/server/service/privilege/privilege-directive.ts +12 -1
- package/server/service/user/user-mutation.ts +4 -0
- package/server/service/user/user-query.ts +34 -10
- package/server/service/user/user-types.ts +30 -0
- package/translations/en.json +1 -0
- package/translations/ja.json +1 -0
- package/translations/ko.json +1 -0
- package/translations/ms.json +1 -0
- package/translations/zh.json +1 -0
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@things-factory/auth-base",
|
3
|
-
"version": "7.0.
|
3
|
+
"version": "7.0.72",
|
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
|
"dependencies": {
|
33
33
|
"@simplewebauthn/browser": "^10.0.0",
|
34
34
|
"@simplewebauthn/server": "^10.0.0",
|
35
|
-
"@things-factory/email-base": "^7.0.
|
35
|
+
"@things-factory/email-base": "^7.0.72",
|
36
36
|
"@things-factory/env": "^7.0.70",
|
37
|
-
"@things-factory/shell": "^7.0.
|
37
|
+
"@things-factory/shell": "^7.0.72",
|
38
38
|
"@things-factory/utils": "^7.0.70",
|
39
39
|
"@types/webappsec-credential-management": "^0.6.8",
|
40
40
|
"jsonwebtoken": "^9.0.0",
|
@@ -46,5 +46,5 @@
|
|
46
46
|
"passport-jwt": "^4.0.0",
|
47
47
|
"passport-local": "^1.0.0"
|
48
48
|
},
|
49
|
-
"gitHead": "
|
49
|
+
"gitHead": "6131a0f20fcc11bc8e9e9d839de8e9700a2b0ac0"
|
50
50
|
}
|
@@ -2,7 +2,6 @@ import { defaultFieldResolver, GraphQLSchema } from 'graphql'
|
|
2
2
|
import gql from 'graphql-tag'
|
3
3
|
|
4
4
|
import { getDirective, MapperKind, mapSchema } from '@graphql-tools/utils'
|
5
|
-
import { User } from '../user/user'
|
6
5
|
import { checkPermission } from '../../utils/check-permission'
|
7
6
|
|
8
7
|
process['PRIVILEGES'] = {}
|
@@ -33,6 +32,18 @@ export const privilegeDirectiveResolver = (schema: GraphQLSchema) =>
|
|
33
32
|
process['PRIVILEGES'][`${category} ${privilege}`] = [category, privilege]
|
34
33
|
}
|
35
34
|
|
35
|
+
// 필드의 기존 description 가져오기
|
36
|
+
const existingDescription = fieldConfig.description || ''
|
37
|
+
|
38
|
+
// 권한 정보를 포함한 새로운 description 생성
|
39
|
+
const privilegeDescription =
|
40
|
+
`\n\n🔒 Requires privilege: ${category}:${privilege}` +
|
41
|
+
(domainOwnerGranted ? ', Domain ownership' : '') +
|
42
|
+
(superUserGranted ? ', System ownership' : '')
|
43
|
+
|
44
|
+
// 기존 description과 결합
|
45
|
+
fieldConfig.description = `${existingDescription} ${privilegeDescription}`.trim()
|
46
|
+
|
36
47
|
fieldConfig.resolve = async function (source, args, context, info) {
|
37
48
|
const { domain, user, unsafeIP, prohibitedPrivileges } = context.state
|
38
49
|
|
@@ -28,6 +28,10 @@ export class UserMutation {
|
|
28
28
|
throw new Error(context.t('error.x already exists in y', { x: context.t('field.user'), y: 'operato' }))
|
29
29
|
}
|
30
30
|
|
31
|
+
if (!user.password && !defaultPassword) {
|
32
|
+
throw new Error(context.t('error.initial password or default password should be supported'))
|
33
|
+
}
|
34
|
+
|
31
35
|
// consider if validation password rule is required
|
32
36
|
/* check if password is following the rule */
|
33
37
|
// User.validatePasswordByRule(user.password, context.lng)
|
@@ -3,19 +3,37 @@ import { GraphQLEmailAddress } from 'graphql-scalars'
|
|
3
3
|
import { ILike, SelectQueryBuilder } from 'typeorm'
|
4
4
|
|
5
5
|
import { config } from '@things-factory/env'
|
6
|
-
import {
|
6
|
+
import { getRepository, ListParam, getQueryBuilderFromListParams } from '@things-factory/shell'
|
7
7
|
|
8
8
|
import { checkUserBelongsDomain } from '../../utils/check-user-belongs-domain'
|
9
9
|
import { buildDomainUsersQueryBuilder } from '../../utils/get-domain-users'
|
10
|
-
import { Appliance } from '../appliance/appliance'
|
11
|
-
import { Application } from '../application/application'
|
12
10
|
import { User } from './user'
|
13
|
-
import { UserList } from './user-types'
|
11
|
+
import { PasswordRule, UserList } from './user-types'
|
12
|
+
|
13
|
+
const passwordRule = config.get('password') || {
|
14
|
+
lowerCase: true,
|
15
|
+
upperCase: true,
|
16
|
+
digit: true,
|
17
|
+
specialCharacter: true,
|
18
|
+
allowRepeat: false,
|
19
|
+
useTightPattern: true,
|
20
|
+
useLoosePattern: false,
|
21
|
+
tightCharacterLength: 8,
|
22
|
+
looseCharacterLength: 15
|
23
|
+
}
|
14
24
|
|
15
25
|
@Resolver(User)
|
16
26
|
export class UserQuery {
|
27
|
+
@Query(returns => PasswordRule, {
|
28
|
+
description:
|
29
|
+
'Retrieves the current password rule configuration for the system, such as required character types and minimum length.'
|
30
|
+
})
|
31
|
+
passwordRule(@Ctx() context: ResolverContext): PasswordRule {
|
32
|
+
return passwordRule
|
33
|
+
}
|
34
|
+
|
17
35
|
@Directive('@privilege(category: "user", privilege: "query", domainOwnerGranted: true, superUserGranted: true)')
|
18
|
-
@Query(returns => User, { description: '
|
36
|
+
@Query(returns => User, { description: 'Fetches a user by their email address within the current domain.' })
|
19
37
|
async user(@Arg('email', type => GraphQLEmailAddress) email: string, @Ctx() context: ResolverContext): Promise<User> {
|
20
38
|
const { domain } = context.state
|
21
39
|
|
@@ -26,7 +44,9 @@ export class UserQuery {
|
|
26
44
|
}
|
27
45
|
|
28
46
|
@Directive('@privilege(category: "user", privilege: "query", domainOwnerGranted: true, superUserGranted: true)')
|
29
|
-
@Query(returns => UserList, {
|
47
|
+
@Query(returns => UserList, {
|
48
|
+
description: 'Fetches a list of users based on provided search parameters within the current domain.'
|
49
|
+
})
|
30
50
|
async users(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<UserList> {
|
31
51
|
const { domain } = context.state
|
32
52
|
|
@@ -58,7 +78,7 @@ export class UserQuery {
|
|
58
78
|
return { items: foundUsers, total }
|
59
79
|
}
|
60
80
|
|
61
|
-
@Query(returns => Boolean, { description: '
|
81
|
+
@Query(returns => Boolean, { description: 'Checks if the current authenticated user belongs to the current domain.' })
|
62
82
|
async checkUserBelongsDomain(@Ctx() context: ResolverContext): Promise<Boolean> {
|
63
83
|
const { user, domain } = context.state
|
64
84
|
|
@@ -69,14 +89,18 @@ export class UserQuery {
|
|
69
89
|
}
|
70
90
|
}
|
71
91
|
|
72
|
-
@Query(returns => Boolean, {
|
92
|
+
@Query(returns => Boolean, {
|
93
|
+
description: 'Determines whether the system provides a default password when creating a new user.'
|
94
|
+
})
|
73
95
|
async checkResettablePasswordToDefault(@Ctx() context: ResolverContext): Promise<Boolean> {
|
74
96
|
const { defaultPassword } = config.get('password')
|
75
97
|
|
76
98
|
return Boolean(defaultPassword)
|
77
99
|
}
|
78
100
|
|
79
|
-
@Query(returns => Boolean, {
|
101
|
+
@Query(returns => Boolean, {
|
102
|
+
description: 'Checks if the system is configured to provide a default password for new users.'
|
103
|
+
})
|
80
104
|
async checkDefaultPassword(@Ctx() context: ResolverContext): Promise<Boolean> {
|
81
105
|
const { defaultPassword } = config.get('password')
|
82
106
|
|
@@ -84,7 +108,7 @@ export class UserQuery {
|
|
84
108
|
}
|
85
109
|
|
86
110
|
@Directive('@privilege(category: "user", privilege: "query")')
|
87
|
-
@Query(returns => Boolean, { description: '
|
111
|
+
@Query(returns => Boolean, { description: 'Checks if a user with the given email address exists in the system.' })
|
88
112
|
async checkUserExistence(@Arg('email', type => GraphQLEmailAddress) email: string): Promise<Boolean> {
|
89
113
|
return Boolean(await getRepository(User).count({ where: { email: ILike(email) } }))
|
90
114
|
}
|
@@ -3,6 +3,36 @@ import { GraphQLEmailAddress } from 'graphql-scalars'
|
|
3
3
|
import { ObjectRef } from '@things-factory/shell'
|
4
4
|
import { User } from './user'
|
5
5
|
|
6
|
+
@ObjectType()
|
7
|
+
export class PasswordRule {
|
8
|
+
@Field({ nullable: true })
|
9
|
+
lowerCase?: boolean
|
10
|
+
|
11
|
+
@Field({ nullable: true })
|
12
|
+
upperCase?: boolean
|
13
|
+
|
14
|
+
@Field({ nullable: true })
|
15
|
+
digit?: boolean
|
16
|
+
|
17
|
+
@Field({ nullable: true })
|
18
|
+
specialCharacter?: boolean
|
19
|
+
|
20
|
+
@Field({ nullable: true })
|
21
|
+
allowRepeat?: boolean
|
22
|
+
|
23
|
+
@Field({ nullable: true })
|
24
|
+
useTightPattern?: boolean
|
25
|
+
|
26
|
+
@Field({ nullable: true })
|
27
|
+
useLoosePattern?: boolean
|
28
|
+
|
29
|
+
@Field({ nullable: true })
|
30
|
+
tightCharacterLength?: number
|
31
|
+
|
32
|
+
@Field({ nullable: true })
|
33
|
+
looseCharacterLength?: number
|
34
|
+
}
|
35
|
+
|
6
36
|
@InputType()
|
7
37
|
export class NewUser {
|
8
38
|
@Field()
|
package/translations/en.json
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
"error.domain mismatch": "certificate is not for this domain",
|
6
6
|
"error.domain not allowed": "user not allowed domain `{subdomain}`",
|
7
7
|
"error.failed to find x": "failed to find {x}",
|
8
|
+
"error.password should be supported": "initial password or default password should be supported",
|
8
9
|
"error.password should match the rule": "password should match following rule. ${rule}",
|
9
10
|
"error.password used in the past": "password used in the past",
|
10
11
|
"error.subdomain not found": "domain not found",
|
package/translations/ja.json
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
"error.domain mismatch": "証明書のドメインと現在のドメインが一致しません.",
|
6
6
|
"error.domain not allowed": "'{subdomain}' 領域はこのユーザに許可されていません.",
|
7
7
|
"error.failed to find x": "{x}が見つかりません.",
|
8
|
+
"error.password should be supported": "初期パスワードまたはデフォルトパスワードがサポートされるべきです",
|
8
9
|
"error.password should match the rule": "パスワードは次の規則を守らなければなりません. {rule}",
|
9
10
|
"error.password used in the past": "過去に使用されたパスワードです.",
|
10
11
|
"error.subdomain not found": "サブドメインが見つかりません.",
|
package/translations/ko.json
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
"error.domain mismatch": "인증서의 도메인과 현재 도메인이 일치하지 않습니다.",
|
6
6
|
"error.domain not allowed": "'{subdomain}' 영역은 이 사용자에게 허가되지 않았습니다.",
|
7
7
|
"error.failed to find x": "{x}을(를) 찾을 수 없습니다.",
|
8
|
+
"error.password should be supported": "초기 비밀번호나 디폴트 비밀번호가 제공되어야 합니다.",
|
8
9
|
"error.password should match the rule": "비밀번호는 다음 규칙을 지켜야 합니다. {rule}",
|
9
10
|
"error.password used in the past": "과거에 사용된 비밀번호입니다.",
|
10
11
|
"error.subdomain not found": "서브도메인을 찾을 수 없습니다.",
|
package/translations/ms.json
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
"error.domain mismatch": "Sijil tidak sesuai untuk domain ini",
|
6
6
|
"error.domain not allowed": "Pengguna tidak dibenarkan domain `{subdomain}`",
|
7
7
|
"error.failed to find x": "Gagal mencari {x}",
|
8
|
+
"error.password should be supported": "kata laluan awal atau kata laluan lalai harus disokong",
|
8
9
|
"error.password should match the rule": "Kata laluan harus mematuhi peraturan berikut. ${rule}",
|
9
10
|
"error.password used in the past": "Kata laluan telah digunakan dalam masa lampau",
|
10
11
|
"error.subdomain not found": "Domain tidak ditemui",
|
package/translations/zh.json
CHANGED
@@ -6,6 +6,7 @@
|
|
6
6
|
"error.domain mismatch": "证书不适用于该域!",
|
7
7
|
"error.domain not allowed": "用户无权限使用`{subdomain}`域!",
|
8
8
|
"error.failed to find x": "查询{x}失败!",
|
9
|
+
"error.password should be supported": "应支持初始密码或默认密码",
|
9
10
|
"error.password should match the rule": "密码应符合以下规则。${rule}",
|
10
11
|
"error.password used in the past": "使用过的密码!",
|
11
12
|
"error.subdomain not found": "用户域查询失败!",
|