@ossy/platform 3.9.0 → 3.11.1
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/README.md +2 -0
- package/package.json +8 -7
- package/src/index.js +3 -0
- package/src/proxy-internal.js +7 -2
- package/src/runtime.js +5 -3
- package/src/select-workspace.api.js +5 -1
- package/src/server.js +14 -3
- package/src/tasks/change-stream.js +11 -45
- package/src/test/flow-action.js +62 -0
- package/src/test/flow-action.spec.js +64 -0
- package/src/test/flow-context.js +20 -0
- package/src/test/flow-context.spec.js +14 -0
- package/src/test/flow-download.js +102 -0
- package/src/test/flow-download.spec.js +60 -0
- package/src/test/flow-files.js +83 -0
- package/src/test/flow-files.spec.js +69 -0
- package/src/test/flow-runner.js +428 -68
- package/src/test/test.util.js +37 -0
- package/src/user-app-settings.js +70 -9
- package/src/verify-sign-in-session.js +24 -0
package/src/user-app-settings.js
CHANGED
|
@@ -1,35 +1,96 @@
|
|
|
1
1
|
export const USER_SETTINGS_COOKIE = 'x-ossy-user-settings'
|
|
2
|
+
export const WORKSPACE_ID_COOKIE = 'x-ossy-workspace-id'
|
|
2
3
|
export const AUTH_COOKIE = 'auth'
|
|
3
4
|
|
|
4
5
|
const USER_SETTINGS_MAX_AGE_MS = 2147483647
|
|
5
6
|
const AUTH_MAX_AGE_MS = 14 * 24 * 60 * 60 * 1000
|
|
6
7
|
|
|
8
|
+
const signedCookieOpts = {
|
|
9
|
+
httpOnly: true,
|
|
10
|
+
signed: true,
|
|
11
|
+
path: '/',
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function settingsCookieExpires () {
|
|
15
|
+
return new Date(Date.now() + USER_SETTINGS_MAX_AGE_MS)
|
|
16
|
+
}
|
|
17
|
+
|
|
7
18
|
export function readUserAppSettings (req) {
|
|
8
19
|
return JSON.parse(req.signedCookies?.[USER_SETTINGS_COOKIE] || '{}')
|
|
9
20
|
}
|
|
10
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Active workspace id: dedicated cookie (select-workspace / sign-in) wins over the
|
|
24
|
+
* legacy field inside x-ossy-user-settings. Shell Sync PATCH must not clobber the
|
|
25
|
+
* dedicated cookie — see mergeUserAppSettingsCookie.
|
|
26
|
+
*/
|
|
27
|
+
export function readWorkspaceIdFromCookies (req) {
|
|
28
|
+
const dedicated = req.signedCookies?.[WORKSPACE_ID_COOKIE]
|
|
29
|
+
if (dedicated && typeof dedicated === 'string' && dedicated !== 'undefined') {
|
|
30
|
+
return dedicated
|
|
31
|
+
}
|
|
32
|
+
const fromSettings = readUserAppSettings(req).workspaceId
|
|
33
|
+
if (fromSettings && typeof fromSettings === 'string' && fromSettings !== 'undefined') {
|
|
34
|
+
return fromSettings
|
|
35
|
+
}
|
|
36
|
+
return undefined
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function setWorkspaceIdCookie (res, workspaceId) {
|
|
40
|
+
res.cookie(WORKSPACE_ID_COOKIE, String(workspaceId), {
|
|
41
|
+
...signedCookieOpts,
|
|
42
|
+
expires: settingsCookieExpires(),
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function clearWorkspaceIdCookie (res) {
|
|
47
|
+
const clearOpts = { httpOnly: true, path: '/' }
|
|
48
|
+
res.clearCookie(WORKSPACE_ID_COOKIE, clearOpts)
|
|
49
|
+
res.clearCookie(WORKSPACE_ID_COOKIE, { ...clearOpts, signed: true })
|
|
50
|
+
res.cookie(WORKSPACE_ID_COOKIE, '', {
|
|
51
|
+
...clearOpts,
|
|
52
|
+
signed: true,
|
|
53
|
+
expires: new Date(0),
|
|
54
|
+
})
|
|
55
|
+
}
|
|
56
|
+
|
|
11
57
|
export function mergeUserAppSettingsCookie (req, res, partial) {
|
|
12
|
-
const
|
|
58
|
+
const current = readUserAppSettings(req)
|
|
59
|
+
const updated = { ...current, ...partial }
|
|
60
|
+
const explicitWorkspaceId = Object.prototype.hasOwnProperty.call(partial, 'workspaceId')
|
|
61
|
+
|
|
62
|
+
if (explicitWorkspaceId) {
|
|
63
|
+
if (partial.workspaceId) {
|
|
64
|
+
setWorkspaceIdCookie(res, partial.workspaceId)
|
|
65
|
+
updated.workspaceId = partial.workspaceId
|
|
66
|
+
} else {
|
|
67
|
+
clearWorkspaceIdCookie(res)
|
|
68
|
+
delete updated.workspaceId
|
|
69
|
+
}
|
|
70
|
+
} else {
|
|
71
|
+
// Shell Sync and similar patches omit workspaceId. Never rewrite it from the
|
|
72
|
+
// request's cookie snapshot — an in-flight PATCH started before select-workspace
|
|
73
|
+
// would otherwise clobber the newly selected workspace (Switch workspace e2e flake).
|
|
74
|
+
delete updated.workspaceId
|
|
75
|
+
}
|
|
76
|
+
|
|
13
77
|
res.cookie(USER_SETTINGS_COOKIE, JSON.stringify(updated), {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
path: '/',
|
|
17
|
-
expires: new Date(Date.now() + USER_SETTINGS_MAX_AGE_MS),
|
|
78
|
+
...signedCookieOpts,
|
|
79
|
+
expires: settingsCookieExpires(),
|
|
18
80
|
})
|
|
19
81
|
}
|
|
20
82
|
|
|
21
83
|
export function clearWorkspaceFromUserAppSettings (req, res) {
|
|
22
84
|
const settings = readUserAppSettings(req)
|
|
23
85
|
delete settings.workspaceId
|
|
86
|
+
clearWorkspaceIdCookie(res)
|
|
24
87
|
if (Object.keys(settings).length === 0) {
|
|
25
88
|
res.clearCookie(USER_SETTINGS_COOKIE, { httpOnly: true, signed: true, path: '/' })
|
|
26
89
|
return
|
|
27
90
|
}
|
|
28
91
|
res.cookie(USER_SETTINGS_COOKIE, JSON.stringify(settings), {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
path: '/',
|
|
32
|
-
expires: new Date(Date.now() + USER_SETTINGS_MAX_AGE_MS),
|
|
92
|
+
...signedCookieOpts,
|
|
93
|
+
expires: settingsCookieExpires(),
|
|
33
94
|
})
|
|
34
95
|
}
|
|
35
96
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ActionService } from './actions/action.service.js'
|
|
2
|
+
import { mergeUserAppSettingsCookie, setAuthCookie } from './user-app-settings.js'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Set auth (and optional single-workspace default) cookies after verify-sign-in.
|
|
6
|
+
*
|
|
7
|
+
* @param {import('express').Request} req
|
|
8
|
+
* @param {import('express').Response} res
|
|
9
|
+
* @param {{ sub: string, token: string }} session
|
|
10
|
+
*/
|
|
11
|
+
export async function applyVerifySignInSessionCookies (req, res, { sub, token }) {
|
|
12
|
+
setAuthCookie(res, token)
|
|
13
|
+
try {
|
|
14
|
+
const workspaces = await ActionService.invoke('@ossy/workspaces/actions/list', {
|
|
15
|
+
payload: { userId: sub },
|
|
16
|
+
req,
|
|
17
|
+
})
|
|
18
|
+
if (workspaces.length === 1) {
|
|
19
|
+
mergeUserAppSettingsCookie(req, res, { workspaceId: workspaces[0].id })
|
|
20
|
+
}
|
|
21
|
+
} catch {
|
|
22
|
+
// Cookie for the session is enough; workspace default is best-effort.
|
|
23
|
+
}
|
|
24
|
+
}
|