@abtnode/blocklet-services 1.16.52-beta-20250918-114058-f5efc10b → 1.16.52-beta-20250924-093428-bd3f0d8c

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/api/index.js CHANGED
@@ -88,7 +88,7 @@ const createOpenComponentRoutes = require('./routes/opencomponent');
88
88
  const createOpenEmbedRoutes = require('./routes/openembed');
89
89
  const createAccessKeyRoutes = require('./routes/access-key');
90
90
  const checkRunning = require('./middlewares/check-running');
91
- const launcherLogin = require('./middlewares/launcher-login');
91
+ const { launcherLogin } = require('./middlewares/launcher-login');
92
92
  const { checkMemberPermission, checkGuestPermission } = require('./middlewares/check-permission');
93
93
  const ensureBlocklet = require('./middlewares/ensure-blocklet');
94
94
  const proxyToDaemon = require('./middlewares/proxy-to-daemon');
@@ -9,6 +9,94 @@ const { createTokenFn } = require('../util');
9
9
  const initJwt = require('../libs/jwt');
10
10
  const logger = require('../libs/logger')('blocklet-services:launcher-login');
11
11
 
12
+ const doLauncherLogin = async (req, token, blocklet, node, options) => {
13
+ const decoded = JWT.decode(token);
14
+ const info = await req.getNodeInfo();
15
+
16
+ const isSameLauncher = isSameDid(decoded.iss, info.registerInfo?.appId);
17
+ const isSameOwner = isSameDid(decoded.oid, blocklet.settings?.owner?.did);
18
+ const isSameLauncherSessionId = decoded.lid === blocklet.controller.launcherSessionId;
19
+ const isSameBlocklet = [blocklet.appDid, blocklet.appPid].includes(decoded.aid);
20
+
21
+ logger.debug('Launcher login check', {
22
+ isSameLauncher,
23
+ isSameOwner,
24
+ isSameLauncherSessionId,
25
+ isSameBlocklet,
26
+ decoded,
27
+ owner: blocklet.settings?.owner,
28
+ launcher: info.registerInfo,
29
+ controller: blocklet.controller,
30
+ appDids: [blocklet.appDid, blocklet.appPid],
31
+ });
32
+
33
+ if (isSameLauncher && isSameOwner && isSameLauncherSessionId && isSameBlocklet) {
34
+ const verified = await JWT.verify(token, info.registerInfo?.appPk);
35
+ if (verified) {
36
+ const user = await node.getUser({
37
+ teamDid: blocklet.appPid,
38
+ user: { did: decoded.oid },
39
+ options: { enableConnectedAccount: true },
40
+ });
41
+ if (user?.approved) {
42
+ const { secret } = await req.getBlockletInfo();
43
+ const { createSessionToken } = initJwt(node, options);
44
+ const createToken = createTokenFn(createSessionToken);
45
+ const { sessionToken, refreshToken } = createToken(
46
+ user.did,
47
+ {
48
+ secret,
49
+ role: 'owner',
50
+ fullName: user.fullName,
51
+ provider: user.sourceProvider,
52
+ walletOS: user.walletOS,
53
+ emailVerified: !!user?.emailVerified,
54
+ phoneVerified: !!user?.phoneVerified,
55
+ elevated: true,
56
+ },
57
+ blocklet.settings?.session || {}
58
+ );
59
+
60
+ const visitorId = decoded.vid || req.cookies?.vid || generateId();
61
+
62
+ logger.info('done auto login for launcher user', {
63
+ appPid: blocklet.appPid,
64
+ userDid: user.did,
65
+ visitorId,
66
+ });
67
+
68
+ await node.upsertUserSession({
69
+ teamDid: blocklet.appPid,
70
+ userDid: user.did,
71
+ visitorId,
72
+ appPid: blocklet.appPid,
73
+ passportId: null,
74
+ status: 'online',
75
+ ua: req.get('user-agent'),
76
+ lastLoginIp: getRequestIP(req),
77
+ extra: {
78
+ walletOS: user.walletOS,
79
+ device: getDeviceData({ req }),
80
+ },
81
+ locale: req.blockletLocale,
82
+ origin: await getOrigin({ req }),
83
+ });
84
+
85
+ return {
86
+ sessionToken,
87
+ refreshToken,
88
+ visitorId,
89
+ };
90
+ }
91
+ logger.warn('Launcher login failed, user is revoked', { userDid: user?.did });
92
+ } else {
93
+ logger.warn('Launcher login failed, token is invalid', { token, verified });
94
+ }
95
+ }
96
+
97
+ return null;
98
+ };
99
+
12
100
  // auto login from authenticated launcher users: will skip if user is already logged in
13
101
  const launcherLogin = (node, options) => async (req, res, next) => {
14
102
  if (!req.query.__lt) {
@@ -27,94 +115,18 @@ const launcherLogin = (node, options) => async (req, res, next) => {
27
115
 
28
116
  try {
29
117
  const token = req.query.__lt;
30
- const decoded = JWT.decode(token);
31
- const info = await req.getNodeInfo();
32
-
33
- const isSameLauncher = isSameDid(decoded.iss, info.registerInfo?.appId);
34
- const isSameOwner = isSameDid(decoded.oid, blocklet.settings?.owner?.did);
35
- const isSameLauncherSessionId = decoded.lid === blocklet.controller.launcherSessionId;
36
- const isSameBlocklet = [blocklet.appDid, blocklet.appPid].includes(decoded.aid);
37
-
38
- logger.debug('Launcher login check', {
39
- isSameLauncher,
40
- isSameOwner,
41
- isSameLauncherSessionId,
42
- isSameBlocklet,
43
- decoded,
44
- owner: blocklet.settings?.owner,
45
- launcher: info.registerInfo,
46
- controller: blocklet.controller,
47
- appDids: [blocklet.appDid, blocklet.appPid],
48
- });
49
-
50
- if (isSameLauncher && isSameOwner && isSameLauncherSessionId && isSameBlocklet) {
51
- const verified = await JWT.verify(token, info.registerInfo?.appPk);
52
- if (verified) {
53
- const user = await node.getUser({
54
- teamDid: blocklet.appPid,
55
- user: { did: decoded.oid },
56
- options: { enableConnectedAccount: true },
57
- });
58
- if (user?.approved) {
59
- const { secret } = await req.getBlockletInfo();
60
- const { createSessionToken } = initJwt(node, options);
61
- const createToken = createTokenFn(createSessionToken);
62
- const result = createToken(
63
- user.did,
64
- {
65
- secret,
66
- role: 'owner',
67
- fullName: user.fullName,
68
- provider: user.sourceProvider,
69
- walletOS: user.walletOS,
70
- emailVerified: !!user?.emailVerified,
71
- phoneVerified: !!user?.phoneVerified,
72
- elevated: true,
73
- },
74
- blocklet.settings?.session || {}
75
- );
76
-
77
- const visitorId = decoded.vid || req.cookies?.vid || generateId();
78
-
79
- logger.info('done auto login for launcher user', {
80
- appPid: blocklet.appPid,
81
- userDid: user.did,
82
- visitorId,
83
- });
84
-
85
- await node.upsertUserSession({
86
- teamDid: blocklet.appPid,
87
- userDid: user.did,
88
- visitorId,
89
- appPid: blocklet.appPid,
90
- passportId: null,
91
- status: 'online',
92
- ua: req.get('user-agent'),
93
- lastLoginIp: getRequestIP(req),
94
- extra: {
95
- walletOS: user.walletOS,
96
- device: getDeviceData({ req }),
97
- },
98
- locale: req.blockletLocale,
99
- origin: await getOrigin({ req }),
100
- });
101
-
102
- res.cookie('login_token', result.sessionToken, {
103
- maxAge: 24 * 60 * 60 * 1000,
104
- secure: true,
105
- sameSite: 'lax',
106
- });
107
- res.cookie('vid', visitorId, {
108
- maxAge: 365 * 24 * 60 * 60 * 1000,
109
- secure: true,
110
- sameSite: 'lax',
111
- });
112
- } else {
113
- logger.warn('Launcher login failed, user is revoked', { userDid: user?.did });
114
- }
115
- } else {
116
- logger.warn('Launcher login failed, token is invalid', { token, verified });
117
- }
118
+ const result = await doLauncherLogin(req, token, blocklet, node, options);
119
+ if (result) {
120
+ res.cookie('login_token', result.sessionToken, {
121
+ maxAge: 24 * 60 * 60 * 1000,
122
+ secure: true,
123
+ sameSite: 'lax',
124
+ });
125
+ res.cookie('vid', result.visitorId, {
126
+ maxAge: 365 * 24 * 60 * 60 * 1000,
127
+ secure: true,
128
+ sameSite: 'lax',
129
+ });
118
130
  }
119
131
  } catch (err) {
120
132
  logger.error('Failed to attach launcher token', { error: err });
@@ -123,4 +135,7 @@ const launcherLogin = (node, options) => async (req, res, next) => {
123
135
  return next();
124
136
  };
125
137
 
126
- module.exports = launcherLogin;
138
+ module.exports = {
139
+ launcherLogin,
140
+ doLauncherLogin,
141
+ };
@@ -51,6 +51,7 @@ const { sendToUser } = require('../libs/notification');
51
51
  const { createEmailLimiter } = require('../services/kyc');
52
52
  const cache = require('../cache');
53
53
  const { ensureUserExists, ensureUserEnabled, t } = require('../util/check-user');
54
+ const { doLauncherLogin } = require('../middlewares/launcher-login');
54
55
 
55
56
  const validateUser = (user) => {
56
57
  try {
@@ -870,6 +871,36 @@ module.exports = {
870
871
  });
871
872
  });
872
873
 
874
+ // Used by ArcSphere to login by launcher token
875
+ server.post(`${prefixApi}/loginByLauncher`, async (req, res) => {
876
+ const { token } = req.body;
877
+ if (!token) {
878
+ throw new CustomError(400, 'Launcher token is required');
879
+ }
880
+
881
+ const blocklet = await req.getBlocklet();
882
+ if (!blocklet.controller) {
883
+ logger.debug('Launcher login is not supported for this blocklet', { blockletDid: blocklet.appDid });
884
+ throw new CustomError(400, 'Launcher login is not supported for this blocklet');
885
+ }
886
+
887
+ try {
888
+ const result = await doLauncherLogin(req, token, blocklet, node, options);
889
+ if (result) {
890
+ res.json({
891
+ sessionToken: result.sessionToken,
892
+ refreshToken: result.refreshToken,
893
+ visitorId: result.visitorId,
894
+ });
895
+ } else {
896
+ throw new CustomError(400, 'Failed to login by launcher: not matched');
897
+ }
898
+ } catch (err) {
899
+ logger.error('Failed to login by launcher', { error: err });
900
+ throw new CustomError(500, 'Failed to login by launcher: internal error');
901
+ }
902
+ });
903
+
873
904
  server.post(`${prefixApi}/checkUser`, async (req, res) => {
874
905
  const { users = [], sourceAppPid } = req.body;
875
906
  const { error } = checkUserSchema.validate({
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "1.16.52-beta-20250918-114058-f5efc10b",
6
+ "version": "1.16.52-beta-20250924-093428-bd3f0d8c",
7
7
  "description": "Provide unified services for every blocklet",
8
8
  "main": "api/index.js",
9
9
  "files": [
@@ -34,17 +34,17 @@
34
34
  "author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
35
35
  "license": "Apache-2.0",
36
36
  "dependencies": {
37
- "@abtnode/analytics": "1.16.52-beta-20250918-114058-f5efc10b",
38
- "@abtnode/auth": "1.16.52-beta-20250918-114058-f5efc10b",
39
- "@abtnode/connect-storage": "1.16.52-beta-20250918-114058-f5efc10b",
40
- "@abtnode/constant": "1.16.52-beta-20250918-114058-f5efc10b",
41
- "@abtnode/core": "1.16.52-beta-20250918-114058-f5efc10b",
42
- "@abtnode/cron": "1.16.52-beta-20250918-114058-f5efc10b",
43
- "@abtnode/db-cache": "1.16.52-beta-20250918-114058-f5efc10b",
44
- "@abtnode/logger": "1.16.52-beta-20250918-114058-f5efc10b",
45
- "@abtnode/models": "1.16.52-beta-20250918-114058-f5efc10b",
46
- "@abtnode/router-templates": "1.16.52-beta-20250918-114058-f5efc10b",
47
- "@abtnode/util": "1.16.52-beta-20250918-114058-f5efc10b",
37
+ "@abtnode/analytics": "1.16.52-beta-20250924-093428-bd3f0d8c",
38
+ "@abtnode/auth": "1.16.52-beta-20250924-093428-bd3f0d8c",
39
+ "@abtnode/connect-storage": "1.16.52-beta-20250924-093428-bd3f0d8c",
40
+ "@abtnode/constant": "1.16.52-beta-20250924-093428-bd3f0d8c",
41
+ "@abtnode/core": "1.16.52-beta-20250924-093428-bd3f0d8c",
42
+ "@abtnode/cron": "1.16.52-beta-20250924-093428-bd3f0d8c",
43
+ "@abtnode/db-cache": "1.16.52-beta-20250924-093428-bd3f0d8c",
44
+ "@abtnode/logger": "1.16.52-beta-20250924-093428-bd3f0d8c",
45
+ "@abtnode/models": "1.16.52-beta-20250924-093428-bd3f0d8c",
46
+ "@abtnode/router-templates": "1.16.52-beta-20250924-093428-bd3f0d8c",
47
+ "@abtnode/util": "1.16.52-beta-20250924-093428-bd3f0d8c",
48
48
  "@arcblock/did": "1.24.0",
49
49
  "@arcblock/did-connect-js": "1.24.0",
50
50
  "@arcblock/did-ext": "1.24.0",
@@ -54,18 +54,18 @@
54
54
  "@arcblock/jwt": "1.24.0",
55
55
  "@arcblock/validator": "1.24.0",
56
56
  "@arcblock/ws": "1.24.0",
57
- "@blocklet/constant": "1.16.52-beta-20250918-114058-f5efc10b",
57
+ "@blocklet/constant": "1.16.52-beta-20250924-093428-bd3f0d8c",
58
58
  "@blocklet/dbhub": "^0.2.9",
59
- "@blocklet/env": "1.16.52-beta-20250918-114058-f5efc10b",
59
+ "@blocklet/env": "1.16.52-beta-20250924-093428-bd3f0d8c",
60
60
  "@blocklet/error": "^0.2.5",
61
61
  "@blocklet/form-builder": "^0.1.12",
62
62
  "@blocklet/form-collector": "^0.1.8",
63
- "@blocklet/images": "1.16.52-beta-20250918-114058-f5efc10b",
64
- "@blocklet/js-sdk": "1.16.52-beta-20250918-114058-f5efc10b",
65
- "@blocklet/meta": "1.16.52-beta-20250918-114058-f5efc10b",
66
- "@blocklet/rate-limit": "1.16.52-beta-20250918-114058-f5efc10b",
67
- "@blocklet/sdk": "1.16.52-beta-20250918-114058-f5efc10b",
68
- "@blocklet/server-js": "1.16.52-beta-20250918-114058-f5efc10b",
63
+ "@blocklet/images": "1.16.52-beta-20250924-093428-bd3f0d8c",
64
+ "@blocklet/js-sdk": "1.16.52-beta-20250924-093428-bd3f0d8c",
65
+ "@blocklet/meta": "1.16.52-beta-20250924-093428-bd3f0d8c",
66
+ "@blocklet/rate-limit": "1.16.52-beta-20250924-093428-bd3f0d8c",
67
+ "@blocklet/sdk": "1.16.52-beta-20250924-093428-bd3f0d8c",
68
+ "@blocklet/server-js": "1.16.52-beta-20250924-093428-bd3f0d8c",
69
69
  "@blocklet/theme": "^3.1.41",
70
70
  "@blocklet/theme-builder": "0.4.6",
71
71
  "@blocklet/uploader-server": "^0.2.11",
@@ -125,7 +125,7 @@
125
125
  "whatwg-url": "14.0.0"
126
126
  },
127
127
  "devDependencies": {
128
- "@abtnode/ux": "1.16.52-beta-20250918-114058-f5efc10b",
128
+ "@abtnode/ux": "1.16.52-beta-20250924-093428-bd3f0d8c",
129
129
  "@arcblock/bridge": "^3.1.41",
130
130
  "@arcblock/did-connect-react": "^3.1.41",
131
131
  "@arcblock/icons": "^3.1.41",
@@ -135,7 +135,7 @@
135
135
  "@blocklet/did-space-react": "^1.1.24",
136
136
  "@blocklet/launcher-layout": "^3.1.41",
137
137
  "@blocklet/payment-react": "^1.20.11",
138
- "@blocklet/tracker": "1.16.52-beta-20250918-114058-f5efc10b",
138
+ "@blocklet/tracker": "1.16.52-beta-20250924-093428-bd3f0d8c",
139
139
  "@blocklet/ui-react": "^3.1.41",
140
140
  "@blocklet/uploader": "^0.2.11",
141
141
  "@emotion/react": "^11.14.0",
@@ -215,5 +215,5 @@
215
215
  "url": "https://github.com/ArcBlock/blocklet-server/issues",
216
216
  "email": "shijun@arcblock.io"
217
217
  },
218
- "gitHead": "0ca3d74cc1b1c5e0f1b1ab8322c38db67d674392"
218
+ "gitHead": "208aa87c8e036c9ff5d40e7f6d7a5e24bcc57833"
219
219
  }