@things-factory/auth-base 8.0.0-alpha.28 → 8.0.0-alpha.35
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-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/constants/error-code.d.ts +2 -0
- package/dist-server/constants/error-code.js +3 -1
- package/dist-server/constants/error-code.js.map +1 -1
- package/dist-server/controllers/change-pwd.js +2 -2
- package/dist-server/controllers/change-pwd.js.map +1 -1
- package/dist-server/controllers/delete-user.js +13 -12
- package/dist-server/controllers/delete-user.js.map +1 -1
- package/dist-server/controllers/invitation.d.ts +2 -1
- package/dist-server/controllers/invitation.js +30 -5
- package/dist-server/controllers/invitation.js.map +1 -1
- package/dist-server/controllers/profile.d.ts +4 -3
- package/dist-server/controllers/profile.js +20 -2
- package/dist-server/controllers/profile.js.map +1 -1
- package/dist-server/controllers/signin.d.ts +4 -1
- package/dist-server/controllers/signin.js +17 -1
- package/dist-server/controllers/signin.js.map +1 -1
- package/dist-server/controllers/signup.js +13 -4
- package/dist-server/controllers/signup.js.map +1 -1
- package/dist-server/controllers/unlock-user.js +1 -0
- package/dist-server/controllers/unlock-user.js.map +1 -1
- package/dist-server/controllers/verification.js +1 -0
- package/dist-server/controllers/verification.js.map +1 -1
- package/dist-server/middlewares/signin-middleware.js +3 -3
- package/dist-server/middlewares/signin-middleware.js.map +1 -1
- package/dist-server/migrations/1548206416130-SeedUser.js +2 -1
- package/dist-server/migrations/1548206416130-SeedUser.js.map +1 -1
- package/dist-server/router/auth-checkin-router.js +8 -2
- package/dist-server/router/auth-checkin-router.js.map +1 -1
- package/dist-server/router/auth-private-process-router.js +12 -7
- package/dist-server/router/auth-private-process-router.js.map +1 -1
- package/dist-server/router/auth-public-process-router.js +14 -5
- package/dist-server/router/auth-public-process-router.js.map +1 -1
- package/dist-server/router/auth-signin-router.js +3 -3
- package/dist-server/router/auth-signin-router.js.map +1 -1
- package/dist-server/service/invitation/invitation-mutation.d.ts +3 -2
- package/dist-server/service/invitation/invitation-mutation.js +20 -8
- package/dist-server/service/invitation/invitation-mutation.js.map +1 -1
- package/dist-server/service/user/user-mutation.d.ts +3 -2
- package/dist-server/service/user/user-mutation.js +62 -37
- package/dist-server/service/user/user-mutation.js.map +1 -1
- package/dist-server/service/user/user-types.d.ts +1 -0
- package/dist-server/service/user/user-types.js +4 -0
- package/dist-server/service/user/user-types.js.map +1 -1
- package/dist-server/service/user/user.d.ts +1 -0
- package/dist-server/service/user/user.js +40 -14
- package/dist-server/service/user/user.js.map +1 -1
- package/dist-server/templates/account-unlock-email.d.ts +2 -1
- package/dist-server/templates/account-unlock-email.js +1 -1
- package/dist-server/templates/account-unlock-email.js.map +1 -1
- package/dist-server/templates/invitation-email.d.ts +2 -1
- package/dist-server/templates/invitation-email.js +1 -1
- package/dist-server/templates/invitation-email.js.map +1 -1
- package/dist-server/templates/verification-email.d.ts +2 -1
- package/dist-server/templates/verification-email.js +1 -1
- package/dist-server/templates/verification-email.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/server/constants/error-code.ts +2 -0
- package/server/controllers/change-pwd.ts +3 -2
- package/server/controllers/delete-user.ts +16 -13
- package/server/controllers/invitation.ts +36 -5
- package/server/controllers/profile.ts +29 -2
- package/server/controllers/signin.ts +21 -2
- package/server/controllers/signup.ts +16 -4
- package/server/controllers/unlock-user.ts +1 -0
- package/server/controllers/verification.ts +1 -0
- package/server/middlewares/signin-middleware.ts +3 -3
- package/server/migrations/1548206416130-SeedUser.ts +2 -1
- package/server/router/auth-checkin-router.ts +11 -5
- package/server/router/auth-private-process-router.ts +14 -7
- package/server/router/auth-public-process-router.ts +16 -5
- package/server/router/auth-signin-router.ts +3 -3
- package/server/service/invitation/invitation-mutation.ts +24 -9
- package/server/service/user/user-mutation.ts +68 -36
- package/server/service/user/user-types.ts +3 -0
- package/server/service/user/user.ts +41 -14
- package/server/templates/account-unlock-email.ts +1 -1
- package/server/templates/invitation-email.ts +1 -1
- package/server/templates/verification-email.ts +1 -1
- package/translations/en.json +4 -1
- package/translations/ja.json +4 -1
- package/translations/ko.json +5 -3
- package/translations/ms.json +4 -1
- package/translations/zh.json +4 -1
@@ -1,6 +1,6 @@
|
|
1
1
|
import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'
|
2
2
|
import { GraphQLEmailAddress } from 'graphql-scalars'
|
3
|
-
import { ILike, In, SelectQueryBuilder } from 'typeorm'
|
3
|
+
import { ILike, In, SelectQueryBuilder, EntityManager } from 'typeorm'
|
4
4
|
|
5
5
|
import { config } from '@things-factory/env'
|
6
6
|
import { Domain, getRepository, ObjectRef } from '@things-factory/shell'
|
@@ -10,6 +10,7 @@ import { buildDomainUsersQueryBuilder } from '../../utils/get-domain-users'
|
|
10
10
|
import { Role } from '../role/role'
|
11
11
|
import { User, UserStatus } from './user'
|
12
12
|
import { NewUser, UserPatch } from './user-types'
|
13
|
+
import { USERNAME_ALREADY_EXISTS, EMAIL_ALREADY_EXISTS } from '../../constants/error-code'
|
13
14
|
|
14
15
|
@Resolver(User)
|
15
16
|
export class UserMutation {
|
@@ -17,19 +18,29 @@ export class UserMutation {
|
|
17
18
|
@Directive('@transaction')
|
18
19
|
@Mutation(returns => User, { description: 'To create new user' })
|
19
20
|
async createUser(@Arg('user') user: NewUser, @Ctx() context: ResolverContext) {
|
20
|
-
const { domain } = context.state
|
21
|
+
const { domain, tx } = context.state
|
21
22
|
const { defaultPassword } = config.get('password')
|
22
|
-
const { email } = user
|
23
|
+
const { username, email } = user
|
24
|
+
const userRepository = getRepository(User, tx)
|
23
25
|
|
26
|
+
user.username = username.trim()
|
24
27
|
user.email = email.trim()
|
25
28
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
+
if (await userRepository.findOne({ where: { username: user.username } })) {
|
30
|
+
throw new Error(context.t(USERNAME_ALREADY_EXISTS))
|
31
|
+
}
|
32
|
+
|
33
|
+
if (await userRepository.findOne({ where: { email: ILike(user.email) } })) {
|
34
|
+
throw new Error(context.t(EMAIL_ALREADY_EXISTS))
|
29
35
|
}
|
30
36
|
|
31
37
|
if (!user.password && !defaultPassword) {
|
32
|
-
throw new Error(
|
38
|
+
throw new Error('initial password or default password should be supported.')
|
39
|
+
}
|
40
|
+
|
41
|
+
// TODO username은 다음 패턴을 따라야 한다. pattern="^[A-Za-z0-9]*$"
|
42
|
+
if (!/^[A-Za-z0-9]*$/.test(user.username)) {
|
43
|
+
throw new Error(context.t('error.invalid x', { x: context.t('field.username') }))
|
33
44
|
}
|
34
45
|
|
35
46
|
// consider if validation password rule is required
|
@@ -38,14 +49,14 @@ export class UserMutation {
|
|
38
49
|
|
39
50
|
const salt = User.generateSalt()
|
40
51
|
|
41
|
-
return await
|
52
|
+
return await userRepository.save({
|
42
53
|
creator: context.state.user,
|
43
54
|
updater: context.state.user,
|
44
55
|
...user,
|
45
56
|
domains: [domain],
|
46
57
|
roles:
|
47
58
|
user.roles && user.roles.length
|
48
|
-
? await getRepository(Role).findBy({
|
59
|
+
? await getRepository(Role, tx).findBy({
|
49
60
|
id: In(user.roles.map(role => role.id)),
|
50
61
|
domain: { id: domain.id }
|
51
62
|
})
|
@@ -64,7 +75,7 @@ export class UserMutation {
|
|
64
75
|
@Arg('patch') patch: UserPatch,
|
65
76
|
@Ctx() context: ResolverContext
|
66
77
|
) {
|
67
|
-
const { domain, user: updater }: { domain: Domain; user: User } = context.state
|
78
|
+
const { domain, user: updater, tx }: { domain: Domain; user: User; tx?: EntityManager } = context.state
|
68
79
|
const qb: SelectQueryBuilder<User> = buildDomainUsersQueryBuilder(domain.id, 'USER')
|
69
80
|
const user: User = await qb
|
70
81
|
.andWhere('LOWER(USER.email) = :email', { email: email?.toLowerCase().trim() || '' })
|
@@ -73,14 +84,16 @@ export class UserMutation {
|
|
73
84
|
.getOne()
|
74
85
|
|
75
86
|
if (patch.roles) {
|
76
|
-
patch.roles = await getRepository(Role).find({
|
87
|
+
patch.roles = await getRepository(Role, tx).find({
|
88
|
+
where: { id: In(patch.roles.map((r: Partial<Role>) => r.id)) }
|
89
|
+
})
|
77
90
|
}
|
78
91
|
|
79
92
|
if (patch.status && patch.status === 'activated') {
|
80
93
|
user.status = UserStatus.ACTIVATED
|
81
94
|
}
|
82
95
|
|
83
|
-
return await getRepository(User).save({
|
96
|
+
return await getRepository(User, tx).save({
|
84
97
|
...user,
|
85
98
|
...patch,
|
86
99
|
updater
|
@@ -92,7 +105,7 @@ export class UserMutation {
|
|
92
105
|
@Mutation(returns => [User], { description: 'To modify multiple users information' })
|
93
106
|
async updateMultipleUser(@Arg('patches', type => [UserPatch]) patches: UserPatch[], @Ctx() context: ResolverContext) {
|
94
107
|
const { domain, user, tx } = context.state
|
95
|
-
const userRepo =
|
108
|
+
const userRepo = getRepository(User, tx)
|
96
109
|
|
97
110
|
let results = []
|
98
111
|
const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')
|
@@ -183,10 +196,10 @@ export class UserMutation {
|
|
183
196
|
@Directive('@privilege(category: "user", privilege: "mutation", domainOwnerGranted: true)')
|
184
197
|
@Directive('@transaction')
|
185
198
|
@Mutation(returns => Boolean, { description: 'To delete a user' })
|
186
|
-
async deleteUser(@Arg('
|
199
|
+
async deleteUser(@Arg('username') username: string, @Ctx() context: ResolverContext) {
|
187
200
|
const { tx } = context.state
|
188
201
|
|
189
|
-
await commonDeleteUser({
|
202
|
+
await commonDeleteUser({ username }, tx)
|
190
203
|
|
191
204
|
return true
|
192
205
|
}
|
@@ -194,9 +207,9 @@ export class UserMutation {
|
|
194
207
|
@Directive('@privilege(category: "user", privilege: "mutation", domainOwnerGranted: true)')
|
195
208
|
@Directive('@transaction')
|
196
209
|
@Mutation(returns => Boolean, { description: 'To delete some users' })
|
197
|
-
async deleteUsers(@Arg('
|
210
|
+
async deleteUsers(@Arg('usernames', type => [String]) usernames: string[], @Ctx() context: ResolverContext) {
|
198
211
|
const { tx } = context.state
|
199
|
-
await commonDeleteUsers({
|
212
|
+
await commonDeleteUsers({ usernames }, tx)
|
200
213
|
|
201
214
|
return true
|
202
215
|
}
|
@@ -207,8 +220,8 @@ export class UserMutation {
|
|
207
220
|
@Arg('email', type => GraphQLEmailAddress) email: string,
|
208
221
|
@Ctx() context: ResolverContext
|
209
222
|
): Promise<boolean> {
|
210
|
-
const { domain } = context.state
|
211
|
-
const invitee: User = await getRepository(User).findOne({
|
223
|
+
const { domain, tx } = context.state
|
224
|
+
const invitee: User = await getRepository(User, tx).findOne({
|
212
225
|
where: { email: ILike(email) },
|
213
226
|
relations: ['domains']
|
214
227
|
})
|
@@ -222,7 +235,7 @@ export class UserMutation {
|
|
222
235
|
throw new Error(context.t('error.x already exists in y', { x: context.t('field.user'), y: domain.name }))
|
223
236
|
}
|
224
237
|
invitee.domains = [...existingDomains, domain]
|
225
|
-
await getRepository(User).save(invitee)
|
238
|
+
await getRepository(User, tx).save(invitee)
|
226
239
|
|
227
240
|
return true
|
228
241
|
}
|
@@ -236,9 +249,10 @@ export class UserMutation {
|
|
236
249
|
): Promise<boolean> {
|
237
250
|
const { tx, domain } = context.state
|
238
251
|
|
239
|
-
let user: User = await tx
|
240
|
-
|
241
|
-
|
252
|
+
let user: User = await getRepository(User, tx).findOne({
|
253
|
+
where: { email: ILike(email) },
|
254
|
+
relations: ['domains', 'roles', 'roles.domain']
|
255
|
+
})
|
242
256
|
if (!user) {
|
243
257
|
throw new Error(context.t('error.failed to find x', { x: context.t('field.user') }))
|
244
258
|
}
|
@@ -254,7 +268,7 @@ export class UserMutation {
|
|
254
268
|
// Remove domain's roles that user has
|
255
269
|
user.roles = user.roles.filter((role: Role) => role.domain.id !== domain.id)
|
256
270
|
|
257
|
-
await
|
271
|
+
await getRepository(User, tx).save(user)
|
258
272
|
|
259
273
|
return true
|
260
274
|
}
|
@@ -266,12 +280,30 @@ export class UserMutation {
|
|
266
280
|
@Arg('email', type => GraphQLEmailAddress) email: string,
|
267
281
|
@Ctx() context: ResolverContext
|
268
282
|
): Promise<boolean> {
|
269
|
-
const { domain } = context.state
|
270
|
-
const user: User = await getRepository(User).findOne({
|
271
|
-
where: { email: ILike(email) }
|
283
|
+
const { domain, tx } = context.state
|
284
|
+
const user: User = await getRepository(User, tx).findOne({
|
285
|
+
where: { email: ILike(email) },
|
286
|
+
relations: ['domains', 'roles']
|
272
287
|
})
|
288
|
+
|
289
|
+
if (!user) {
|
290
|
+
throw new Error('Failed to find user')
|
291
|
+
}
|
292
|
+
|
293
|
+
if (user.status !== UserStatus.ACTIVATED) {
|
294
|
+
throw new Error('Only activated users are eligible to receive admin privileges.')
|
295
|
+
}
|
296
|
+
|
297
|
+
if (user.domains.map((d: Domain) => d.id).indexOf(domain.id) < 0) {
|
298
|
+
throw new Error(`User is not belongs to current domain`)
|
299
|
+
}
|
300
|
+
|
301
|
+
if (user.roles.filter((r: Role) => r.domainId == domain.id).length == 0) {
|
302
|
+
throw new Error(`Only users with at least one role in this domain are eligible to receive admin privileges.`)
|
303
|
+
}
|
304
|
+
|
273
305
|
domain.owner = user.id
|
274
|
-
await getRepository(Domain).save(domain)
|
306
|
+
await getRepository(Domain, tx).save(domain)
|
275
307
|
|
276
308
|
return true
|
277
309
|
}
|
@@ -282,7 +314,7 @@ export class UserMutation {
|
|
282
314
|
async activateUser(@Arg('userId') userId: string, @Ctx() context: ResolverContext): Promise<boolean> {
|
283
315
|
const { tx, domain } = context.state
|
284
316
|
|
285
|
-
const targetUser: User = await
|
317
|
+
const targetUser: User = await getRepository(User, tx).findOne({
|
286
318
|
where: { id: userId },
|
287
319
|
relations: ['domains']
|
288
320
|
})
|
@@ -297,7 +329,7 @@ export class UserMutation {
|
|
297
329
|
targetUser.failCount = 0
|
298
330
|
targetUser.status = UserStatus.ACTIVATED
|
299
331
|
|
300
|
-
await
|
332
|
+
await getRepository(User, tx).save(targetUser)
|
301
333
|
|
302
334
|
return true
|
303
335
|
}
|
@@ -308,7 +340,7 @@ export class UserMutation {
|
|
308
340
|
async inactivateUser(@Arg('userId') userId: string, @Ctx() context: ResolverContext): Promise<boolean> {
|
309
341
|
const { tx, domain } = context.state
|
310
342
|
|
311
|
-
const targetUser: User = await
|
343
|
+
const targetUser: User = await getRepository(User, tx).findOne({
|
312
344
|
where: { id: userId },
|
313
345
|
relations: ['domains']
|
314
346
|
})
|
@@ -326,7 +358,7 @@ export class UserMutation {
|
|
326
358
|
|
327
359
|
targetUser.status = UserStatus.INACTIVE
|
328
360
|
|
329
|
-
await
|
361
|
+
await getRepository(User, tx).save(targetUser)
|
330
362
|
|
331
363
|
return true
|
332
364
|
}
|
@@ -342,7 +374,7 @@ export class UserMutation {
|
|
342
374
|
throw new Error('No default password found')
|
343
375
|
}
|
344
376
|
|
345
|
-
const targetUser: User = await
|
377
|
+
const targetUser: User = await getRepository(User, tx).findOne({
|
346
378
|
where: { id: userId },
|
347
379
|
relations: ['domains']
|
348
380
|
})
|
@@ -356,7 +388,7 @@ export class UserMutation {
|
|
356
388
|
|
357
389
|
targetUser.salt = User.generateSalt()
|
358
390
|
targetUser.password = User.encode(defaultPassword, targetUser.salt)
|
359
|
-
await
|
391
|
+
await getRepository(User, tx).save(targetUser)
|
360
392
|
|
361
393
|
return true
|
362
394
|
}
|
@@ -371,7 +403,7 @@ export class UserMutation {
|
|
371
403
|
@Ctx() context: ResolverContext
|
372
404
|
) {
|
373
405
|
const { domain, tx } = context.state
|
374
|
-
let user: User = await
|
406
|
+
let user: User = await getRepository(User, tx).findOne({
|
375
407
|
where: { id: userId },
|
376
408
|
relations: ['domains', 'roles']
|
377
409
|
})
|
@@ -387,6 +419,6 @@ export class UserMutation {
|
|
387
419
|
user.roles = user.roles.filter((r: Role) => availableRoleIds.indexOf(r.id) < 0)
|
388
420
|
user.roles = user.roles.concat(selectedRoles as Role[])
|
389
421
|
|
390
|
-
return await
|
422
|
+
return await getRepository(User, tx).save(user)
|
391
423
|
}
|
392
424
|
}
|
@@ -6,6 +6,7 @@ import {
|
|
6
6
|
Column,
|
7
7
|
CreateDateColumn,
|
8
8
|
Entity,
|
9
|
+
ILike,
|
9
10
|
Index,
|
10
11
|
JoinTable,
|
11
12
|
ManyToMany,
|
@@ -43,13 +44,23 @@ export enum UserStatus {
|
|
43
44
|
}
|
44
45
|
|
45
46
|
@Entity()
|
46
|
-
@Index('ix_user_0', (user: User) => [user.email], {
|
47
|
+
@Index('ix_user_0', (user: User) => [user.email], {
|
48
|
+
unique: true
|
49
|
+
})
|
50
|
+
@Index('ix_user_1', (user: User) => [user.username], {
|
51
|
+
unique: true,
|
52
|
+
where: '"username" IS NOT NULL'
|
53
|
+
})
|
47
54
|
@ObjectType()
|
48
55
|
export class User {
|
49
56
|
@PrimaryGeneratedColumn('uuid')
|
50
57
|
@Field(type => ID)
|
51
58
|
readonly id: string
|
52
59
|
|
60
|
+
@Column({ nullable: true })
|
61
|
+
@Field({ nullable: true })
|
62
|
+
username: string
|
63
|
+
|
53
64
|
@Column()
|
54
65
|
@Field({ nullable: true })
|
55
66
|
name: string
|
@@ -165,15 +176,10 @@ export class User {
|
|
165
176
|
|
166
177
|
/* signing for jsonwebtoken */
|
167
178
|
async sign(options?) {
|
168
|
-
var { expiresIn = sessionExpirySeconds
|
179
|
+
var { expiresIn = sessionExpirySeconds } = options || {}
|
169
180
|
|
170
181
|
var user = {
|
171
|
-
|
172
|
-
userType: this.userType,
|
173
|
-
status: this.status,
|
174
|
-
domain: {
|
175
|
-
subdomain
|
176
|
-
}
|
182
|
+
username: this.username || this.email
|
177
183
|
}
|
178
184
|
|
179
185
|
return await jwt.sign(user, SECRET, {
|
@@ -262,18 +268,39 @@ export class User {
|
|
262
268
|
}
|
263
269
|
|
264
270
|
static async checkAuth(decoded) {
|
265
|
-
|
271
|
+
// id 는 하위호환성을 위해 단기적으로 유지함
|
272
|
+
const { id, username } = decoded || {}
|
273
|
+
|
274
|
+
if (!id && !username) {
|
266
275
|
throw new AuthError({
|
267
276
|
errorCode: AuthError.ERROR_CODES.USER_NOT_FOUND
|
268
277
|
})
|
269
278
|
}
|
270
279
|
|
271
280
|
const repository = getRepository(User)
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
281
|
+
if (id) {
|
282
|
+
var user = await repository.findOne({
|
283
|
+
where: { id },
|
284
|
+
relations: ['domains', 'credentials'],
|
285
|
+
cache: true
|
286
|
+
})
|
287
|
+
} else {
|
288
|
+
var user = await repository.findOne({
|
289
|
+
where: { username },
|
290
|
+
relations: ['domains', 'credentials'],
|
291
|
+
cache: true
|
292
|
+
})
|
293
|
+
|
294
|
+
if (!user && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(username)) {
|
295
|
+
user = await repository.findOne({
|
296
|
+
where: {
|
297
|
+
email: ILike(username)
|
298
|
+
},
|
299
|
+
relations: ['domains', 'credentials'],
|
300
|
+
cache: true
|
301
|
+
})
|
302
|
+
}
|
303
|
+
}
|
277
304
|
|
278
305
|
if (!user)
|
279
306
|
throw new AuthError({
|
package/translations/en.json
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
"error.confirm password not matched": "new password and confirm password is not matched",
|
5
5
|
"error.domain mismatch": "certificate is not for this domain",
|
6
6
|
"error.domain not allowed": "user not allowed domain `{subdomain}`",
|
7
|
+
"error.email already exists": "email already used by another user",
|
7
8
|
"error.failed to find x": "failed to find {x}",
|
8
9
|
"error.password should be supported": "initial password or default password should be supported",
|
9
10
|
"error.password should match the rule": "password should match following rule. ${rule}",
|
@@ -11,13 +12,15 @@
|
|
11
12
|
"error.subdomain not found": "domain not found",
|
12
13
|
"error.token or password is invalid": "token or password is invalid",
|
13
14
|
"error.unavailable-domain": "unavailable domain",
|
15
|
+
"error.user credential not found": "user credential not found. You need to register device to use biometric authentication.",
|
14
16
|
"error.user credential registeration failed": "user credential registration failed. It may be an already registered credential.",
|
15
17
|
"error.user credential registration not allowed": "user credential registration failed. The registration timed out or was not allowed.",
|
16
|
-
"error.user duplicated": "user
|
18
|
+
"error.user duplicated.": "there is a user account using same email or user ID.",
|
17
19
|
"error.user not activated": "user is not activated",
|
18
20
|
"error.user not found": "user not found",
|
19
21
|
"error.user or verification token not found": "user or verification token not found",
|
20
22
|
"error.user validation failed": "user validation failed",
|
23
|
+
"error.username already exists": "username already used by another user",
|
21
24
|
"error.x is not a member of y": "{x} is not a member of {y}",
|
22
25
|
"field.active": "active",
|
23
26
|
"field.appliance_id": "appliance id",
|
package/translations/ja.json
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
"error.confirm password not matched": "新しいパスワードと確認パスワードが一致しません.",
|
5
5
|
"error.domain mismatch": "証明書のドメインと現在のドメインが一致しません.",
|
6
6
|
"error.domain not allowed": "'{subdomain}' 領域はこのユーザに許可されていません.",
|
7
|
+
"error.email already exists": "メールはすでに他のユーザーによって使用されています.",
|
7
8
|
"error.failed to find x": "{x}が見つかりません.",
|
8
9
|
"error.password should be supported": "初期パスワードまたはデフォルトパスワードがサポートされるべきです",
|
9
10
|
"error.password should match the rule": "パスワードは次の規則を守らなければなりません. {rule}",
|
@@ -11,13 +12,15 @@
|
|
11
12
|
"error.subdomain not found": "サブドメインが見つかりません.",
|
12
13
|
"error.token or password is invalid": "トークンまたはパスワードが無効です.",
|
13
14
|
"error.unavailable-domain": "使用できないドメインです.",
|
15
|
+
"error.user credential not found": "ユーザー資格情報が見つかりません. 生体認証を使用するにはデバイスを登録する必要があります.",
|
14
16
|
"error.user credential registeration failed": "ユーザー資格情報の登録に失敗しました。既に登録されている資格情報の可能性があります。",
|
15
17
|
"error.user credential registration not allowed": "ユーザー資格情報の登録に失敗しました。登録のタイムアウトまたは登録が許可されていません。",
|
16
|
-
"error.user duplicated": "
|
18
|
+
"error.user duplicated.": "ユーザーが重複しています.",
|
17
19
|
"error.user not activated": "ユーザーがアクティブ化されていません.",
|
18
20
|
"error.user not found": "ユーザーが存在しません.",
|
19
21
|
"error.user or verification token not found": "ユーザーまたは確認トークンが見つかりません.",
|
20
22
|
"error.user validation failed": "ユーザー確認に失敗しました.",
|
23
|
+
"error.username already exists": "ユーザー名はすでに他のユーザーによって使用されています.",
|
21
24
|
"error.x is not a member of y": "{x}は{y}のメンバーではありません.",
|
22
25
|
"field.active": "アクティブ",
|
23
26
|
"field.appliance_id": "器具ID",
|
package/translations/ko.json
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
"error.confirm password not matched": "새 비밀번호와 확인 비밀번호가 일치하지 않습니다.",
|
5
5
|
"error.domain mismatch": "인증서의 도메인과 현재 도메인이 일치하지 않습니다.",
|
6
6
|
"error.domain not allowed": "'{subdomain}' 영역은 이 사용자에게 허가되지 않았습니다.",
|
7
|
+
"error.email already exists": "이메일이 이미 사용되고 있습니다.",
|
7
8
|
"error.failed to find x": "{x}을(를) 찾을 수 없습니다.",
|
8
9
|
"error.password should be supported": "초기 비밀번호나 디폴트 비밀번호가 제공되어야 합니다.",
|
9
10
|
"error.password should match the rule": "비밀번호는 다음 규칙을 지켜야 합니다. {rule}",
|
@@ -12,13 +13,14 @@
|
|
12
13
|
"error.token or password is invalid": "토큰 또는 비밀번호가 유효하지 않습니다.",
|
13
14
|
"error.unavailable-domain": "사용할 수 없는 도메인입니다.",
|
14
15
|
"error.user credential not found": "사용자 자격 증명을 찾을 수 없습니다. 바이오메트릭 인증을 사용하기 위해서는 먼저 기기를 등록해야 합니다.",
|
15
|
-
"error.user
|
16
|
+
"error.user credential registeration failed": "사용자 인증서 등록이 실패하였습니다. 이미 등록된 인증서일 수 있습니다.",
|
17
|
+
"error.user credential registration not allowed": "사용자 인증서 등록이 실패하였습니다. 등록 시간이 초과되었거나 등록이 허용되지 않았습니다.",
|
18
|
+
"error.user duplicated": "동일한 이메일이나 사용자아이디로 가입된 계정이 이미 존재합니다.",
|
16
19
|
"error.user not activated": "사용자가 활성화되지 않았습니다.",
|
17
20
|
"error.user not found": "사용자가 존재하지 않습니다.",
|
18
21
|
"error.user or verification token not found": "사용자 또는 확인토큰을 찾을 수 없습니다.",
|
19
|
-
"error.user credential registeration failed": "사용자 인증서 등록이 실패하였습니다. 이미 등록된 인증서일 수 있습니다.",
|
20
|
-
"error.user credential registration not allowed": "사용자 인증서 등록이 실패하였습니다. 등록 시간이 초과되었거나 등록이 허용되지 않았습니다.",
|
21
22
|
"error.user validation failed": "사용자 확인에 실패하였습니다.",
|
23
|
+
"error.username already exists": "사용자 아이디가 이미 사용되고 있습니다.",
|
22
24
|
"error.x is not a member of y": "{x}은(는) {y}의 멤버가 아닙니다.",
|
23
25
|
"field.active": "활성화",
|
24
26
|
"field.appliance_id": "기구 아이디",
|
package/translations/ms.json
CHANGED
@@ -4,6 +4,7 @@
|
|
4
4
|
"error.confirm password not matched": "Kata laluan baru dan pengesahan kata laluan tidak sepadan",
|
5
5
|
"error.domain mismatch": "Sijil tidak sesuai untuk domain ini",
|
6
6
|
"error.domain not allowed": "Pengguna tidak dibenarkan domain `{subdomain}`",
|
7
|
+
"error.email already exists": "Emel telah digunakan oleh pengguna lain",
|
7
8
|
"error.failed to find x": "Gagal mencari {x}",
|
8
9
|
"error.password should be supported": "kata laluan awal atau kata laluan lalai harus disokong",
|
9
10
|
"error.password should match the rule": "Kata laluan harus mematuhi peraturan berikut. ${rule}",
|
@@ -11,13 +12,15 @@
|
|
11
12
|
"error.subdomain not found": "Domain tidak ditemui",
|
12
13
|
"error.token or password is invalid": "Token atau kata laluan tidak sah",
|
13
14
|
"error.unavailable-domain": "Domain tidak tersedia",
|
15
|
+
"error.user credential not found": "kelayakan pengguna tidak ditemui. Anda perlu mendaftarkan peranti untuk menggunakan pengesahan biometrik.",
|
14
16
|
"error.user credential registeration failed": "pendaftaran kelayakan pengguna gagal. Mungkin kelayakan tersebut sudah didaftarkan.",
|
15
17
|
"error.user credential registration not allowed": "pendaftaran kelayakan pengguna gagal. Masa pendaftaran telah tamat atau pendaftaran tidak dibenarkan.",
|
16
|
-
"error.user duplicated": "
|
18
|
+
"error.user duplicated": "terdapat akaun pengguna yang menggunakan e-mel atau ID pengguna yang sama.",
|
17
19
|
"error.user not activated": "Pengguna tidak diaktifkan",
|
18
20
|
"error.user not found": "Pengguna tidak ditemui",
|
19
21
|
"error.user or verification token not found": "Pengguna atau token pengesahan tidak ditemui",
|
20
22
|
"error.user validation failed": "Validasi pengguna gagal",
|
23
|
+
"error.username already exists": "Nama pengguna telah digunakan oleh pengguna lain",
|
21
24
|
"error.x is not a member of y": "{x} bukan ahli {y}",
|
22
25
|
"field.active": "Aktif",
|
23
26
|
"field.appliance_id": "Perkakas",
|
package/translations/zh.json
CHANGED
@@ -5,6 +5,7 @@
|
|
5
5
|
"error.confirm password not matched": "新密码与确认密码不匹配!",
|
6
6
|
"error.domain mismatch": "证书不适用于该域!",
|
7
7
|
"error.domain not allowed": "用户无权限使用`{subdomain}`域!",
|
8
|
+
"error.email already exists": "电子邮件已被其他用户使用!",
|
8
9
|
"error.failed to find x": "查询{x}失败!",
|
9
10
|
"error.password should be supported": "应支持初始密码或默认密码",
|
10
11
|
"error.password should match the rule": "密码应符合以下规则。${rule}",
|
@@ -12,13 +13,15 @@
|
|
12
13
|
"error.subdomain not found": "用户域查询失败!",
|
13
14
|
"error.token or password is invalid": "令牌或密码无效!",
|
14
15
|
"error.unavailable-domain": "不可用的域名",
|
16
|
+
"error.user credential not found": "用户凭证未找到。您需要注册设备以使用生物识别认证。",
|
15
17
|
"error.user credential registeration failed": "用户凭证注册失败。可能是已注册的凭证。",
|
16
18
|
"error.user credential registration not allowed": "用户凭证注册失败。注册超时或注册不被允许。",
|
17
|
-
"error.user duplicated": "
|
19
|
+
"error.user duplicated": "存在一个用户帐户使用相同的电子邮件或用户ID。",
|
18
20
|
"error.user not activated": "用户未激活!",
|
19
21
|
"error.user not found": "找不到用户",
|
20
22
|
"error.user or verification token not found": "找不到用户或验证令牌。",
|
21
23
|
"error.user validation failed": "用户验证失败!",
|
24
|
+
"error.username already exists": "用户名已被其他用户使用",
|
22
25
|
"error.x is not a member of y": "{x}不是{y}的成员",
|
23
26
|
"field.active": "激活",
|
24
27
|
"field.appliance_id": "终端机ID",
|