@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/auth-base",
3
- "version": "7.0.70",
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.70",
35
+ "@things-factory/email-base": "^7.0.72",
36
36
  "@things-factory/env": "^7.0.70",
37
- "@things-factory/shell": "^7.0.70",
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": "f046cfbb15447499fc5be9a9d82e2deb296b5f36"
49
+ "gitHead": "6131a0f20fcc11bc8e9e9d839de8e9700a2b0ac0"
50
50
  }
@@ -42,6 +42,7 @@ export async function changePwd(attrs, currentPass, newPass, confirmPass, contex
42
42
  }
43
43
  })
44
44
  }
45
+
45
46
  /* check if password is following the rule */
46
47
  User.validatePasswordByRule(newPass, context?.lng)
47
48
 
@@ -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 { Domain, getRepository, ListParam, getQueryBuilderFromListParams } from '@things-factory/shell'
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: 'To fetch user' })
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, { description: 'To fetch multiple users' })
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: 'To check if current user is belongs to current domain' })
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, { description: 'To check if system would provide default password to create new user' })
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, { description: 'To check if system would provide default password to create new user' })
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()
@@ -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",
@@ -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": "サブドメインが見つかりません.",
@@ -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": "서브도메인을 찾을 수 없습니다.",
@@ -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",
@@ -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": "用户域查询失败!",