@sasjs/api 0.13.0 → 0.14.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/build/browser.js CHANGED
@@ -1,4 +1,4 @@
1
- /* @sasjs/api 0.13.0 - the SASjs Server API, for a service worker. https://github.com/sasjs/api */
1
+ /* @sasjs/api 0.14.1 - the SASjs Server API, for a service worker. https://github.com/sasjs/api */
2
2
  "use strict";
3
3
  var SASjsApi = (() => {
4
4
  var __defProp = Object.defineProperty;
@@ -28,6 +28,7 @@ var SASjsApi = (() => {
28
28
  CODE_CORPUS: () => CODE_CORPUS,
29
29
  DEFAULT_GRANTABLE_ROUTES: () => DEFAULT_GRANTABLE_ROUTES,
30
30
  DEFAULT_IDENTITY: () => DEFAULT_IDENTITY,
31
+ DEFAULT_SESSIONS: () => DEFAULT_SESSIONS,
31
32
  DEPLOY_CORPUS: () => DEPLOY_CORPUS,
32
33
  DEPLOY_LIMITS: () => DEPLOY_LIMITS,
33
34
  DEPLOY_PAYLOAD_BYTES: () => DEPLOY_PAYLOAD_BYTES,
@@ -36,8 +37,10 @@ var SASjsApi = (() => {
36
37
  HANDLED_ROUTES: () => HANDLED_ROUTES,
37
38
  IDENTITY_CORPUS: () => IDENTITY_CORPUS,
38
39
  IDENTITY_FORMAT: () => IDENTITY_FORMAT,
40
+ MemoryAppStreamRegistry: () => MemoryAppStreamRegistry,
39
41
  MemoryDriveStore: () => MemoryDriveStore,
40
42
  MemoryIdentityStore: () => MemoryIdentityStore,
43
+ MemorySessionHost: () => MemorySessionHost,
41
44
  OVERLAY: () => OVERLAY,
42
45
  PROVIDER_MANAGED: () => PROVIDER_MANAGED,
43
46
  RECORD_CORPUS: () => RECORD_CORPUS,
@@ -51,6 +54,7 @@ var SASjsApi = (() => {
51
54
  createDriveService: () => createDriveService,
52
55
  createIdentityService: () => createIdentityService,
53
56
  createRecordService: () => createRecordService,
57
+ createSessionService: () => createSessionService,
54
58
  decodeBase64: () => decodeBase64,
55
59
  deployTree: () => deployTree,
56
60
  dirname: () => dirname,
@@ -68,7 +72,8 @@ var SASjsApi = (() => {
68
72
  runCase: () => runCase,
69
73
  sanitiseDisplayName: () => sanitiseDisplayName,
70
74
  servicesFor: () => servicesFor,
71
- topLevelRouteFor: () => topLevelRouteFor
75
+ topLevelRouteFor: () => topLevelRouteFor,
76
+ unpublishAppStream: () => unpublishAppStream
72
77
  });
73
78
 
74
79
  // src/types.ts
@@ -1007,7 +1012,7 @@ var SASjsApi = (() => {
1007
1012
  },
1008
1013
  {
1009
1014
  status: 404,
1010
- description: "No such app stream entry"
1015
+ description: "No app is published at that folder"
1011
1016
  }
1012
1017
  ]
1013
1018
  },
@@ -1641,6 +1646,10 @@ var SASjsApi = (() => {
1641
1646
  {
1642
1647
  status: 200,
1643
1648
  description: "Ok"
1649
+ },
1650
+ {
1651
+ status: 401,
1652
+ description: "Administrator access is required"
1644
1653
  }
1645
1654
  ]
1646
1655
  },
@@ -2808,7 +2817,7 @@ var SASjsApi = (() => {
2808
2817
  throw new ApiError(400, '"streamServiceName" is required');
2809
2818
  if (!body.appLoc) throw new ApiError(400, '"appLoc" is required');
2810
2819
  if (!await registry.unpublish(body.appLoc))
2811
- throw new ApiError(404, "No such app stream entry.");
2820
+ throw new ApiError(404, "No app is published at that folder.");
2812
2821
  return { status: "success" };
2813
2822
  };
2814
2823
  var MemoryAppStreamRegistry = class {
@@ -3629,7 +3638,8 @@ var SASjsApi = (() => {
3629
3638
  return groupDetails(updated);
3630
3639
  },
3631
3640
  async listAuthorizedRoutes(caller) {
3632
- await requireCaller(store, caller);
3641
+ const reader = await requireCaller(store, caller);
3642
+ if (!reader.isAdmin) throw new ApiError(401, "Admin account required");
3633
3643
  return { paths: [...grantableRoutes] };
3634
3644
  },
3635
3645
  async myAuthorizedRoutes(caller) {
@@ -5008,7 +5018,7 @@ var SASjsApi = (() => {
5008
5018
  subject: SUBJECT,
5009
5019
  body: { streamServiceName: "myApp", appLoc: "/Public/not-an-app" }
5010
5020
  },
5011
- expect: { status: 404, error: "No such app stream entry." }
5021
+ expect: { status: 404, error: "No app is published at that folder." }
5012
5022
  },
5013
5023
  // ------------------------------------------- the uploaded-archive route
5014
5024
  // The archive is expanded by the host, so what arrives here is the same tree
@@ -5236,6 +5246,112 @@ var SASjsApi = (() => {
5236
5246
  }
5237
5247
  ];
5238
5248
 
5249
+ // src/session/service.ts
5250
+ var createSessionService = (store, host) => {
5251
+ const notFound2 = (id) => `Session with ID '${id}' was not found.`;
5252
+ const visible = async (caller, id) => {
5253
+ if (!caller) throw new ApiError(401, "Unauthorized");
5254
+ const reader = await store.userById(
5255
+ caller.userId
5256
+ );
5257
+ if (!reader || !reader.isActive) throw new ApiError(401, "Unauthorized");
5258
+ const session = await host.session(id);
5259
+ if (!session) throw new ApiError(404, notFound2(id));
5260
+ const owner = session.owner;
5261
+ if (owner !== reader.uid && owner !== reader.username && !reader.isAdmin)
5262
+ throw new ApiError(404, notFound2(id));
5263
+ return session;
5264
+ };
5265
+ return {
5266
+ async summary(caller, id) {
5267
+ const session = await visible(caller, id);
5268
+ return session.summary;
5269
+ },
5270
+ async state(caller, id) {
5271
+ await visible(caller, id);
5272
+ const state = await host.state(id);
5273
+ if (!state) throw new ApiError(404, notFound2(id));
5274
+ return state;
5275
+ },
5276
+ async log(caller, id) {
5277
+ await visible(caller, id);
5278
+ const log = await host.log(id);
5279
+ if (log === void 0) throw new ApiError(404, notFound2(id));
5280
+ return log;
5281
+ },
5282
+ async output(caller, id) {
5283
+ await visible(caller, id);
5284
+ const output = await host.output(id);
5285
+ if (output === void 0) throw new ApiError(404, notFound2(id));
5286
+ return output;
5287
+ }
5288
+ };
5289
+ };
5290
+
5291
+ // src/session/memory-host.ts
5292
+ var DEFAULT_SESSIONS = {
5293
+ "sess-admin": {
5294
+ owner: "user-admin",
5295
+ summary: {
5296
+ sessionId: "sess-admin",
5297
+ state: "completed",
5298
+ pid: 4242,
5299
+ creationTimeStamp: "2026-11-07T09:00:00.000Z",
5300
+ deathTimeStamp: "2026-11-07T09:00:04.000Z",
5301
+ expiresAfterMins: 60
5302
+ }
5303
+ },
5304
+ "sess-restricted": {
5305
+ owner: "user-restricted",
5306
+ summary: {
5307
+ sessionId: "sess-restricted",
5308
+ state: "running",
5309
+ pid: 4243,
5310
+ creationTimeStamp: "2026-11-07T09:05:00.000Z"
5311
+ }
5312
+ },
5313
+ "sess-silent": {
5314
+ owner: "user-admin",
5315
+ summary: {
5316
+ sessionId: "sess-silent",
5317
+ state: "running",
5318
+ pid: 4244,
5319
+ creationTimeStamp: "2026-11-07T09:10:00.000Z"
5320
+ }
5321
+ }
5322
+ };
5323
+ var STATES = {
5324
+ "sess-admin": { state: "completed", pid: 4242, lineCount: 12 },
5325
+ "sess-restricted": { state: "running", pid: 4243, lineCount: 3 }
5326
+ };
5327
+ var LOGS = {
5328
+ "sess-admin": "NOTE: session started\nNOTE: session completed\n",
5329
+ "sess-restricted": "NOTE: session started\n",
5330
+ "sess-silent": ""
5331
+ };
5332
+ var OUTPUTS = {
5333
+ "sess-admin": "<html><body>42</body></html>",
5334
+ "sess-restricted": "",
5335
+ "sess-silent": ""
5336
+ };
5337
+ var MemorySessionHost = class {
5338
+ constructor(sessions = DEFAULT_SESSIONS) {
5339
+ this.sessions = sessions;
5340
+ }
5341
+ async session(id) {
5342
+ return this.sessions[id];
5343
+ }
5344
+ async state(id) {
5345
+ return STATES[id];
5346
+ }
5347
+ async log(id) {
5348
+ return LOGS[id];
5349
+ }
5350
+ async output(id) {
5351
+ return OUTPUTS[id];
5352
+ }
5353
+ };
5354
+
5239
5355
  // src/corpus/records.ts
5240
5356
  var SIGNED_IN_TOKENS = [
5241
5357
  {
@@ -5932,11 +6048,11 @@ var SASjsApi = (() => {
5932
6048
  },
5933
6049
  // ------------------------------------------------------------ permissions
5934
6050
  {
5935
- id: "authorized-routes",
6051
+ id: "authorized-routes-as-admin",
5936
6052
  route: "GET /SASjsApi/info/authorizedRoutes",
5937
- description: "answers the routes that accept a rule, to any caller",
6053
+ description: "answers the route inventory to an administrator",
5938
6054
  identity: ADMIN_SIGNED_IN,
5939
- request: { token: RESTRICTED2 },
6055
+ request: { token: ADMIN2 },
5940
6056
  expect: {
5941
6057
  status: 200,
5942
6058
  body: {
@@ -5955,6 +6071,14 @@ var SASjsApi = (() => {
5955
6071
  }
5956
6072
  }
5957
6073
  },
6074
+ {
6075
+ id: "authorized-routes-as-user",
6076
+ route: "GET /SASjsApi/info/authorizedRoutes",
6077
+ description: "refuses the inventory to a caller who is not an administrator",
6078
+ identity: ADMIN_SIGNED_IN,
6079
+ request: { token: RESTRICTED2 },
6080
+ expect: { status: 401, error: "Admin account required" }
6081
+ },
5958
6082
  {
5959
6083
  id: "my-authorized-routes-as-admin",
5960
6084
  route: "GET /SASjsApi/info/myAuthorizedRoutes",
@@ -6452,112 +6576,6 @@ var SASjsApi = (() => {
6452
6576
  }
6453
6577
  ];
6454
6578
 
6455
- // src/session/service.ts
6456
- var createSessionService = (store, host) => {
6457
- const notFound2 = (id) => `Session with ID '${id}' was not found.`;
6458
- const visible = async (caller, id) => {
6459
- if (!caller) throw new ApiError(401, "Unauthorized");
6460
- const reader = await store.userById(
6461
- caller.userId
6462
- );
6463
- if (!reader || !reader.isActive) throw new ApiError(401, "Unauthorized");
6464
- const session = await host.session(id);
6465
- if (!session) throw new ApiError(404, notFound2(id));
6466
- const owner = session.owner;
6467
- if (owner !== reader.uid && owner !== reader.username && !reader.isAdmin)
6468
- throw new ApiError(404, notFound2(id));
6469
- return session;
6470
- };
6471
- return {
6472
- async summary(caller, id) {
6473
- const session = await visible(caller, id);
6474
- return session.summary;
6475
- },
6476
- async state(caller, id) {
6477
- await visible(caller, id);
6478
- const state = await host.state(id);
6479
- if (!state) throw new ApiError(404, notFound2(id));
6480
- return state;
6481
- },
6482
- async log(caller, id) {
6483
- await visible(caller, id);
6484
- const log = await host.log(id);
6485
- if (log === void 0) throw new ApiError(404, notFound2(id));
6486
- return log;
6487
- },
6488
- async output(caller, id) {
6489
- await visible(caller, id);
6490
- const output = await host.output(id);
6491
- if (output === void 0) throw new ApiError(404, notFound2(id));
6492
- return output;
6493
- }
6494
- };
6495
- };
6496
-
6497
- // src/session/memory-host.ts
6498
- var DEFAULT_SESSIONS = {
6499
- "sess-admin": {
6500
- owner: "user-admin",
6501
- summary: {
6502
- sessionId: "sess-admin",
6503
- state: "completed",
6504
- pid: 4242,
6505
- creationTimeStamp: "2026-11-07T09:00:00.000Z",
6506
- deathTimeStamp: "2026-11-07T09:00:04.000Z",
6507
- expiresAfterMins: 60
6508
- }
6509
- },
6510
- "sess-restricted": {
6511
- owner: "user-restricted",
6512
- summary: {
6513
- sessionId: "sess-restricted",
6514
- state: "running",
6515
- pid: 4243,
6516
- creationTimeStamp: "2026-11-07T09:05:00.000Z"
6517
- }
6518
- },
6519
- "sess-silent": {
6520
- owner: "user-admin",
6521
- summary: {
6522
- sessionId: "sess-silent",
6523
- state: "running",
6524
- pid: 4244,
6525
- creationTimeStamp: "2026-11-07T09:10:00.000Z"
6526
- }
6527
- }
6528
- };
6529
- var STATES = {
6530
- "sess-admin": { state: "completed", pid: 4242, lineCount: 12 },
6531
- "sess-restricted": { state: "running", pid: 4243, lineCount: 3 }
6532
- };
6533
- var LOGS = {
6534
- "sess-admin": "NOTE: session started\nNOTE: session completed\n",
6535
- "sess-restricted": "NOTE: session started\n",
6536
- "sess-silent": ""
6537
- };
6538
- var OUTPUTS = {
6539
- "sess-admin": "<html><body>42</body></html>",
6540
- "sess-restricted": "",
6541
- "sess-silent": ""
6542
- };
6543
- var MemorySessionHost = class {
6544
- constructor(sessions = DEFAULT_SESSIONS) {
6545
- this.sessions = sessions;
6546
- }
6547
- async session(id) {
6548
- return this.sessions[id];
6549
- }
6550
- async state(id) {
6551
- return STATES[id];
6552
- }
6553
- async log(id) {
6554
- return LOGS[id];
6555
- }
6556
- async output(id) {
6557
- return OUTPUTS[id];
6558
- }
6559
- };
6560
-
6561
6579
  // src/corpus/runner.ts
6562
6580
  var servicesFor = (testCase) => {
6563
6581
  const identity = new MemoryIdentityStore(
@@ -51,7 +51,7 @@ exports.DEPLOY_CORPUS = [
51
51
  subject: SUBJECT,
52
52
  body: { streamServiceName: 'myApp', appLoc: '/Public/not-an-app' }
53
53
  },
54
- expect: { status: 404, error: 'No such app stream entry.' }
54
+ expect: { status: 404, error: 'No app is published at that folder.' }
55
55
  },
56
56
  // ------------------------------------------- the uploaded-archive route
57
57
  // The archive is expanded by the host, so what arrives here is the same tree
@@ -703,11 +703,11 @@ exports.RECORD_CORPUS = [
703
703
  },
704
704
  // ------------------------------------------------------------ permissions
705
705
  {
706
- id: 'authorized-routes',
706
+ id: 'authorized-routes-as-admin',
707
707
  route: 'GET /SASjsApi/info/authorizedRoutes',
708
- description: 'answers the routes that accept a rule, to any caller',
708
+ description: 'answers the route inventory to an administrator',
709
709
  identity: exports.ADMIN_SIGNED_IN,
710
- request: { token: RESTRICTED },
710
+ request: { token: ADMIN },
711
711
  expect: {
712
712
  status: 200,
713
713
  body: {
@@ -726,6 +726,14 @@ exports.RECORD_CORPUS = [
726
726
  }
727
727
  }
728
728
  },
729
+ {
730
+ id: 'authorized-routes-as-user',
731
+ route: 'GET /SASjsApi/info/authorizedRoutes',
732
+ description: 'refuses the inventory to a caller who is not an administrator',
733
+ identity: exports.ADMIN_SIGNED_IN,
734
+ request: { token: RESTRICTED },
735
+ expect: { status: 401, error: 'Admin account required' }
736
+ },
729
737
  {
730
738
  id: 'my-authorized-routes-as-admin',
731
739
  route: 'GET /SASjsApi/info/myAuthorizedRoutes',
@@ -19,7 +19,7 @@ const unpublishAppStream = async (registry, body) => {
19
19
  if (!body.appLoc)
20
20
  throw new types_js_1.ApiError(400, '"appLoc" is required');
21
21
  if (!(await registry.unpublish(body.appLoc)))
22
- throw new types_js_1.ApiError(404, 'No such app stream entry.');
22
+ throw new types_js_1.ApiError(404, 'No app is published at that folder.');
23
23
  return { status: 'success' };
24
24
  };
25
25
  exports.unpublishAppStream = unpublishAppStream;
@@ -288,9 +288,14 @@ const createRecordService = (store, options = {}) => {
288
288
  return groupDetails(updated);
289
289
  },
290
290
  async listAuthorizedRoutes(caller) {
291
- // an identity is required because the route is about a caller's access,
292
- // even though what it returns is the whole inventory
293
- await requireCaller(store, caller);
291
+ // The inventory is for the administration dialog, and it is admin-only:
292
+ // the routes a caller may reach are reconnaissance, and a non-administrator
293
+ // learns their own access from `myAuthorizedRoutes` instead. The refusal is
294
+ // the host's too - sasjs/server gates the same path with `verifyAdmin` -
295
+ // which is why the message matches what a caller sees there.
296
+ const reader = await requireCaller(store, caller);
297
+ if (!reader.isAdmin)
298
+ throw new types_js_1.ApiError(401, 'Admin account required');
294
299
  return { paths: [...grantableRoutes] };
295
300
  },
296
301
  async myAuthorizedRoutes(caller) {
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.servicesFor = exports.runCase = exports.PROVIDER_MANAGED = exports.ADMIN_SIGNED_IN = exports.RECORD_CORPUS = exports.SESSION_CORPUS = exports.DEPLOY_CORPUS = exports.IDENTITY_CORPUS = exports.DRIVE_CORPUS = exports.parseIdentity = exports.IDENTITY_FORMAT = exports.DEFAULT_IDENTITY = exports.MemoryIdentityStore = exports.CODE_CORPUS = exports.sanitiseDisplayName = exports.createRecordService = exports.createIdentityService = exports.HANDLED_ROUTES = exports.dispatch = exports.TAG_CAPABILITIES = exports.OVERLAY = exports.findRoute = exports.routeById = exports.ROUTES = exports.MemoryDriveStore = exports.measureDeployTree = exports.isDeployTree = exports.deployTree = exports.decodeBase64 = exports.checkDeployTree = exports.DEPLOY_SUCCESS = exports.DEPLOY_PAYLOAD_BYTES = exports.DEPLOY_LIMITS = exports.createDriveService = exports.isRoot = exports.basename = exports.dirname = exports.hasBlockedExtension = exports.normaliseDrivePath = void 0;
17
+ exports.servicesFor = exports.runCase = exports.PROVIDER_MANAGED = exports.ADMIN_SIGNED_IN = exports.RECORD_CORPUS = exports.unpublishAppStream = exports.MemoryAppStreamRegistry = exports.MemorySessionHost = exports.DEFAULT_SESSIONS = exports.createSessionService = exports.SESSION_CORPUS = exports.DEPLOY_CORPUS = exports.IDENTITY_CORPUS = exports.DRIVE_CORPUS = exports.parseIdentity = exports.IDENTITY_FORMAT = exports.DEFAULT_IDENTITY = exports.MemoryIdentityStore = exports.CODE_CORPUS = exports.sanitiseDisplayName = exports.createRecordService = exports.createIdentityService = exports.HANDLED_ROUTES = exports.dispatch = exports.TAG_CAPABILITIES = exports.OVERLAY = exports.findRoute = exports.routeById = exports.ROUTES = exports.MemoryDriveStore = exports.measureDeployTree = exports.isDeployTree = exports.deployTree = exports.decodeBase64 = exports.checkDeployTree = exports.DEPLOY_SUCCESS = exports.DEPLOY_PAYLOAD_BYTES = exports.DEPLOY_LIMITS = exports.createDriveService = exports.isRoot = exports.basename = exports.dirname = exports.hasBlockedExtension = exports.normaliseDrivePath = void 0;
18
18
  /**
19
19
  * `@sasjs/api` - the SASjs Server API described once.
20
20
  *
@@ -83,6 +83,14 @@ var deploy_js_2 = require("./corpus/deploy.js");
83
83
  Object.defineProperty(exports, "DEPLOY_CORPUS", { enumerable: true, get: function () { return deploy_js_2.DEPLOY_CORPUS; } });
84
84
  var session_js_1 = require("./corpus/session.js");
85
85
  Object.defineProperty(exports, "SESSION_CORPUS", { enumerable: true, get: function () { return session_js_1.SESSION_CORPUS; } });
86
+ var service_js_3 = require("./session/service.js");
87
+ Object.defineProperty(exports, "createSessionService", { enumerable: true, get: function () { return service_js_3.createSessionService; } });
88
+ var memory_host_js_1 = require("./session/memory-host.js");
89
+ Object.defineProperty(exports, "DEFAULT_SESSIONS", { enumerable: true, get: function () { return memory_host_js_1.DEFAULT_SESSIONS; } });
90
+ Object.defineProperty(exports, "MemorySessionHost", { enumerable: true, get: function () { return memory_host_js_1.MemorySessionHost; } });
91
+ var registry_js_1 = require("./drive/registry.js");
92
+ Object.defineProperty(exports, "MemoryAppStreamRegistry", { enumerable: true, get: function () { return registry_js_1.MemoryAppStreamRegistry; } });
93
+ Object.defineProperty(exports, "unpublishAppStream", { enumerable: true, get: function () { return registry_js_1.unpublishAppStream; } });
86
94
  var records_js_2 = require("./corpus/records.js");
87
95
  Object.defineProperty(exports, "RECORD_CORPUS", { enumerable: true, get: function () { return records_js_2.RECORD_CORPUS; } });
88
96
  Object.defineProperty(exports, "ADMIN_SIGNED_IN", { enumerable: true, get: function () { return records_js_2.ADMIN_SIGNED_IN; } });
@@ -460,7 +460,7 @@ exports.GENERATED_ROUTES = [
460
460
  },
461
461
  {
462
462
  status: 404,
463
- description: 'No such app stream entry'
463
+ description: 'No app is published at that folder'
464
464
  }
465
465
  ]
466
466
  },
@@ -1094,6 +1094,10 @@ exports.GENERATED_ROUTES = [
1094
1094
  {
1095
1095
  status: 200,
1096
1096
  description: 'Ok'
1097
+ },
1098
+ {
1099
+ status: 401,
1100
+ description: 'Administrator access is required'
1097
1101
  }
1098
1102
  ]
1099
1103
  },
@@ -48,7 +48,7 @@ export const DEPLOY_CORPUS = [
48
48
  subject: SUBJECT,
49
49
  body: { streamServiceName: 'myApp', appLoc: '/Public/not-an-app' }
50
50
  },
51
- expect: { status: 404, error: 'No such app stream entry.' }
51
+ expect: { status: 404, error: 'No app is published at that folder.' }
52
52
  },
53
53
  // ------------------------------------------- the uploaded-archive route
54
54
  // The archive is expanded by the host, so what arrives here is the same tree
@@ -1 +1 @@
1
- {"version":3,"file":"records.d.ts","sourceRoot":"","sources":["../../../src/corpus/records.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EAEL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAA;AAkB/B,qFAAqF;AACrF,eAAO,MAAM,eAAe,EAAE,eAG7B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,eA0C9B,CAAA;AAOD,eAAO,MAAM,aAAa,EAAE,UAAU,EA4oCrC,CAAA"}
1
+ {"version":3,"file":"records.d.ts","sourceRoot":"","sources":["../../../src/corpus/records.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EAEL,KAAK,eAAe,EAErB,MAAM,wBAAwB,CAAA;AAkB/B,qFAAqF;AACrF,eAAO,MAAM,eAAe,EAAE,eAG7B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,EAAE,eA0C9B,CAAA;AAOD,eAAO,MAAM,aAAa,EAAE,UAAU,EAqpCrC,CAAA"}
@@ -700,11 +700,11 @@ export const RECORD_CORPUS = [
700
700
  },
701
701
  // ------------------------------------------------------------ permissions
702
702
  {
703
- id: 'authorized-routes',
703
+ id: 'authorized-routes-as-admin',
704
704
  route: 'GET /SASjsApi/info/authorizedRoutes',
705
- description: 'answers the routes that accept a rule, to any caller',
705
+ description: 'answers the route inventory to an administrator',
706
706
  identity: ADMIN_SIGNED_IN,
707
- request: { token: RESTRICTED },
707
+ request: { token: ADMIN },
708
708
  expect: {
709
709
  status: 200,
710
710
  body: {
@@ -723,6 +723,14 @@ export const RECORD_CORPUS = [
723
723
  }
724
724
  }
725
725
  },
726
+ {
727
+ id: 'authorized-routes-as-user',
728
+ route: 'GET /SASjsApi/info/authorizedRoutes',
729
+ description: 'refuses the inventory to a caller who is not an administrator',
730
+ identity: ADMIN_SIGNED_IN,
731
+ request: { token: RESTRICTED },
732
+ expect: { status: 401, error: 'Admin account required' }
733
+ },
726
734
  {
727
735
  id: 'my-authorized-routes-as-admin',
728
736
  route: 'GET /SASjsApi/info/myAuthorizedRoutes',
@@ -16,7 +16,7 @@ export const unpublishAppStream = async (registry, body) => {
16
16
  if (!body.appLoc)
17
17
  throw new ApiError(400, '"appLoc" is required');
18
18
  if (!(await registry.unpublish(body.appLoc)))
19
- throw new ApiError(404, 'No such app stream entry.');
19
+ throw new ApiError(404, 'No app is published at that folder.');
20
20
  return { status: 'success' };
21
21
  };
22
22
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"records.d.ts","sourceRoot":"","sources":["../../../src/identity/records.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"records.d.ts","sourceRoot":"","sources":["../../../src/identity/records.ts"],"names":[],"mappings":"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"}
@@ -284,9 +284,14 @@ export const createRecordService = (store, options = {}) => {
284
284
  return groupDetails(updated);
285
285
  },
286
286
  async listAuthorizedRoutes(caller) {
287
- // an identity is required because the route is about a caller's access,
288
- // even though what it returns is the whole inventory
289
- await requireCaller(store, caller);
287
+ // The inventory is for the administration dialog, and it is admin-only:
288
+ // the routes a caller may reach are reconnaissance, and a non-administrator
289
+ // learns their own access from `myAuthorizedRoutes` instead. The refusal is
290
+ // the host's too - sasjs/server gates the same path with `verifyAdmin` -
291
+ // which is why the message matches what a caller sees there.
292
+ const reader = await requireCaller(store, caller);
293
+ if (!reader.isAdmin)
294
+ throw new ApiError(401, 'Admin account required');
290
295
  return { paths: [...grantableRoutes] };
291
296
  },
292
297
  async myAuthorizedRoutes(caller) {
@@ -40,6 +40,11 @@ export { DRIVE_CORPUS } from './corpus/drive.js';
40
40
  export { IDENTITY_CORPUS } from './corpus/identity.js';
41
41
  export { DEPLOY_CORPUS } from './corpus/deploy.js';
42
42
  export { SESSION_CORPUS } from './corpus/session.js';
43
+ export { createSessionService } from './session/service.js';
44
+ export type { HostSession, SessionHost, SessionService, SessionStateResponse, SessionSummary } from './session/service.js';
45
+ export { DEFAULT_SESSIONS, MemorySessionHost } from './session/memory-host.js';
46
+ export { MemoryAppStreamRegistry, unpublishAppStream } from './drive/registry.js';
47
+ export type { AppStreamRegistry, UnpublishBody } from './drive/registry.js';
43
48
  export { RECORD_CORPUS, ADMIN_SIGNED_IN, PROVIDER_MANAGED } from './corpus/records.js';
44
49
  export type { CorpusCase } from './corpus/drive.js';
45
50
  export { runCase, servicesFor } from './corpus/runner.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,cAAc,YAAY,CAAA;AAC1B,OAAO,EACL,kBAAkB,EAClB,mBAAmB,EACnB,OAAO,EACP,QAAQ,EACR,MAAM,EACP,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACvD,OAAO,EACL,aAAa,EACb,oBAAoB,EACpB,cAAc,EACd,eAAe,EACf,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,iBAAiB,EAClB,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EACV,YAAY,EACZ,kBAAkB,EAClB,YAAY,EACZ,aAAa,EACb,UAAU,EACX,MAAM,mBAAmB,CAAA;AAC1B,YAAY,EACV,YAAY,EACZ,WAAW,EACX,YAAY,EACZ,SAAS,EACT,SAAS,EACV,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAChE,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAC/D,YAAY,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAG7D,cAAc,2BAA2B,CAAA;AACzC,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAC3E,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAChF,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA;AAC9C,YAAY,EACV,wBAAwB,EACxB,oBAAoB,EACpB,aAAa,EACb,kBAAkB,EAClB,oBAAoB,EACpB,aAAa,EACb,mBAAmB,EACnB,YAAY,EACb,MAAM,uBAAuB,CAAA;AAC9B,YAAY,EACV,eAAe,EACf,WAAW,EACX,aAAa,EACd,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAChE,OAAO,EACL,gBAAgB,EAChB,eAAe,EACf,aAAa,EACd,MAAM,uBAAuB,CAAA;AAC9B,YAAY,EACV,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,yBAAyB,EACzB,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,uBAAuB,CAAA;AAC9B,YAAY,EACV,cAAc,EACd,oBAAoB,EACpB,mBAAmB,EACnB,wBAAwB,EACxB,aAAa,EACb,YAAY,EACZ,kBAAkB,EAClB,QAAQ,EACR,aAAa,EACb,OAAO,EACP,OAAO,EACP,SAAS,EACT,UAAU,EACX,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAClD,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EACL,aAAa,EACb,eAAe,EACf,gBAAgB,EACjB,MAAM,qBAAqB,CAAA;AAC5B,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AACzD,YAAY,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"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"}
@@ -32,5 +32,8 @@ export { DRIVE_CORPUS } from './corpus/drive.js';
32
32
  export { IDENTITY_CORPUS } from './corpus/identity.js';
33
33
  export { DEPLOY_CORPUS } from './corpus/deploy.js';
34
34
  export { SESSION_CORPUS } from './corpus/session.js';
35
+ export { createSessionService } from './session/service.js';
36
+ export { DEFAULT_SESSIONS, MemorySessionHost } from './session/memory-host.js';
37
+ export { MemoryAppStreamRegistry, unpublishAppStream } from './drive/registry.js';
35
38
  export { RECORD_CORPUS, ADMIN_SIGNED_IN, PROVIDER_MANAGED } from './corpus/records.js';
36
39
  export { runCase, servicesFor } from './corpus/runner.js';
@@ -1 +1 @@
1
- {"version":3,"file":"generated.d.ts","sourceRoot":"","sources":["../../../src/routes/generated.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD,eAAO,MAAM,gBAAgB,EAAE,cAAc,EAw6D5C,CAAA"}
1
+ {"version":3,"file":"generated.d.ts","sourceRoot":"","sources":["../../../src/routes/generated.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAEjD,eAAO,MAAM,gBAAgB,EAAE,cAAc,EA46D5C,CAAA"}
@@ -457,7 +457,7 @@ export const GENERATED_ROUTES = [
457
457
  },
458
458
  {
459
459
  status: 404,
460
- description: 'No such app stream entry'
460
+ description: 'No app is published at that folder'
461
461
  }
462
462
  ]
463
463
  },
@@ -1091,6 +1091,10 @@ export const GENERATED_ROUTES = [
1091
1091
  {
1092
1092
  status: 200,
1093
1093
  description: 'Ok'
1094
+ },
1095
+ {
1096
+ status: 401,
1097
+ description: 'Administrator access is required'
1094
1098
  }
1095
1099
  ]
1096
1100
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sasjs/api",
3
- "version": "0.13.0",
3
+ "version": "0.14.1",
4
4
  "description": "The SASjs Server API, described once - a generated route table, the services behind it, and the conformance corpus both hosts run",
5
5
  "license": "MIT",
6
6
  "author": "SASjs",