@abtnode/auth 1.16.32-beta-4d47ae7f → 1.16.32-beta-0593a408

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/lib/auth.js CHANGED
@@ -34,6 +34,7 @@ const {
34
34
  upsertToPassports,
35
35
  createUserPassport,
36
36
  getRoleFromLocalPassport,
37
+ createKycVC,
37
38
  } = require('./passport');
38
39
 
39
40
  const createPassportSvg = require('./util/create-passport-svg');
@@ -48,6 +49,10 @@ const messages = {
48
49
  requestOwnerPassport: getLocaleMap('requestOwnerPassport'),
49
50
  requestBlockletNft: getLocaleMap('requestBlockletNft'),
50
51
  receivePassport: getLocaleMap('receivePassport'),
52
+ requestEmailKyc: getLocaleMap('requestEmailKyc'),
53
+ requestPhoneKyc: getLocaleMap('requestPhoneKyc'),
54
+ receiveEmailKyc: getLocaleMap('receiveEmailKyc'),
55
+ receivePhoneKyc: getLocaleMap('receivePhoneKyc'),
51
56
 
52
57
  // error
53
58
  actionForbidden: getLocaleMap('actionForbidden'),
@@ -59,9 +64,14 @@ const messages = {
59
64
  notAppOwner: getLocaleMap('notAppOwner'),
60
65
  notSupported: getLocaleMap('notSupported'),
61
66
  notAllowedAppUser: getLocaleMap('notAllowedAppUser'),
62
- missingCredentialClaim: getLocaleMap('missingCredentialClaim'),
63
- missingBlockletCredentialClaim: getLocaleMap('missingBlockletCredentialClaim'),
67
+ missingPassport: getLocaleMap('missingPassport'),
68
+ missingEmailKyc: getLocaleMap('missingEmailKyc'),
69
+ missingPhoneKyc: getLocaleMap('missingPhoneKyc'),
64
70
  missingChallenge: getLocaleMap('missingChallenge'),
71
+ emailMismatch: getLocaleMap('emailMismatch'),
72
+ phoneMismatch: getLocaleMap('phoneMismatch'),
73
+ emailAlreadyUsed: getLocaleMap('emailAlreadyUsed'),
74
+ phoneAlreadyUsed: getLocaleMap('phoneAlreadyUsed'),
65
75
  invalidCredentialHolder: getLocaleMap('invalidCredentialHolder'),
66
76
  invalidCredentialProof: getLocaleMap('invalidCredentialProof'),
67
77
  notOwner: getLocaleMap('notOwner'),
@@ -273,12 +283,14 @@ const createAuthToken = ({
273
283
  tokenType,
274
284
  provider = LOGIN_PROVIDER.WALLET,
275
285
  walletOS,
286
+ kyc = 0,
276
287
  } = {}) => {
277
288
  const payload = {
278
289
  type: 'user',
279
290
  did,
280
291
  role,
281
292
  provider,
293
+ kyc,
282
294
  };
283
295
  if (walletOS) {
284
296
  payload.walletOS = walletOS;
@@ -375,6 +387,8 @@ const createInvitationRequest = async ({ node, nodeInfo, teamDid, inviteId, base
375
387
  display: JSON.stringify({
376
388
  type: 'svg',
377
389
  content: createPassportSvg({
390
+ scope: 'passport',
391
+ role: inviteInfo.role,
378
392
  issuer: issuerName,
379
393
  title: passport.title,
380
394
  issuerDid: issuerWallet.address,
@@ -401,6 +415,7 @@ const handleInvitationReceive = async ({
401
415
  endpoint,
402
416
  profile,
403
417
  provider = LOGIN_PROVIDER.WALLET,
418
+ kycUpdates = {},
404
419
  }) => {
405
420
  if (!nodeInfo.nodeOwner) {
406
421
  throw new Error(messages.notInitialized[locale]);
@@ -518,6 +533,7 @@ const handleInvitationReceive = async ({
518
533
  teamDid,
519
534
  user: {
520
535
  ...profile,
536
+ ...kycUpdates,
521
537
  avatar,
522
538
  did: user.did,
523
539
  pk: user.pk,
@@ -547,6 +563,7 @@ const handleInvitationReceive = async ({
547
563
  teamDid,
548
564
  user: {
549
565
  ...profile,
566
+ ...kycUpdates,
550
567
  avatar,
551
568
  did: userDid,
552
569
  pk: userPk,
@@ -610,6 +627,7 @@ const handleInvitationResponse = async ({
610
627
  statusEndpointBaseUrl,
611
628
  endpoint,
612
629
  newNftOwner,
630
+ kycUpdates = {},
613
631
  }) => {
614
632
  const claim = claims.find((x) => x.type === 'signature');
615
633
  verifySignature(claim, userDid, userPk, locale);
@@ -630,6 +648,7 @@ const handleInvitationResponse = async ({
630
648
  endpoint,
631
649
  profile,
632
650
  provider: LOGIN_PROVIDER.WALLET,
651
+ kycUpdates,
633
652
  });
634
653
 
635
654
  return receiveResult;
@@ -683,6 +702,8 @@ const createIssuePassportRequest = async ({ node, nodeInfo, teamDid, id, baseUrl
683
702
  display: JSON.stringify({
684
703
  type: 'svg',
685
704
  content: createPassportSvg({
705
+ scope: 'passport',
706
+ role: issuanceInfo.name,
686
707
  issuer: issuerName,
687
708
  title: passport.title,
688
709
  issuerDid: issuerWallet.address,
@@ -696,10 +717,6 @@ const createIssuePassportRequest = async ({ node, nodeInfo, teamDid, id, baseUrl
696
717
  };
697
718
  };
698
719
 
699
- /**
700
- * @param {string} endpoint passport endpoint
701
- * @param {string} statusEndpointBaseUrl passport status endpoint base url
702
- */
703
720
  const handleIssuePassportResponse = async ({
704
721
  req = {},
705
722
  node,
@@ -828,7 +845,7 @@ const handleIssuePassportResponse = async ({
828
845
  };
829
846
  };
830
847
 
831
- const getVCFromClaims = ({ claims, challenge, trustedIssuers, vcTypes, locale = 'en', vcId }) => {
848
+ const getVCFromClaims = ({ claims, challenge, trustedIssuers, types, locale = 'en', vcId = '' }) => {
832
849
  const credential = claims
833
850
  .filter(Boolean) // FIXES: https://github.com/ArcBlock/did-connect/issues/74
834
851
  .find(
@@ -836,7 +853,7 @@ const getVCFromClaims = ({ claims, challenge, trustedIssuers, vcTypes, locale =
836
853
  x.type === 'verifiableCredential' &&
837
854
  // 注意此处不要筛选出 did Spaces 的 verifiableCredential
838
855
  x?.meta?.purpose !== 'DidSpace' &&
839
- vcTypes.some((item) => x.item.includes(item))
856
+ types.some((item) => x.item.includes(item))
840
857
  );
841
858
 
842
859
  if (!credential || !credential.presentation) {
@@ -870,14 +887,13 @@ const getVCFromClaims = ({ claims, challenge, trustedIssuers, vcTypes, locale =
870
887
  }
871
888
 
872
889
  // verify vc type
873
- const types = [].concat(vc.type);
874
- if (!types.some((x) => vcTypes.includes(x))) {
875
- throw new Error(messages.invalidCredentialType[locale](vcTypes));
890
+ if (![].concat(vc.type).some((x) => types.includes(x))) {
891
+ throw new Error(messages.invalidCredentialType[locale](types));
876
892
  }
877
893
 
878
894
  return {
879
895
  vc,
880
- types,
896
+ types: [].concat(vc.type),
881
897
  };
882
898
  };
883
899
 
@@ -1046,12 +1062,14 @@ const setUserInfoHeaders = (req) => {
1046
1062
  req.headers['x-user-provider'] = req.user.provider || LOGIN_PROVIDER.WALLET;
1047
1063
  req.headers['x-connected-did'] = req.user.did;
1048
1064
  req.headers['x-user-wallet-os'] = req.user.walletOS || '';
1065
+ req.headers['x-user-kyc'] = req.user.kyc || 0;
1049
1066
  } else {
1050
1067
  delete req.headers['x-user-did'];
1051
1068
  delete req.headers['x-user-fullname'];
1052
1069
  delete req.headers['x-user-role'];
1053
1070
  delete req.headers['x-user-provider'];
1054
1071
  delete req.headers['x-user-wallet-os'];
1072
+ delete req.headers['x-user-kyc'];
1055
1073
 
1056
1074
  if (req.cookies && req.cookies.connected_did) {
1057
1075
  req.headers['x-connected-did'] = req.cookies.connected_did;
@@ -1135,6 +1153,163 @@ const verifyNFT = async ({ claims, challenge, chainHost, locale }) => {
1135
1153
  return state;
1136
1154
  };
1137
1155
 
1156
+ const beforeIssueKycRequest = async ({ node, teamDid, code, locale = 'en' }) => {
1157
+ const blocklet = await node.getBlocklet({ did: teamDid });
1158
+ if (!blocklet?.settings?.notification?.email?.enabled) {
1159
+ throw new Error(
1160
+ {
1161
+ en: 'Email notification is not enabled',
1162
+ zh: '邮箱通知未启用',
1163
+ }[locale]
1164
+ );
1165
+ }
1166
+
1167
+ const doc = await node.getVerifyCode({ teamDid, code });
1168
+ if (!doc || !doc.verified) {
1169
+ throw new Error(
1170
+ {
1171
+ en: 'The verification code is not verified',
1172
+ zh: '验证码未验证',
1173
+ }[locale]
1174
+ );
1175
+ }
1176
+ };
1177
+
1178
+ const handleIssueKycResponse = async ({
1179
+ request = {},
1180
+ node,
1181
+ nodeInfo,
1182
+ teamDid,
1183
+ userDid,
1184
+ userPk,
1185
+ code,
1186
+ locale = 'en',
1187
+ claims,
1188
+ statusEndpointBaseUrl,
1189
+ endpoint,
1190
+ updateKyc,
1191
+ inviter,
1192
+ }) => {
1193
+ const blocklet = await node.getBlocklet({ did: teamDid });
1194
+ const profile = claims.find((x) => x.type === 'profile');
1195
+ const doc = await node.getVerifyCode({ teamDid, code });
1196
+
1197
+ const user = await getUser(node, teamDid, userDid, { enableConnectedAccount: true });
1198
+ if (user && !user.approved) {
1199
+ throw new Error(
1200
+ {
1201
+ zh: '你没有权限访问该应用',
1202
+ en: 'You are not allowed to access this app',
1203
+ }[locale]
1204
+ );
1205
+ }
1206
+
1207
+ const {
1208
+ name: issuerName,
1209
+ wallet: issuerWallet,
1210
+ dataDir,
1211
+ passportColor,
1212
+ logo,
1213
+ } = await getApplicationInfo({ node, nodeInfo, teamDid, baseUrl: endpoint });
1214
+
1215
+ const ownerAvatar = getUserAvatarUrl(
1216
+ endpoint,
1217
+ await extractUserAvatar(profile.avatar, { dataDir }),
1218
+ nodeInfo,
1219
+ teamDid === nodeInfo.did
1220
+ );
1221
+
1222
+ const vc = createKycVC({
1223
+ issuerName,
1224
+ issuerWallet,
1225
+ issuerAvatarUrl: logo,
1226
+ ownerDid: userDid,
1227
+ kyc: {
1228
+ scope: doc.scope,
1229
+ subject: doc.subject,
1230
+ digest: doc.digest,
1231
+ specVersion: doc.specVersion,
1232
+ },
1233
+ endpoint: getPassportStatusEndpoint({
1234
+ baseUrl: statusEndpointBaseUrl,
1235
+ userDid,
1236
+ teamDid,
1237
+ }),
1238
+ types: {
1239
+ email: ['VerifiedEmailCredential'],
1240
+ phone: ['VerifiedPhoneCredential'],
1241
+ }[doc.scope],
1242
+ ownerProfile: {
1243
+ avatar: ownerAvatar,
1244
+ fullName: profile.fullName,
1245
+ },
1246
+ preferredColor: passportColor,
1247
+ });
1248
+
1249
+ // persist passport
1250
+ const passport = createUserPassport(vc, { role: doc.scope });
1251
+ logger.debug('issued kyc passport', passport);
1252
+ const passports = upsertToPassports(user?.passports || [], passport);
1253
+ if (user) {
1254
+ const emailVerified = Boolean(updateKyc ? doc.scope === 'email' : user.emailVerified);
1255
+ const phoneVerified = Boolean(updateKyc ? doc.scope === 'phone' : user.phoneVerified);
1256
+ const newEmail = updateKyc && doc.scope === 'email' && emailVerified ? doc.subject : user.email;
1257
+ const newPhone = updateKyc && doc.scope === 'phone' && phoneVerified ? doc.subject : user.phone;
1258
+ await node.updateUser({
1259
+ teamDid,
1260
+ user: {
1261
+ did: userDid,
1262
+ pk: userPk,
1263
+ email: newEmail,
1264
+ phone: newPhone,
1265
+ passports,
1266
+ emailVerified,
1267
+ phoneVerified,
1268
+ kycChanged: emailVerified !== user.emailVerified || phoneVerified !== user.phoneVerified,
1269
+ },
1270
+ });
1271
+ await node.createAuditLog(
1272
+ {
1273
+ action: 'issueKyc',
1274
+ args: { teamDid, userDid, code, reason: 'claimed kyc' },
1275
+ context: formatContext(Object.assign(request, { user })),
1276
+ result: passport,
1277
+ },
1278
+ node
1279
+ );
1280
+ } else {
1281
+ const emailVerified = doc.scope === 'email';
1282
+ const phoneVerified = doc.scope === 'phone';
1283
+ const newEmail = emailVerified ? doc.subject : '';
1284
+ const newPhone = phoneVerified ? doc.subject : '';
1285
+ await node.addUser({
1286
+ teamDid,
1287
+ user: {
1288
+ did: userDid,
1289
+ pk: userPk,
1290
+ email: newEmail,
1291
+ phone: newPhone,
1292
+ emailVerified,
1293
+ phoneVerified,
1294
+ passports,
1295
+ inviter,
1296
+ approved: true,
1297
+ ...profile,
1298
+ avatar: await extractUserAvatar(get(profile, 'avatar'), {
1299
+ dataDir: blocklet.env.dataDir,
1300
+ }),
1301
+ },
1302
+ });
1303
+ logger.info('issued kyc passport for new user', { userDid, teamDid });
1304
+ }
1305
+
1306
+ return {
1307
+ disposition: 'attachment',
1308
+ type: 'VerifiableCredential',
1309
+ data: vc,
1310
+ };
1311
+ };
1312
+
1138
1313
  /**
1139
1314
  * @typedef {Object} UserSessionRequstData
1140
1315
  * @property {string} teamDid
@@ -1172,5 +1347,7 @@ module.exports = {
1172
1347
  validatePassportStatus,
1173
1348
  setUserInfoHeaders,
1174
1349
  createBlockletControllerAuthToken,
1350
+ beforeIssueKycRequest,
1351
+ handleIssueKycResponse,
1175
1352
  TEAM_TYPE,
1176
1353
  };
@@ -2,17 +2,18 @@ const path = require('path');
2
2
  const { joinURL } = require('ufo');
3
3
  const uniqBy = require('lodash/uniqBy');
4
4
  const uniq = require('lodash/uniq');
5
+ const get = require('lodash/get');
6
+ const isFunction = require('lodash/isFunction');
5
7
  const getBlockletInfo = require('@blocklet/meta/lib/info');
6
8
  const formatContext = require('@abtnode/util/lib/format-context');
7
9
  const getRandomMessage = require('@abtnode/util/lib/get-random-message');
8
10
  const getNodeWallet = require('@abtnode/util/lib/get-app-wallet');
9
11
  const { getDisplayName, getBlockletAppIdList } = require('@blocklet/meta/lib/util');
10
12
  const { VC_TYPE_NODE_PASSPORT, PASSPORT_STATUS, NODE_DATA_DIR_NAME } = require('@abtnode/constant');
11
- const get = require('lodash/get');
12
- const isFunction = require('lodash/isFunction');
13
13
  const { getUserAvatarUrl, getAppAvatarUrl, getServerAvatarUrl, extractUserAvatar } = require('@abtnode/util/lib/user');
14
14
  const getRequestIP = require('@abtnode/util/lib/get-request-ip');
15
15
  const { getWalletDid } = require('@blocklet/meta/lib/did-utils');
16
+ const { Hasher } = require('@ocap/mcrypto');
16
17
  const { getSourceAppPid, getLoginProvider } = require('@blocklet/sdk/lib/util/login');
17
18
  const {
18
19
  getFederatedMaster,
@@ -28,6 +29,7 @@ const {
28
29
  upsertToPassports,
29
30
  createUserPassport,
30
31
  getRoleFromLocalPassport,
32
+ createKycVC,
31
33
  } = require('./passport');
32
34
  const verifySignature = require('./util/verify-signature');
33
35
 
@@ -183,7 +185,7 @@ const createLostPassportIssueRoute = ({ node, type, authServicePrefix, createTok
183
185
  },
184
186
  {
185
187
  signature: async ({ extraParams, context: { baseUrl, request, didwallet } }) => {
186
- const { locale, passportName, receiverDid } = extraParams;
188
+ const { locale, passportId, receiverDid } = extraParams;
187
189
  checkWalletVersion({ didwallet, locale });
188
190
 
189
191
  const { teamDid, issuerDid, issuerName, issuerLogo, passportColor, info, dataDir } = await getApplicationInfo({
@@ -193,7 +195,13 @@ const createLostPassportIssueRoute = ({ node, type, authServicePrefix, createTok
193
195
  baseUrl,
194
196
  });
195
197
  const user = await getUser(node, teamDid, receiverDid, { enableConnectedAccount: true });
196
- const passport = await createPassport({ name: passportName, node, teamDid, locale });
198
+ const oldPassport = await node.getPassportById({ teamDid, passportId });
199
+
200
+ let { title } = oldPassport;
201
+ if (oldPassport.scope === 'passport') {
202
+ const passport = await createPassport({ name: oldPassport.name, node, teamDid, locale });
203
+ title = passport.title;
204
+ }
197
205
 
198
206
  const avatar = await extractUserAvatar(user.avatar, { dataDir });
199
207
 
@@ -204,8 +212,10 @@ const createLostPassportIssueRoute = ({ node, type, authServicePrefix, createTok
204
212
  display: JSON.stringify({
205
213
  type: 'svg',
206
214
  content: createPassportSvg({
215
+ scope: oldPassport.scope,
216
+ role: oldPassport.role,
207
217
  issuer: issuerName,
208
- title: passport.title,
218
+ title: oldPassport.scope === 'kyc' ? oldPassport.name : title,
209
219
  issuerDid,
210
220
  issuerAvatarUrl: issuerLogo,
211
221
  ownerDid: receiverDid,
@@ -220,10 +230,11 @@ const createLostPassportIssueRoute = ({ node, type, authServicePrefix, createTok
220
230
  ],
221
231
 
222
232
  onAuth: async ({ claims, userDid, userPk, extraParams, updateSession, baseUrl, req, request }) => {
223
- const { locale = 'en', receiverDid, passportName } = extraParams;
233
+ const { locale = 'en', receiverDid, passportId } = extraParams;
224
234
 
225
235
  const { teamDid, issuerDidList, issuerName, issuerLogo, issuerWallet, passportColor, info, dataDir } =
226
236
  await getApplicationInfo({ node, req, type, baseUrl });
237
+ const oldPassport = await node.getPassportById({ teamDid, passportId });
227
238
  const statusEndpointBaseUrl = getStatusEndpointBaseUrl(type, baseUrl, authServicePrefix);
228
239
 
229
240
  // Verify signature
@@ -258,7 +269,7 @@ const createLostPassportIssueRoute = ({ node, type, authServicePrefix, createTok
258
269
  // check passport
259
270
  const exist = (user.passports || []).find(
260
271
  (x) =>
261
- x.name === passportName &&
272
+ x.name === oldPassport.name &&
262
273
  x.status === PASSPORT_STATUS.VALID &&
263
274
  issuerDidList.includes(x.issuer.id) &&
264
275
  (!x.expirationDate || Date.now() > new Date(x.expirationDate).getTime())
@@ -275,37 +286,69 @@ const createLostPassportIssueRoute = ({ node, type, authServicePrefix, createTok
275
286
 
276
287
  const avatar = await extractUserAvatar(user.avatar, { dataDir });
277
288
 
278
- const vcParams = {
279
- issuerName,
280
- issuerWallet,
281
- issuerAvatarUrl: issuerLogo,
282
- ownerDid: userDid,
283
- passport: await createPassport({
284
- name: passportName,
285
- node,
286
- teamDid,
287
- locale,
288
- endpoint: baseUrl,
289
- }),
290
- endpoint: getPassportStatusEndpoint({
291
- baseUrl: statusEndpointBaseUrl,
292
- userDid,
293
- teamDid,
294
- }),
295
- types: [],
296
- ownerProfile: { ...user, avatar: getUserAvatarUrl(baseUrl, avatar, info, info.did === teamDid) },
297
- preferredColor: passportColor,
298
- };
299
-
300
- if (type === TEAM_TYPES.NODE) {
301
- vcParams.types = [VC_TYPE_NODE_PASSPORT];
302
- vcParams.tag = teamDid;
303
- }
289
+ let vc;
290
+ let role;
291
+ let passport;
292
+
293
+ if (oldPassport.scope === 'passport') {
294
+ const vcParams = {
295
+ issuerName,
296
+ issuerWallet,
297
+ issuerAvatarUrl: issuerLogo,
298
+ ownerDid: userDid,
299
+ passport: await createPassport({
300
+ name: oldPassport.name,
301
+ node,
302
+ teamDid,
303
+ locale,
304
+ endpoint: baseUrl,
305
+ }),
306
+ endpoint: getPassportStatusEndpoint({
307
+ baseUrl: statusEndpointBaseUrl,
308
+ userDid,
309
+ teamDid,
310
+ }),
311
+ types: [],
312
+ ownerProfile: { ...user, avatar: getUserAvatarUrl(baseUrl, avatar, info, info.did === teamDid) },
313
+ preferredColor: passportColor,
314
+ };
304
315
 
305
- const vc = createPassportVC(vcParams);
316
+ if (type === TEAM_TYPES.NODE) {
317
+ vcParams.types = [VC_TYPE_NODE_PASSPORT];
318
+ vcParams.tag = teamDid;
319
+ }
306
320
 
307
- const role = getRoleFromLocalPassport(get(vc, 'credentialSubject.passport'));
308
- const passport = createUserPassport(vc, { role });
321
+ vc = createPassportVC(vcParams);
322
+ role = getRoleFromLocalPassport(get(vc, 'credentialSubject.passport'));
323
+ passport = createUserPassport(vc, { role });
324
+ }
325
+ if (oldPassport.scope === 'kyc') {
326
+ vc = createKycVC({
327
+ issuerName,
328
+ issuerWallet,
329
+ issuerAvatarUrl: issuerLogo,
330
+ ownerDid: userDid,
331
+ kyc: {
332
+ scope: oldPassport.role,
333
+ subject: oldPassport.name,
334
+ digest: Hasher.SHA3.hash256(oldPassport.name),
335
+ specVersion: oldPassport.specVersion,
336
+ },
337
+ endpoint: getPassportStatusEndpoint({
338
+ baseUrl: statusEndpointBaseUrl,
339
+ userDid,
340
+ teamDid,
341
+ }),
342
+ types: {
343
+ email: ['VerifiedEmailCredential'],
344
+ phone: ['VerifiedPhoneCredential'],
345
+ }[oldPassport.role],
346
+ ownerProfile: { ...user, avatar: getUserAvatarUrl(baseUrl, avatar, info, info.did === teamDid) },
347
+ preferredColor: passportColor,
348
+ });
349
+ role = oldPassport.role;
350
+ passport = createUserPassport(vc, { role });
351
+ }
309
352
 
310
353
  const result = await node.updateUser({
311
354
  teamDid,
@@ -325,7 +368,7 @@ const createLostPassportIssueRoute = ({ node, type, authServicePrefix, createTok
325
368
  node
326
369
  );
327
370
 
328
- if (isFunction(createToken)) {
371
+ if (oldPassport.scope === 'passport' && isFunction(createToken)) {
329
372
  if (type === TEAM_TYPES.BLOCKLET) {
330
373
  const lastLoginIp = getRequestIP(request);
331
374
  const walletDeviceMessageToken = request.get('wallet-device-message-token');
package/lib/passport.js CHANGED
@@ -1,8 +1,9 @@
1
1
  /* eslint-disable max-len */
2
2
 
3
3
  const Joi = require('joi');
4
- const { joinURL } = require('ufo');
4
+ const { joinURL, withQuery } = require('ufo');
5
5
  const pick = require('lodash/pick');
6
+ const uniq = require('lodash/uniq');
6
7
  const { create: createVC } = require('@arcblock/vc');
7
8
  const {
8
9
  ROLES,
@@ -29,6 +30,27 @@ const validatePassport = (d) => {
29
30
  return value;
30
31
  };
31
32
 
33
+ const kycSchema = Joi.object({
34
+ scope: Joi.string().valid('email', 'phone').required(),
35
+ subject: Joi.alternatives().conditional('scope', {
36
+ is: 'email',
37
+ then: Joi.string().email().required(),
38
+ otherwise: Joi.string()
39
+ .pattern(/^\+?[1-9]\d{1,14}$/)
40
+ .required(),
41
+ }),
42
+ digest: Joi.string().required().trim(),
43
+ specVersion: Joi.string().trim(),
44
+ }).options({ stripUnknown: true });
45
+
46
+ const validateKyc = (d) => {
47
+ const { value, error } = kycSchema.validate(d);
48
+ if (error) {
49
+ throw Array.isArray(error) ? error[0] : error;
50
+ }
51
+ return value;
52
+ };
53
+
32
54
  const createPassport = async ({ name, node, locale = 'en', teamDid, endpoint, role: inputRole = null } = {}) => {
33
55
  const passportNotFound = {
34
56
  en: (x) => `The passport was not found: ${x}`,
@@ -86,6 +108,7 @@ const createPassportVC = ({
86
108
  display: {
87
109
  type: 'svg',
88
110
  content: createPassportSvg({
111
+ scope: 'passport',
89
112
  issuer: issuerName,
90
113
  issuerDid: issuerWallet.address,
91
114
  issuerAvatarUrl,
@@ -103,6 +126,48 @@ const createPassportVC = ({
103
126
  });
104
127
  };
105
128
 
129
+ const createKycVC = ({
130
+ issuerWallet,
131
+ issuerName,
132
+ issuerAvatarUrl,
133
+ ownerDid,
134
+ kyc,
135
+ endpoint,
136
+ types = [],
137
+ ownerProfile,
138
+ preferredColor,
139
+ } = {}) => {
140
+ validateKyc(kyc);
141
+
142
+ return createVC({
143
+ type: uniq(['KycCredential', 'VerifiableCredential', ...types].filter(Boolean)),
144
+ issuer: {
145
+ wallet: issuerWallet,
146
+ name: issuerName,
147
+ },
148
+ subject: {
149
+ id: ownerDid,
150
+ kyc,
151
+ display: {
152
+ type: 'svg',
153
+ content: createPassportSvg({
154
+ scope: 'kyc',
155
+ role: kyc.scope,
156
+ issuer: issuerName,
157
+ issuerDid: issuerWallet.address,
158
+ issuerAvatarUrl,
159
+ title: kyc.subject || { email: 'VerifiedEmailCredential', phone: 'VerifiedPhoneCredential' }[kyc.scope],
160
+ ownerDid,
161
+ ownerName: ownerProfile ? ownerProfile.fullName : '',
162
+ ownerAvatarUrl: ownerProfile ? ownerProfile.avatar : '',
163
+ preferredColor,
164
+ }),
165
+ },
166
+ },
167
+ endpoint,
168
+ });
169
+ };
170
+
106
171
  /**
107
172
  * insert or update passport to passports
108
173
  */
@@ -173,15 +238,34 @@ const createUserPassport = (vc, { status = PASSPORT_STATUS.VALID, role = ROLES.G
173
238
  }
174
239
 
175
240
  const x = pick(vc, ['id', 'type', 'issuer', 'issuanceDate', 'expirationDate']);
176
- Object.assign(x, vc.credentialSubject.passport);
177
241
  x.status = status;
178
242
  x.role = role;
179
243
 
244
+ if (['email', 'phone'].includes(role)) {
245
+ Object.assign(x, {
246
+ ...vc.credentialSubject.kyc,
247
+ title: { email: 'VerifiedEmailCredential', phone: 'VerifiedPhoneCredential' }[role],
248
+ name: vc.credentialSubject.kyc.subject,
249
+ scope: 'kyc',
250
+ role,
251
+ });
252
+ } else {
253
+ Object.assign(x, {
254
+ ...vc.credentialSubject.passport,
255
+ scope: 'passport',
256
+ });
257
+ }
258
+
180
259
  return x;
181
260
  };
182
261
 
183
- const getPassportClaimUrl = (baseUrl, prefix = '') =>
184
- baseUrl ? joinURL(new URL(baseUrl).origin, prefix, WELLKNOWN_SERVICE_PATH_PREFIX, '/lost-passport') : '';
262
+ const getPassportClaimUrl = (baseUrl, prefix = '', role = undefined) =>
263
+ baseUrl
264
+ ? withQuery(joinURL(new URL(baseUrl).origin, prefix, WELLKNOWN_SERVICE_PATH_PREFIX, '/lost-passport'), { role })
265
+ : '';
266
+
267
+ const getKycAcquireUrl = (baseUrl, prefix = '', role = 'email') =>
268
+ baseUrl ? joinURL(new URL(baseUrl).origin, prefix, WELLKNOWN_SERVICE_PATH_PREFIX, `/kyc/${role}`) : '';
185
269
 
186
270
  module.exports = {
187
271
  validatePassport,
@@ -196,4 +280,8 @@ module.exports = {
196
280
  getRoleFromExternalPassport,
197
281
  createUserPassport,
198
282
  getPassportClaimUrl,
283
+ getKycAcquireUrl,
284
+ kycSchema,
285
+ createKycVC,
286
+ validateKyc,
199
287
  };
package/lib/server.js CHANGED
@@ -137,7 +137,7 @@ const authenticateByVc = async ({
137
137
  claims,
138
138
  challenge,
139
139
  trustedIssuers,
140
- vcTypes: BLOCKLET_SERVER_VC_TYPES,
140
+ types: BLOCKLET_SERVER_VC_TYPES,
141
141
  locale,
142
142
  vcId: blocklet?.controller?.vcId,
143
143
  });
@@ -28,7 +28,7 @@ const getTextColor = (background) => {
28
28
  * @param {string} params.title passport title
29
29
  * @param {string} params.issuer issuer name
30
30
  * @param {string} params.issuerDid
31
- * @param {string} params.ownerName
31
+ * @param {string} [params.ownerName]
32
32
  * @param {string} params.ownerDid
33
33
  * @param {string} params.ownerAvatarUrl
34
34
  * @param {string} [params.preferredColor]
@@ -38,6 +38,9 @@ const getTextColor = (background) => {
38
38
  * @param {string} [params.issuerAvatarUrl]
39
39
  * @param {boolean} [params.revoked] 是否撤销
40
40
  * @param {boolean} [params.isDataUrl] 返回生成 data url
41
+ * @param {object} [params.extra]
42
+ * @param {string} [params.scope]
43
+ * @param {string} [params.role]
41
44
  * @returns {string} svg xml or image data url
42
45
  */
43
46
  const createPassportSvg = ({
@@ -53,6 +56,9 @@ const createPassportSvg = ({
53
56
  isDataUrl = false,
54
57
  width = '100%',
55
58
  height = '100%',
59
+ extra = null,
60
+ scope = 'passport',
61
+ role = '',
56
62
  }) => {
57
63
  const color = getPassportColor(preferredColor, issuerDid);
58
64
 
@@ -66,7 +72,7 @@ const createPassportSvg = ({
66
72
  color,
67
73
 
68
74
  did: ownerDid,
69
- variant: 'app-passport' || ownerName,
75
+ variant: `app-${scope}`,
70
76
  verifiable: true,
71
77
 
72
78
  issuer: {
@@ -75,15 +81,11 @@ const createPassportSvg = ({
75
81
  },
76
82
 
77
83
  header: {
78
- name: title,
84
+ name: scope === 'passport' ? title : ownerName,
79
85
  icon: ownerAvatarUrl,
80
86
  },
81
87
 
82
- // FIXME: @wangshijun this should be dynamic
83
- extra: {
84
- key: 'Exp',
85
- value: '2123-01-01',
86
- },
88
+ extra: scope === 'kyc' ? { key: role, value: title } : extra || { key: 'Exp', value: '2123-01-01' },
87
89
  });
88
90
 
89
91
  if (isDataUrl) {
package/locales/ar.js CHANGED
@@ -15,7 +15,6 @@ module.exports = {
15
15
  notAllowed: 'لا يُسمَح لك بتسجيل الدخول إلى هذا العُقدة',
16
16
  notAppOwner: 'أنت لست مالك هذا التطبيق',
17
17
  notSupported: 'هذا التطبيق غير مدعوم على هذا الخادم',
18
- missingCredentialClaim: 'لم يتم توفير أوراق الاعتماد',
19
18
  missingBlockletCredentialClaim: 'لم يتم توفير بيانات اعتماد Blocklet',
20
19
  missingChallenge: 'عرض الاعتماد لا يتضمن تحدي صالح.',
21
20
  invalidCredentialHolder: 'حامل بيانات اعتماد غير صحيحة',
@@ -68,4 +67,15 @@ module.exports = {
68
67
  noLauncherDid: 'لم يتم العثور على المشغّل من معلومات مشغّل الخادم',
69
68
  noNftDid: 'لم يتم العثور على NFT من معلومات مشغل الخادم',
70
69
  notAllowedAppUser: 'تم إلغاء وصولك إلى هذا التطبيق',
70
+ requestEmailKyc: 'يرجى تقديم شهادة بريد إلكتروني موثقة',
71
+ receiveEmailKyc: 'يرجى توقيع النص للحصول على شهادة بريد إلكتروني موثقة',
72
+ requestPhoneKyc: 'يرجى تقديم شهادة موثقة بالهاتف',
73
+ receivePhoneKyc: 'يرجى توقيع النص للحصول على شهادة هاتف موثقة',
74
+ missingPassport: 'الجواز غير مقدم',
75
+ missingEmailKyc: 'شهادة البريد الإلكتروني المتحققة غير متوفرة',
76
+ emailAlreadyUsed: 'البريد الإلكتروني مستخدم بالفعل',
77
+ emailMismatch: 'عدم تطابق البريد الإلكتروني بين الملف الشخصي والشهادة الموثقة',
78
+ missingPhoneKyc: 'الشهادة الموثقة بالهاتف غير متوفرة',
79
+ phoneAlreadyUsed: 'تم استخدام الهاتف بالفعل',
80
+ phoneMismatch: 'عدم تطابق الهاتف بين الملف الشخصي والشهادة الموثقة',
71
81
  };
package/locales/de.js CHANGED
@@ -15,7 +15,6 @@ module.exports = {
15
15
  notAllowed: 'Sie dürfen sich nicht bei diesem Knotenpunkt anmelden',
16
16
  notAppOwner: 'Sie sind nicht der Besitzer dieser Anwendung',
17
17
  notSupported: 'Diese Anwendung wird auf diesem Server nicht unterstützt',
18
- missingCredentialClaim: 'Anmeldedaten werden nicht bereitgestellt',
19
18
  missingBlockletCredentialClaim: 'Blocklet-Credential wird nicht bereitgestellt',
20
19
  missingChallenge: 'Die Vorlage von Referenzen beinhaltet keine gültige Herausforderung.',
21
20
  invalidCredentialHolder: 'Ungültiger Berechtigungsinhaber',
@@ -68,4 +67,15 @@ module.exports = {
68
67
  noLauncherDid: 'Launcher wurde nicht von der Server Launcher Info gefunden',
69
68
  noNftDid: 'NFT wurde in den Server-Launcher-Informationen nicht gefunden',
70
69
  notAllowedAppUser: 'Ihr Zugriff auf diese App wurde widerrufen',
70
+ requestEmailKyc: 'Bitte geben Sie ein verifiziertes E-Mail-Zertifikat an',
71
+ receiveEmailKyc: 'Bitte unterschreiben Sie den Text, um ein verifiziertes E-Mail-Zertifikat zu erhalten',
72
+ requestPhoneKyc: 'Bitte geben Sie ein telefonisch verifiziertes Zertifikat an',
73
+ receivePhoneKyc: 'Bitte unterschreiben Sie den Text, um ein verifiziertes Telefonzertifikat zu erhalten',
74
+ missingPassport: 'Pass ist nicht vorhanden',
75
+ missingEmailKyc: 'Verifiziertes E-Mail-Zertifikat wird nicht bereitgestellt',
76
+ emailAlreadyUsed: 'E-Mail bereits verwendet',
77
+ emailMismatch: 'E-Mail-Unstimmigkeit zwischen Profil und verifiziertem Zertifikat',
78
+ missingPhoneKyc: 'Telefonverifiziertes Zertifikat wird nicht bereitgestellt',
79
+ phoneAlreadyUsed: 'Telefon bereits verwendet',
80
+ phoneMismatch: 'Telefonabweichung zwischen Profil und verifiziertem Zertifikat',
71
81
  };
package/locales/en.js CHANGED
@@ -9,6 +9,10 @@ module.exports = {
9
9
  requestOwnerPassport: 'Please provide owner passport',
10
10
  requestBlockletNft: 'Please provide Blocklet Purchase NFT',
11
11
  receivePassport: 'Please sign the text to get passport',
12
+ requestEmailKyc: 'Please provide verified email certificate',
13
+ receiveEmailKyc: 'Please sign the text to get verified email certificate',
14
+ requestPhoneKyc: 'Please provide phone verified certificate',
15
+ receivePhoneKyc: 'Please sign the text to get verified phone certificate',
12
16
  actionForbidden: 'You are not allowed perform this action',
13
17
  notInitialized: 'This node is not initialized, login is disabled',
14
18
  appNotInitialized: 'This application is not initialized',
@@ -17,7 +21,13 @@ module.exports = {
17
21
  notAllowedAppUser: 'You access to this app has been revoked',
18
22
  notAppOwner: 'You are not the owner of this application',
19
23
  notSupported: 'This application is not supported on this server',
20
- missingCredentialClaim: 'Credential is not provided',
24
+ missingPassport: 'Passport is not provided',
25
+ missingEmailKyc: 'Verified email certificate is not provided',
26
+ emailAlreadyUsed: 'Email already used',
27
+ emailMismatch: 'Email mismatch between profile and verified certificate',
28
+ missingPhoneKyc: 'Phone verified certificate is not provided',
29
+ phoneAlreadyUsed: 'Phone already used',
30
+ phoneMismatch: 'Phone mismatch between profile and verified certificate',
21
31
  missingBlockletCredentialClaim: 'Blocklet credential is not provided',
22
32
  missingChallenge: 'Credential presentation does not include valid challenge',
23
33
  invalidCredentialHolder: 'Invalid credential holder',
package/locales/es.js CHANGED
@@ -15,7 +15,6 @@ module.exports = {
15
15
  notAllowed: 'No tienes permitido iniciar sesión en este nodo',
16
16
  notAppOwner: 'No eres el propietario de esta aplicación',
17
17
  notSupported: 'Esta aplicación no es compatible en este servidor',
18
- missingCredentialClaim: 'Credencial no proporcionada',
19
18
  missingBlockletCredentialClaim: 'El credencial de Blocklet no se proporciona',
20
19
  missingChallenge: 'La presentación de credenciales no incluye un desafío válido',
21
20
  invalidCredentialHolder: 'Credencial inválida',
@@ -68,4 +67,15 @@ module.exports = {
68
67
  noLauncherDid: 'El lanzador NO fue encontrado en la información del lanzador del servidor',
69
68
  noNftDid: 'NFT DID no encontrada en el lanzador del servidor',
70
69
  notAllowedAppUser: 'El acceso a esta aplicación ha sido revocado',
70
+ requestEmailKyc: 'Proporcione un certificado de correo electrónico verificado',
71
+ receiveEmailKyc: 'Por favor firmar el texto para obtener un certificado de correo electrónico verificado',
72
+ requestPhoneKyc: 'Proporcione un certificado verificado por teléfono',
73
+ receivePhoneKyc: 'Por favor firma el texto para obtener el certificado de teléfono verificado',
74
+ missingPassport: 'Pasaporte no proporcionado',
75
+ missingEmailKyc: 'Certificado de correo electrónico verificado no proporcionado',
76
+ emailAlreadyUsed: 'Correo electrónico ya utilizado',
77
+ emailMismatch: 'Email no coincide entre el perfil y el certificado verificado',
78
+ missingPhoneKyc: 'Certificado verificado por teléfono no proporcionado',
79
+ phoneAlreadyUsed: 'Teléfono ya utilizado',
80
+ phoneMismatch: 'Desajuste telefónico entre el perfil y el certificado verificado',
71
81
  };
package/locales/fr.js CHANGED
@@ -15,7 +15,6 @@ module.exports = {
15
15
  notAllowed: "Vous n'êtes pas autorisé à vous connecter à ce nœud",
16
16
  notAppOwner: "Vous n'êtes pas le propriétaire de cette application",
17
17
  notSupported: "Cette application n'est pas prise en charge sur ce serveur",
18
- missingCredentialClaim: "Les informations d'identification ne sont pas fournies",
19
18
  missingBlockletCredentialClaim: "L'identifiant du blocklet n'est pas fourni",
20
19
  missingChallenge: 'La présentation des références ne comprend pas de défi valide.',
21
20
  invalidCredentialHolder: 'Détenteur de référence invalide',
@@ -69,4 +68,15 @@ module.exports = {
69
68
  noLauncherDid: "Launcher n'a pas été trouvé depuis les informations du serveur Launcher",
70
69
  noNftDid: 'Aucun NFT trouvé dans les informations du lanceur de serveur',
71
70
  notAllowedAppUser: 'Votre accès à cette application a été révoqué',
71
+ requestEmailKyc: "Veuillez fournir un certificat d'e-mail vérifié",
72
+ receiveEmailKyc: 'Veuillez signer le texte pour obtenir un certificat e-mail vérifié',
73
+ requestPhoneKyc: 'Veuillez fournir un certificat vérifié par téléphone',
74
+ receivePhoneKyc: 'Veuillez signer le texte pour obtenir un certificat de téléphone vérifié',
75
+ missingPassport: "Le passeport n'est pas fourni",
76
+ missingEmailKyc: "Certificat d'e-mail vérifié n'est pas fourni",
77
+ emailAlreadyUsed: 'Email déjà utilisé',
78
+ emailMismatch: "Incompatibilité d'e-mail entre le profil et le certificat vérifié",
79
+ missingPhoneKyc: "Certificat vérifié par téléphone n'est pas fourni",
80
+ phoneAlreadyUsed: 'Téléphone déjà utilisé',
81
+ phoneMismatch: 'Incompatibilité des téléphones entre le profil et le certificat vérifié',
72
82
  };
package/locales/hi.js CHANGED
@@ -15,7 +15,6 @@ module.exports = {
15
15
  notAllowed: 'आपको इस नोड में लॉगिन करने की अनुमति नहीं है',
16
16
  notAppOwner: 'आप इस ऐप्लिकेशन के मालिक नहीं हैं',
17
17
  notSupported: 'इस सर्वर पर यह एप्लिकेशन समर्थित नहीं है',
18
- missingCredentialClaim: 'प्रमाणपत्र उपलब्ध नहीं है',
19
18
  missingBlockletCredentialClaim: 'ब्लॉकलेट प्रमाणपत्र उपलब्ध नहीं है',
20
19
  missingChallenge: 'प्रमाण प्रस्तुति में वैध चुनौती शामिल नहीं है।',
21
20
  invalidCredentialHolder: 'अमान्य प्रमाण प्राथमिकताधारी',
@@ -68,4 +67,15 @@ module.exports = {
68
67
  noLauncherDid: 'Launcher सर्वर लॉन्चर जानकारी से नहीं मिला',
69
68
  noNftDid: 'NFT सर्वर लॉन्चर जानकारी से नहीं मिला',
70
69
  notAllowedAppUser: 'आपके पास इस ऐप का पहुंच रद्द कर दी गई है',
70
+ requestEmailKyc: 'कृपया सत्यापित ईमेल प्रमाणपत्र प्रदान करें',
71
+ receiveEmailKyc: 'कृपया पाठ पर हस्ताक्षर करें ताकि पुष्टिकृत ईमेल प्रमाणपत्र प्राप्त करें',
72
+ requestPhoneKyc: 'कृपया फ़ोन सत्यापित प्रमाणपत्र प्रदान करें',
73
+ receivePhoneKyc: 'कृपया पाठ पर हस्ताक्षर करें ताकि पुष्टि किया जा सके फोन प्रमाणपत्र',
74
+ missingPassport: 'पासपोर्ट नहीं है',
75
+ missingEmailKyc: 'सत्यापित ईमेल प्रमाणपत्र उपलब्ध नहीं है',
76
+ emailAlreadyUsed: 'ईमेल पहले से उपयोग किया गया है',
77
+ emailMismatch: 'प्रोफ़ाइल और सत्यापित प्रमाणपत्र के बीच ईमेल असंगति',
78
+ missingPhoneKyc: 'फोन सत्यापित प्रमाणपत्र प्रदान नहीं किया जाता है',
79
+ phoneAlreadyUsed: 'फ़ोन पहले से उपयोग किया गया है',
80
+ phoneMismatch: 'प्रोफ़ाइल और सत्यापित प्रमाणपत्र के बीच फ़ोन असंगति',
71
81
  };
package/locales/i18n.db CHANGED
Binary file
package/locales/id.js CHANGED
@@ -15,7 +15,6 @@ module.exports = {
15
15
  notAllowed: 'Anda tidak diizinkan untuk login ke simpul ini',
16
16
  notAppOwner: 'Anda bukan pemilik aplikasi ini',
17
17
  notSupported: 'Aplikasi ini tidak didukung di server ini',
18
- missingCredentialClaim: 'Kredensial tidak disediakan',
19
18
  missingBlockletCredentialClaim: 'Kredensial Blocklet tidak disediakan',
20
19
  missingChallenge: 'Penyajian kredensial tidak mencakup tantangan valid',
21
20
  invalidCredentialHolder: 'Pemegang kredensial tidak valid',
@@ -68,4 +67,15 @@ module.exports = {
68
67
  noLauncherDid: 'Launcher TIDAK ditemukan dari info launcher server',
69
68
  noNftDid: 'NFT DID tidak ditemukan dari info peluncur server',
70
69
  notAllowedAppUser: 'Akses Anda ke aplikasi ini telah dicabut',
70
+ requestEmailKyc: 'Harap berikan sertifikat email yang terverifikasi',
71
+ receiveEmailKyc: 'Silakan tandatangani teks untuk mendapatkan sertifikat email yang diverifikasi',
72
+ requestPhoneKyc: 'Silakan berikan sertifikat yang diverifikasi telepon',
73
+ receivePhoneKyc: 'Tolong tandatangani teks untuk mendapatkan sertifikat telepon yang terverifikasi',
74
+ missingPassport: 'Paspor tidak disediakan',
75
+ missingEmailKyc: 'Sertifikat email yang diverifikasi tidak disediakan',
76
+ emailAlreadyUsed: 'Email sudah digunakan',
77
+ emailMismatch: 'Kesalahan pemasangan email antara profil dan sertifikat terverifikasi',
78
+ missingPhoneKyc: 'Sertifikat yang diverifikasi oleh telepon tidak disediakan',
79
+ phoneAlreadyUsed: 'Telepon sudah digunakan',
80
+ phoneMismatch: 'Kesalahan nomor telepon antara profil dan sertifikat terverifikasi',
71
81
  };
package/locales/ja.js CHANGED
@@ -15,7 +15,6 @@ module.exports = {
15
15
  notAllowed: 'このノードへのログインは許可されていません',
16
16
  notAppOwner: 'あなたはこのアプリケーションの所有者ではありません',
17
17
  notSupported: 'このアプリケーションはこのサーバーではサポートされていません',
18
- missingCredentialClaim: '認証情報が提供されていません',
19
18
  missingBlockletCredentialClaim: 'Blockletのクレデンシャルが提供されていません',
20
19
  missingChallenge: '証明書の提示には有効なチャレンジが含まれていません',
21
20
  invalidCredentialHolder: '無効な資格証',
@@ -68,4 +67,15 @@ module.exports = {
68
67
  noLauncherDid: 'ランチャーがサーバーランチャー情報から見つかりませんでした',
69
68
  noNftDid: 'NFT DID がサーバーランチャー情報から見つかりませんでした',
70
69
  notAllowedAppUser: 'このアプリへのアクセスが取り消されました',
70
+ requestEmailKyc: '検証済みの電子メール証明書を提供してください',
71
+ receiveEmailKyc: '検証された電子メール証明書を取得するためにテキストにサインしてください',
72
+ requestPhoneKyc: '電話で確認された証明書を提供してください',
73
+ receivePhoneKyc: '携帯電話の証明書を受け取るためにテキストにサインしてください',
74
+ missingPassport: 'パスポートが提供されていません',
75
+ missingEmailKyc: '検証された電子メール証明書が提供されていません',
76
+ emailAlreadyUsed: 'メールアドレスはすでに使用されています',
77
+ emailMismatch: 'プロフィールと検証済み証明書の電子メールが一致しません',
78
+ missingPhoneKyc: '電話で確認された証明書は提供されていません',
79
+ phoneAlreadyUsed: '電話はすでに使用されています',
80
+ phoneMismatch: 'プロフィールと検証済証明書の間での電話不一致',
71
81
  };
package/locales/ko.js CHANGED
@@ -15,7 +15,6 @@ module.exports = {
15
15
  notAllowed: '이 노드에 로그인할 수 없습니다',
16
16
  notAppOwner: '이 응용 프로그램의 소유자가 아닙니다',
17
17
  notSupported: '이 응용 프로그램은이 서버에서 지원되지 않습니다',
18
- missingCredentialClaim: '자격증명이 제공되지 않았습니다',
19
18
  missingBlockletCredentialClaim: '블록렛 자격 증명서가 제공되지 않았습니다',
20
19
  missingChallenge: '자격 증명 프레젠테이션에 유효한 도전이 포함되지 않습니다',
21
20
  invalidCredentialHolder: '잘못된 자격 증명 보유자',
@@ -68,4 +67,15 @@ module.exports = {
68
67
  noLauncherDid: '서버 런처 정보에서 런처를 찾지 못했습니다',
69
68
  noNftDid: '서버 런처 정보에서 NFT DID를 찾지 못했습니다',
70
69
  notAllowedAppUser: '이 앱에 대한 액세스가 취소되었습니다',
70
+ requestEmailKyc: '인증된 이메일 인증서를 제공해주세요',
71
+ receiveEmailKyc: '인증된 이메일 인증서를 받기 위해 텍스트에 서명해주세요',
72
+ requestPhoneKyc: '전화 인증된 인증서를 제공해주세요',
73
+ receivePhoneKyc: '휴대폰 인증서를 받으려면 텍스트에 서명해주세요',
74
+ missingPassport: '여권이 제공되지 않았습니다',
75
+ missingEmailKyc: '인증된 이메일 인증서가 제공되지 않았습니다',
76
+ emailAlreadyUsed: '이미 사용된 이메일입니다',
77
+ emailMismatch: '프로필과 검증된 인증서 간의 이메일 불일치',
78
+ missingPhoneKyc: '전화 인증 된 인증서가 제공되지 않았습니다',
79
+ phoneAlreadyUsed: '이미 사용된 전화번호',
80
+ phoneMismatch: '프로필과 확인된 인증서 사이의 전화번호 불일치',
71
81
  };
package/locales/pt.js CHANGED
@@ -15,7 +15,6 @@ module.exports = {
15
15
  notAllowed: 'Você não está autorizado a fazer login neste nó',
16
16
  notAppOwner: 'Você não é o proprietário desta aplicação',
17
17
  notSupported: 'Esta aplicação não é suportada neste servidor',
18
- missingCredentialClaim: 'Credencial não fornecida',
19
18
  missingBlockletCredentialClaim: 'A credencial do Blocklet não é fornecida',
20
19
  missingChallenge: 'A apresentação de credenciais não inclui um desafio válido',
21
20
  invalidCredentialHolder: 'Titular de credencial inválido',
@@ -68,4 +67,15 @@ module.exports = {
68
67
  noLauncherDid: 'Launcher NÃO foi encontrado nas informações do Launcher do servidor',
69
68
  noNftDid: 'NFT DID não encontrado nas informações do iniciador do servidor',
70
69
  notAllowedAppUser: 'O seu acesso a este aplicativo foi revogado',
70
+ requestEmailKyc: 'Por favor, forneça certificado de e-mail verificado',
71
+ receiveEmailKyc: 'Por favor, assine o texto para obter um certificado de e-mail verificado',
72
+ requestPhoneKyc: 'Por favor, forneça certificado verificado por telefone',
73
+ receivePhoneKyc: 'Por favor, assine o texto para obter o certificado de telefone verificado',
74
+ missingPassport: 'Passaporte não fornecido',
75
+ missingEmailKyc: 'Certificado de e-mail verificado não é fornecido',
76
+ emailAlreadyUsed: 'Email já utilizado',
77
+ emailMismatch: 'Discrepância de e-mail entre o perfil e o certificado verificado',
78
+ missingPhoneKyc: 'Certificado verificado por telefone não fornecido',
79
+ phoneAlreadyUsed: 'Telefone já utilizado',
80
+ phoneMismatch: 'Discrepância de telefone entre o perfil e o certificado verificado',
71
81
  };
package/locales/ru.js CHANGED
@@ -15,7 +15,6 @@ module.exports = {
15
15
  notAllowed: 'Вам запрещено входить в этот узел',
16
16
  notAppOwner: 'Вы не являетесь владельцем данного приложения',
17
17
  notSupported: 'Это приложение не поддерживается на этом сервере',
18
- missingCredentialClaim: 'Учетные данные не предоставлены',
19
18
  missingBlockletCredentialClaim: 'Учетные данные блоклета не предоставлены',
20
19
  missingChallenge: 'Представление учетных данных не включает в себя действительное испытание.',
21
20
  invalidCredentialHolder: 'Недействительный держатель учетных данных',
@@ -68,4 +67,15 @@ module.exports = {
68
67
  noLauncherDid: 'Laucnher не был найден в информации о запуске сервера',
69
68
  noNftDid: 'NFT не найден в информации о запускающем сервере',
70
69
  notAllowedAppUser: 'Ваш доступ к этому приложению отозван',
70
+ requestEmailKyc: 'Пожалуйста, предоставьте проверенный сертификат электронной почты',
71
+ receiveEmailKyc: 'Пожалуйста, подпишите текст, чтобы получить подтвержденное электронное письмо',
72
+ requestPhoneKyc: 'Пожалуйста, предоставьте телефонно проверенный сертификат',
73
+ receivePhoneKyc: 'Пожалуйста, подпишите текст, чтобы получить проверенное телефонное удостоверение',
74
+ missingPassport: 'Паспорт не предоставлен',
75
+ missingEmailKyc: 'Проверенный электронный сертификат не предоставляется',
76
+ emailAlreadyUsed: 'Электронная почта уже использовалась',
77
+ emailMismatch: 'Несоответствие электронной почты между профилем и проверенным сертификатом',
78
+ missingPhoneKyc: 'Телефонное подтверждение сертификата не предоставляется',
79
+ phoneAlreadyUsed: 'Телефон уже использовался',
80
+ phoneMismatch: 'Несоответствие телефона между профилем и подтвержденным сертификатом',
71
81
  };
package/locales/th.js CHANGED
@@ -15,7 +15,6 @@ module.exports = {
15
15
  notAllowed: 'คุณไม่ได้รับอนุญาตให้เข้าสู่ระบบนี้',
16
16
  notAppOwner: 'คุณไม่ใช่เจ้าของแอปพลิเคชันนี้',
17
17
  notSupported: 'แอปพลิเคชันนี้ไม่รองรับบนเซิร์ฟเวอร์นี้',
18
- missingCredentialClaim: 'ไม่ได้ระบุข้อมูลประจำตัว',
19
18
  missingBlockletCredentialClaim: 'ไม่ได้รับสรรพากร Blocklet',
20
19
  missingChallenge: 'การนำเสนอข้อมูลประจำตัวไม่รวมถึงความท้าทายที่ถูกต้อง',
21
20
  invalidCredentialHolder: 'ผู้ถือข้อมูลประจักษ์ไม่ถูกต้อง',
@@ -68,4 +67,15 @@ module.exports = {
68
67
  noLauncherDid: 'Launcher หาไม่พบจากข้อมูล launcher ของ server',
69
68
  noNftDid: 'ไม่พบ NFT DID จากข้อมูลตัวเปิดใช้เซิร์ฟเวอร์',
70
69
  notAllowedAppUser: 'การเข้าถึงแอปนี้ของคุณถูกยกเลิกแล้ว',
70
+ requestEmailKyc: 'โปรดให้ใบรับรองอีเมลที่ตรวจสอบแล้ว',
71
+ receiveEmailKyc: 'โปรดเซ็นเอกสารเพื่อรับใบรับรองอีเมลที่ตรวจสอบแล้ว',
72
+ requestPhoneKyc: 'โปรดให้ใบรับรองที่ยืนยันโทรศัพท์',
73
+ receivePhoneKyc: 'โปรดเซ็นข้อความเพื่อรับใบร่างในโทรศัพท์ที่ได้รับการตรวจสอบ',
74
+ missingPassport: 'ไม่มีหนังสือเดินทาง',
75
+ missingEmailKyc: 'ไม่มีใบรับรองอีเมลที่ตรวจสอบ',
76
+ emailAlreadyUsed: 'อีเมลถูกใช้แล้ว',
77
+ emailMismatch: 'อีเมลที่ไม่สอดคล้องกันระหว่างโปรไฟล์และใบรับรองที่ตรวจสอบแล้ว',
78
+ missingPhoneKyc: 'ไม่มีใบรับรองที่ได้รับการยืนยันทางโทรศัพท์',
79
+ phoneAlreadyUsed: 'โทรศัพท์ถูกใช้แล้ว',
80
+ phoneMismatch: 'หมายเลขโทรศัพท์ไม่ตรงกันระหว่างโปรไฟล์และใบรับรองที่ตรวจสอบ',
71
81
  };
package/locales/vi.js CHANGED
@@ -15,7 +15,6 @@ module.exports = {
15
15
  notAllowed: 'Bạn không được phép đăng nhập vào nút này',
16
16
  notAppOwner: 'Bạn không phải chủ sở hữu của ứng dụng này',
17
17
  notSupported: 'Ứng dụng này không được hỗ trợ trên máy chủ này',
18
- missingCredentialClaim: 'Mã đăng nhập không được cung cấp',
19
18
  missingBlockletCredentialClaim: 'Không cung cấp chứng chỉ Blocklet',
20
19
  missingChallenge: 'Trình bày phẩm chứng không bao gồm thách thức hợp lệ',
21
20
  invalidCredentialHolder: 'Người sở hữu thông tin đăng nhập không hợp lệ',
@@ -68,4 +67,15 @@ module.exports = {
68
67
  noLauncherDid: 'Launcher KHÔNG tìm thấy từ thông tin launcher của máy chủ',
69
68
  noNftDid: 'NFT DID không tìm thấy từ thông tin trình khởi chạy máy chủ',
70
69
  notAllowedAppUser: 'Quyền truy cập của bạn vào ứng dụng này đã bị thu hồi',
70
+ requestEmailKyc: 'Vui lòng cung cấp chứng chỉ email đã xác minh',
71
+ receiveEmailKyc: 'Vui lòng ký văn bản để nhận chứng chỉ email được xác minh',
72
+ requestPhoneKyc: 'Vui lòng cung cấp chứng chỉ đã xác minh điện thoại',
73
+ receivePhoneKyc: 'Vui lòng ký vào văn bản để nhận chứng chỉ điện thoại được xác minh',
74
+ missingPassport: 'Không cung cấp hộ chiếu',
75
+ missingEmailKyc: 'Chứng chỉ email đã xác minh không được cung cấp',
76
+ emailAlreadyUsed: 'Email đã được sử dụng',
77
+ emailMismatch: 'Mã nguồn email giữa hồ sơ và chứng chỉ đã xác minh',
78
+ missingPhoneKyc: 'Chứng chỉ đã xác minh qua điện thoại không được cung cấp',
79
+ phoneAlreadyUsed: 'Điện thoại đã được sử dụng',
80
+ phoneMismatch: 'Không khớp số điện thoại giữa hồ sơ và chứng chỉ đã xác minh',
71
81
  };
package/locales/zh-tw.js CHANGED
@@ -15,7 +15,6 @@ module.exports = {
15
15
  notAllowed: '您無權登錄此節點',
16
16
  notAppOwner: '你不是這個應用的所有者',
17
17
  notSupported: '此應用程式在此伺服器上不受支援',
18
- missingCredentialClaim: '未提供憑證',
19
18
  missingBlockletCredentialClaim: '未提供Blocklet憑證',
20
19
  missingChallenge: '憑證演示不包括有效的挑戰',
21
20
  invalidCredentialHolder: '憑證持有者無效',
@@ -66,4 +65,15 @@ module.exports = {
66
65
  noLauncherDid: '從伺服器啟動器資訊中沒有發現啟動器',
67
66
  noNftDid: 'NFT DID 沒有在伺服器啟動程式資訊中找到',
68
67
  notAllowedAppUser: '您對此應用的訪問權限已被撤銷',
68
+ requestEmailKyc: '請提供經過驗證的電子郵件證書',
69
+ receiveEmailKyc: '請簽署文字以獲得驗證電子郵件證書',
70
+ requestPhoneKyc: '請提供電話驗證的憑證',
71
+ receivePhoneKyc: '請簽署文字以獲得驗證電話證書',
72
+ missingPassport: '護照未提供',
73
+ missingEmailKyc: '未提供驗證電子郵件證書',
74
+ emailAlreadyUsed: '電子郵件已被使用',
75
+ emailMismatch: '個人檔案和已驗證證書之間的電子郵件不匹配',
76
+ missingPhoneKyc: '未提供電話驗證的證書',
77
+ phoneAlreadyUsed: '電話已經使用',
78
+ phoneMismatch: '個人檔案和已驗證憑證之間的電話不匹配',
69
79
  };
package/locales/zh.js CHANGED
@@ -16,7 +16,6 @@ module.exports = {
16
16
  notAllowed: '你没有权限登录该节点',
17
17
  notAppOwner: '你不是该应用的所有者',
18
18
  notSupported: '此应用不支持在当前节点安装',
19
- missingCredentialClaim: '请提供凭证',
20
19
  missingBlockletCredentialClaim: '请提供 Blocklet 凭证',
21
20
  missingChallenge: '凭证中缺少正确的随机因子',
22
21
  invalidCredentialHolder: '无效的凭证持有者',
@@ -66,4 +65,15 @@ module.exports = {
66
65
  noLauncherDid: '从服务器启动器信息中没有发现启动器',
67
66
  noNftDid: 'NFT DID 没有在服务器启动程序信息中找到',
68
67
  notAllowedAppUser: '您对此应用的访问权限已被撤销',
68
+ requestEmailKyc: '请提供经过验证的电子邮件证书',
69
+ receiveEmailKyc: '请签署文字以获得验证电子邮件证书',
70
+ requestPhoneKyc: '请提供电话验证的证书',
71
+ receivePhoneKyc: '请签署文字以获得验证电话证书',
72
+ missingPassport: '护照未提供',
73
+ missingEmailKyc: '未提供验证电子邮件证书',
74
+ emailAlreadyUsed: '电子邮件已被使用',
75
+ emailMismatch: '个人资料和已验证证书之间的电子邮件不匹配',
76
+ missingPhoneKyc: '未提供电话验证的证书',
77
+ phoneAlreadyUsed: '电话已经使用',
78
+ phoneMismatch: '个人资料和已验证证书之间的电话不匹配',
69
79
  };
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.16.32-beta-4d47ae7f",
6
+ "version": "1.16.32-beta-0593a408",
7
7
  "description": "Simple lib to manage auth in ABT Node",
8
8
  "main": "lib/index.js",
9
9
  "files": [
@@ -20,17 +20,17 @@
20
20
  "author": "linchen <linchen1987@foxmail.com> (http://github.com/linchen1987)",
21
21
  "license": "Apache-2.0",
22
22
  "dependencies": {
23
- "@abtnode/constant": "1.16.32-beta-4d47ae7f",
24
- "@abtnode/logger": "1.16.32-beta-4d47ae7f",
25
- "@abtnode/util": "1.16.32-beta-4d47ae7f",
23
+ "@abtnode/constant": "1.16.32-beta-0593a408",
24
+ "@abtnode/logger": "1.16.32-beta-0593a408",
25
+ "@abtnode/util": "1.16.32-beta-0593a408",
26
26
  "@arcblock/did": "1.18.135",
27
27
  "@arcblock/jwt": "^1.18.135",
28
- "@arcblock/nft-display": "^2.10.30",
28
+ "@arcblock/nft-display": "^2.10.32",
29
29
  "@arcblock/validator": "^1.18.135",
30
30
  "@arcblock/vc": "1.18.135",
31
- "@blocklet/constant": "1.16.32-beta-4d47ae7f",
32
- "@blocklet/meta": "1.16.32-beta-4d47ae7f",
33
- "@blocklet/sdk": "1.16.32-beta-4d47ae7f",
31
+ "@blocklet/constant": "1.16.32-beta-0593a408",
32
+ "@blocklet/meta": "1.16.32-beta-0593a408",
33
+ "@blocklet/sdk": "1.16.32-beta-0593a408",
34
34
  "@ocap/client": "^1.18.135",
35
35
  "@ocap/mcrypto": "1.18.135",
36
36
  "@ocap/util": "1.18.135",
@@ -50,5 +50,5 @@
50
50
  "devDependencies": {
51
51
  "jest": "^29.7.0"
52
52
  },
53
- "gitHead": "740b8032aa02e19b888bf6a257840089696613ef"
53
+ "gitHead": "5cca981049ad04018d8d361d9cdd33748f47d7d7"
54
54
  }
package/lib/auth.test.js DELETED
@@ -1,27 +0,0 @@
1
- const { messages } = require('./auth');
2
-
3
- const funcKeys = {
4
- invalidCredentialType: 1,
5
- invalidCredentialId: 1,
6
- passportRevoked: 1,
7
- passportStatusCheckFailed: 1,
8
- };
9
-
10
- describe('auth messages has key', () => {
11
- const keys = Object.keys(messages);
12
- // ensure all keys have values
13
- test('auth messages has key', () => {
14
- keys.forEach((key) => {
15
- const localMap = messages[key];
16
- expect(localMap).toBeDefined();
17
- ['en', 'zh', 'ja'].forEach((language) => {
18
- if (funcKeys[key]) {
19
- expect(typeof localMap[language]).toEqual('function');
20
- } else {
21
- expect(typeof localMap[language]).toEqual('string');
22
- expect(localMap[language].length > 0).toBeTruthy();
23
- }
24
- });
25
- });
26
- });
27
- });