anbaric-cloud-hosting 1.18.1 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "anbaric-cloud-hosting",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.19.0",
|
|
4
4
|
"description": "Anbaric Cloud hosting service: Postgres-backed job persistence and queuing exposed over an HTTP API",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "chris@anbaric.ai",
|
|
@@ -18,17 +18,17 @@
|
|
|
18
18
|
"@aws-sdk/client-s3": "^3.1110.0",
|
|
19
19
|
"@aws-sdk/client-secrets-manager": "^3.700.0",
|
|
20
20
|
"@aws-sdk/client-servicediscovery": "^3.1110.0",
|
|
21
|
-
"anbaric-data-store": "^1.
|
|
22
|
-
"anbaric-plugins": "^1.
|
|
23
|
-
"anbaric-tsapi": "^1.
|
|
21
|
+
"anbaric-data-store": "^1.19.0",
|
|
22
|
+
"anbaric-plugins": "^1.19.0",
|
|
23
|
+
"anbaric-tsapi": "^1.19.0",
|
|
24
24
|
"esbuild": "^0.28.2",
|
|
25
25
|
"pg": "^8.16.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"@types/node": "^26.2.0",
|
|
29
29
|
"@types/pg": "^8.15.0",
|
|
30
|
-
"anbaric-impl-cloud": "^1.
|
|
31
|
-
"anbaric-state-machine": "^1.
|
|
30
|
+
"anbaric-impl-cloud": "^1.19.0",
|
|
31
|
+
"anbaric-state-machine": "^1.19.0",
|
|
32
32
|
"tsx": "^4.20.0",
|
|
33
33
|
"typescript": "^7.0.2"
|
|
34
34
|
},
|
|
@@ -89,6 +89,7 @@ class DockerBuildLayer extends BaseBuildLayer {
|
|
|
89
89
|
"--env", "ANBARIC_JSON_STORE_TYPE=cloud",
|
|
90
90
|
"--env", "ANBARIC_SECRET_STORE_TYPE=cloud",
|
|
91
91
|
"--env", "ANBARIC_AUDITOR_TYPE=cloud",
|
|
92
|
+
"--env", "ANBARIC_SESSION_RESOLVER_TYPE=cloud",
|
|
92
93
|
"--env", `ANBARIC_CONSUMER_PORT=${deployment.consumerPort}`,
|
|
93
94
|
"--env", `ANBARIC_CONSUMER_URL=http://${container}:${deployment.consumerPort}`,
|
|
94
95
|
...sqlEnv,
|
|
@@ -178,6 +178,7 @@ class FargateBuildLayer extends BaseBuildLayer {
|
|
|
178
178
|
{ name: "ANBARIC_JSON_STORE_TYPE", value: "cloud" },
|
|
179
179
|
{ name: "ANBARIC_SECRET_STORE_TYPE", value: "cloud" },
|
|
180
180
|
{ name: "ANBARIC_AUDITOR_TYPE", value: "cloud" },
|
|
181
|
+
{ name: "ANBARIC_SESSION_RESOLVER_TYPE", value: "cloud" },
|
|
181
182
|
{ name: "ANBARIC_CONSUMER_PORT", value: String(deployment.consumerPort) },
|
|
182
183
|
{ name: "ANBARIC_CONSUMER_URL", value: `http://${deployment.appHost}:${deployment.consumerPort}` },
|
|
183
184
|
...(this.options.servicesUrl ? [{ name: "ANBARIC_SERVICES_URL", value: this.options.servicesUrl }] : []),
|
|
@@ -11,6 +11,7 @@ import {AppsHandler} from "./handlers/AppsHandler";
|
|
|
11
11
|
import {AuditsHandler} from "./handlers/AuditsHandler";
|
|
12
12
|
import {AuthorizeCliHandler} from "./handlers/auth/AuthorizeCliHandler";
|
|
13
13
|
import {KeysHandler} from "./handlers/auth/KeysHandler";
|
|
14
|
+
import {SessionsHandler} from "./handlers/auth/SessionsHandler";
|
|
14
15
|
import {WhoamiHandler} from "./handlers/auth/WhoamiHandler";
|
|
15
16
|
import {ConsumersHandler} from "./handlers/ConsumersHandler";
|
|
16
17
|
import {DocumentsHandler} from "./handlers/DocumentsHandler";
|
|
@@ -60,12 +61,14 @@ class HostingServer {
|
|
|
60
61
|
const documents = documentStoreFor && new DocumentsHandler(documentStoreFor);
|
|
61
62
|
const secrets = secretStore && new SecretsHandler(secretStore);
|
|
62
63
|
const audits = auditRecords && new AuditsHandler(auditRecords);
|
|
64
|
+
const sessions = new SessionsHandler();
|
|
63
65
|
|
|
64
66
|
const publicRouter = new Router();
|
|
65
67
|
publicRouter.registerRoot(pages);
|
|
66
68
|
publicRouter.register("ping", ping);
|
|
67
69
|
if (plugins.length > 0) publicRouter.registerApi("plugins", new PluginsHandler(plugins));
|
|
68
70
|
publicRouter.registerApi("whoami", new WhoamiHandler());
|
|
71
|
+
publicRouter.registerApi("sessions", sessions);
|
|
69
72
|
publicRouter.registerApi("jobs", jobs);
|
|
70
73
|
publicRouter.registerApi("queue", queueHandler);
|
|
71
74
|
publicRouter.registerApi("consumers", consumers);
|
|
@@ -84,6 +87,7 @@ class HostingServer {
|
|
|
84
87
|
|
|
85
88
|
const internalRouter = new Router();
|
|
86
89
|
internalRouter.register("ping", ping);
|
|
90
|
+
internalRouter.registerApi("sessions", sessions);
|
|
87
91
|
internalRouter.registerApi("jobs", jobs);
|
|
88
92
|
internalRouter.registerApi("queue", queueHandler);
|
|
89
93
|
internalRouter.registerApi("consumers", consumers);
|
|
@@ -113,7 +117,7 @@ class HostingServer {
|
|
|
113
117
|
|
|
114
118
|
async close() : Promise<void> {
|
|
115
119
|
if (this.internalServer.listening) await this.internalServer.close();
|
|
116
|
-
await this.publicServer.close();
|
|
120
|
+
if (this.publicServer.listening) await this.publicServer.close();
|
|
117
121
|
}
|
|
118
122
|
|
|
119
123
|
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import {SessionSigner} from "../../../auth/SessionSigner";
|
|
2
|
+
import {Request} from "../../Request";
|
|
3
|
+
import {RequestHandler} from "../../RequestHandler";
|
|
4
|
+
|
|
5
|
+
/* Resolves a platform session token into the user's identity, for apps that
|
|
6
|
+
cannot verify it themselves (the signing secret is platform only). The token
|
|
7
|
+
travels in the body - it is the credential - so this needs no session
|
|
8
|
+
middleware and is safe on the internal, app-facing router. */
|
|
9
|
+
class SessionsHandler implements RequestHandler {
|
|
10
|
+
|
|
11
|
+
constructor(private sessionSigner : SessionSigner = new SessionSigner()) {}
|
|
12
|
+
|
|
13
|
+
async handle(request : Request) : Promise<void> {
|
|
14
|
+
if (request.method === "POST" && request.id === "resolve" && !request.subresource) {
|
|
15
|
+
return this.resolve(request);
|
|
16
|
+
}
|
|
17
|
+
request.notFound();
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
private async resolve(request : Request) : Promise<void> {
|
|
21
|
+
const body = await request.body() as { session? : string } | undefined;
|
|
22
|
+
const resolved = this.sessionSigner.verify(body?.session);
|
|
23
|
+
if (!resolved) return request.reply(401, { error: "Invalid or expired session" });
|
|
24
|
+
|
|
25
|
+
const [user, tenant] = resolved;
|
|
26
|
+
request.reply(200, {
|
|
27
|
+
id: user.id,
|
|
28
|
+
roles: user.roles.map(role => role.id),
|
|
29
|
+
tenant: tenant?.id,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export { SessionsHandler }
|