@sasjs/api 0.9.0 → 0.11.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.
Files changed (45) hide show
  1. package/build/browser.js +457 -102
  2. package/build/cjs/code/index.js +12 -0
  3. package/build/cjs/code/service.js +57 -0
  4. package/build/cjs/corpus/code.js +99 -0
  5. package/build/cjs/corpus/runner.js +4 -1
  6. package/build/cjs/corpus/session.js +73 -0
  7. package/build/cjs/host/dispatch.js +65 -3
  8. package/build/cjs/index.js +5 -1
  9. package/build/cjs/routes/generated.js +16 -0
  10. package/build/cjs/routes/overlay.js +15 -20
  11. package/build/cjs/session/memory-host.js +74 -0
  12. package/build/cjs/session/service.js +65 -0
  13. package/build/esm/code/index.d.ts +10 -0
  14. package/build/esm/code/index.d.ts.map +1 -0
  15. package/build/esm/code/index.js +8 -0
  16. package/build/esm/code/service.d.ts +40 -0
  17. package/build/esm/code/service.d.ts.map +1 -0
  18. package/build/esm/code/service.js +53 -0
  19. package/build/esm/corpus/code.d.ts +17 -0
  20. package/build/esm/corpus/code.d.ts.map +1 -0
  21. package/build/esm/corpus/code.js +96 -0
  22. package/build/esm/corpus/drive.d.ts +9 -0
  23. package/build/esm/corpus/drive.d.ts.map +1 -1
  24. package/build/esm/corpus/runner.d.ts.map +1 -1
  25. package/build/esm/corpus/runner.js +4 -1
  26. package/build/esm/corpus/session.d.ts +16 -0
  27. package/build/esm/corpus/session.d.ts.map +1 -0
  28. package/build/esm/corpus/session.js +70 -0
  29. package/build/esm/host/dispatch.d.ts +9 -0
  30. package/build/esm/host/dispatch.d.ts.map +1 -1
  31. package/build/esm/host/dispatch.js +65 -3
  32. package/build/esm/index.d.ts +2 -0
  33. package/build/esm/index.d.ts.map +1 -1
  34. package/build/esm/index.js +2 -0
  35. package/build/esm/routes/generated.d.ts.map +1 -1
  36. package/build/esm/routes/generated.js +16 -0
  37. package/build/esm/routes/overlay.d.ts.map +1 -1
  38. package/build/esm/routes/overlay.js +15 -20
  39. package/build/esm/session/memory-host.d.ts +19 -0
  40. package/build/esm/session/memory-host.d.ts.map +1 -0
  41. package/build/esm/session/memory-host.js +70 -0
  42. package/build/esm/session/service.d.ts +62 -0
  43. package/build/esm/session/service.d.ts.map +1 -0
  44. package/build/esm/session/service.js +61 -0
  45. package/package.json +9 -1
package/build/browser.js CHANGED
@@ -1,4 +1,4 @@
1
- /* @sasjs/api 0.9.0 - the SASjs Server API, for a service worker. https://github.com/sasjs/api */
1
+ /* @sasjs/api 0.11.0 - 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;
@@ -25,6 +25,7 @@ var SASjsApi = (() => {
25
25
  ADMIN_SIGNED_IN: () => ADMIN_SIGNED_IN,
26
26
  ALWAYS_VISIBLE_ROUTES: () => ALWAYS_VISIBLE_ROUTES,
27
27
  ApiError: () => ApiError,
28
+ CODE_CORPUS: () => CODE_CORPUS,
28
29
  DEFAULT_GRANTABLE_ROUTES: () => DEFAULT_GRANTABLE_ROUTES,
29
30
  DEFAULT_IDENTITY: () => DEFAULT_IDENTITY,
30
31
  DEPLOY_LIMITS: () => DEPLOY_LIMITS,
@@ -40,6 +41,7 @@ var SASjsApi = (() => {
40
41
  PROVIDER_MANAGED: () => PROVIDER_MANAGED,
41
42
  RECORD_CORPUS: () => RECORD_CORPUS,
42
43
  ROUTES: () => ROUTES,
44
+ SESSION_CORPUS: () => SESSION_CORPUS,
43
45
  STATIC_AUTHORIZED_ROUTES: () => STATIC_AUTHORIZED_ROUTES,
44
46
  TAG_CAPABILITIES: () => TAG_CAPABILITIES,
45
47
  TOP_LEVEL_ROUTES: () => TOP_LEVEL_ROUTES,
@@ -891,6 +893,14 @@ var SASjsApi = (() => {
891
893
  {
892
894
  status: 200,
893
895
  description: "Ok"
896
+ },
897
+ {
898
+ status: 400,
899
+ description: '"code" is required / "code" must be a string / "code" is not allowed to be empty'
900
+ },
901
+ {
902
+ status: 401,
903
+ description: "Unauthorized"
894
904
  }
895
905
  ]
896
906
  },
@@ -919,6 +929,14 @@ var SASjsApi = (() => {
919
929
  {
920
930
  status: 200,
921
931
  description: "Ok"
932
+ },
933
+ {
934
+ status: 400,
935
+ description: '"code" is required / "code" must be a string / "code" is not allowed to be empty'
936
+ },
937
+ {
938
+ status: 401,
939
+ description: "Unauthorized"
922
940
  }
923
941
  ]
924
942
  },
@@ -2459,9 +2477,7 @@ var SASjsApi = (() => {
2459
2477
  Web: ["identity"]
2460
2478
  };
2461
2479
  var DIRECTORY = "Synchronising with an external auth provider needs a directory port, which this package does not have: a host decides which directory it holds accounts in, and answers this itself.";
2462
- var EDITOR = "Linting and formatting come from @sasjs/lint, which this package does not depend on. They land with the code routes so an editor has one wiring.";
2463
2480
  var RUNTIME = "Starting a program needs a runtime port, which this package does not have: a host decides which languages it holds, and answers this itself until then.";
2464
- var SESSION_RECORD = "A triggered session's record, log, output and state belong to the runtime that ran the program, and this package has no runtime port.";
2465
2481
  var HOST_CONFIG = "The body is the host's own configuration - ports, run times and providers - which a mock states for itself and this package cannot know.";
2466
2482
  var HOST_OWNED = "The host owns this report: it describes the host's own process and files, which a browser build has no equivalent of.";
2467
2483
  var WEB_BUNDLE = "The host serves its own web bundle; there is no API decision here for this package to answer.";
@@ -2529,8 +2545,14 @@ var SASjsApi = (() => {
2529
2545
  // Code - the editor's three calls, and the runtime one
2530
2546
  "POST /SASjsApi/code/execute": { implemented: false, reason: RUNTIME },
2531
2547
  "POST /SASjsApi/code/trigger": { implemented: false, reason: RUNTIME },
2532
- "POST /SASjsApi/code/lint": { implemented: false, reason: EDITOR },
2533
- "POST /SASjsApi/code/format": { implemented: false, reason: EDITOR },
2548
+ "POST /SASjsApi/code/lint": {
2549
+ implemented: true,
2550
+ capabilities: ["identity"]
2551
+ },
2552
+ "POST /SASjsApi/code/format": {
2553
+ implemented: true,
2554
+ capabilities: ["identity"]
2555
+ },
2534
2556
  // Drive - the file and folder rules, and the three deploy routes
2535
2557
  // The body is the file itself, so there is nothing to annotate
2536
2558
  "GET /SASjsApi/drive/file": { implemented: true },
@@ -2633,22 +2655,13 @@ var SASjsApi = (() => {
2633
2655
  implemented: true,
2634
2656
  responses: { 200: user }
2635
2657
  },
2636
- "GET /SASjsApi/session/{sessionId}": {
2637
- implemented: false,
2638
- reason: SESSION_RECORD
2639
- },
2640
- "GET /SASjsApi/session/{sessionId}/log": {
2641
- implemented: false,
2642
- reason: SESSION_RECORD
2643
- },
2644
- "GET /SASjsApi/session/{sessionId}/output": {
2645
- implemented: false,
2646
- reason: SESSION_RECORD
2647
- },
2648
- "GET /SASjsApi/session/{sessionId}/state": {
2649
- implemented: false,
2650
- reason: SESSION_RECORD
2651
- },
2658
+ // The port takes the owner as a uid and falls back to a username, which is
2659
+ // what sasjs/server records today - a host hands its sessions through as they
2660
+ // are, and the comparison tries the identifier first.
2661
+ "GET /SASjsApi/session/{sessionId}": { implemented: true },
2662
+ "GET /SASjsApi/session/{sessionId}/log": { implemented: true },
2663
+ "GET /SASjsApi/session/{sessionId}/output": { implemented: true },
2664
+ "GET /SASjsApi/session/{sessionId}/state": { implemented: true },
2652
2665
  // STP - a stored program, on the runtime port
2653
2666
  "GET /SASjsApi/stp/execute": { implemented: false, reason: RUNTIME },
2654
2667
  "POST /SASjsApi/stp/execute": { implemented: false, reason: RUNTIME },
@@ -2772,8 +2785,10 @@ var SASjsApi = (() => {
2772
2785
  continue;
2773
2786
  if (param.in === "path") continue;
2774
2787
  const given = param.in === "query" ? request.query?.[param.name] : request.body?.[param.name];
2775
- if (given === void 0 || given === "")
2788
+ if (given === void 0)
2776
2789
  throw new ApiError(400, `"${param.name}" is required`);
2790
+ if (given === "")
2791
+ throw new ApiError(400, `"${param.name}" is not allowed to be empty`);
2777
2792
  }
2778
2793
  };
2779
2794
  var targetPath = (request) => {
@@ -2786,7 +2801,7 @@ var SASjsApi = (() => {
2786
2801
  var dispatch = async (services, routeId, request = {}) => {
2787
2802
  const route = routeById(routeId);
2788
2803
  if (!route) throw new ApiError(404, `No such operation: ${routeId}`);
2789
- const { drive, identity, records } = services;
2804
+ const { drive, identity, records, code } = services;
2790
2805
  const identityScoped = ["User", "Group", "Permission", "Client"].includes(route.tag) || routeId === "PATCH /SASjsApi/auth/updatePassword";
2791
2806
  if (identityScoped && records) {
2792
2807
  const subject = request.subject ?? (identity ? await identity.authenticate(request.token) : void 0);
@@ -2803,6 +2818,14 @@ var SASjsApi = (() => {
2803
2818
  const query = request.query || {};
2804
2819
  const body = request.body || {};
2805
2820
  const params = request.params || {};
2821
+ const sessionRequired = () => {
2822
+ if (!services.session)
2823
+ throw new ApiError(
2824
+ 501,
2825
+ `This host has no session service, so it cannot answer ${routeId}.`
2826
+ );
2827
+ return services.session;
2828
+ };
2806
2829
  const required = () => {
2807
2830
  if (!records)
2808
2831
  throw new ApiError(
@@ -2827,7 +2850,7 @@ var SASjsApi = (() => {
2827
2850
  status: 200,
2828
2851
  body: await identity.token({
2829
2852
  clientId: String(body.clientId ?? ""),
2830
- code: String(body.code ?? "")
2853
+ code: body.code
2831
2854
  })
2832
2855
  };
2833
2856
  case "POST /SASjsApi/auth/refresh":
@@ -2902,6 +2925,43 @@ var SASjsApi = (() => {
2902
2925
  }
2903
2926
  case "GET /SASjsApi/drive/filetree":
2904
2927
  return { status: 200, body: await drive.tree(query._folderPath) };
2928
+ // ------------------------------------------------------------- sessions
2929
+ case "GET /SASjsApi/session/{sessionId}": {
2930
+ return {
2931
+ status: 200,
2932
+ body: await sessionRequired().summary(
2933
+ await caller(),
2934
+ String(params.sessionId ?? "")
2935
+ )
2936
+ };
2937
+ }
2938
+ case "GET /SASjsApi/session/{sessionId}/log": {
2939
+ return {
2940
+ status: 200,
2941
+ contents: await sessionRequired().log(
2942
+ await caller(),
2943
+ String(params.sessionId ?? "")
2944
+ )
2945
+ };
2946
+ }
2947
+ case "GET /SASjsApi/session/{sessionId}/output": {
2948
+ return {
2949
+ status: 200,
2950
+ contents: await sessionRequired().output(
2951
+ await caller(),
2952
+ String(params.sessionId ?? "")
2953
+ )
2954
+ };
2955
+ }
2956
+ case "GET /SASjsApi/session/{sessionId}/state": {
2957
+ return {
2958
+ status: 200,
2959
+ body: await sessionRequired().state(
2960
+ await caller(),
2961
+ String(params.sessionId ?? "")
2962
+ )
2963
+ };
2964
+ }
2905
2965
  // ------------------------------------------------------------- records
2906
2966
  //
2907
2967
  // The administration routes: users, groups, permission rules, clients and the
@@ -2971,6 +3031,32 @@ var SASjsApi = (() => {
2971
3031
  { password: body.password }
2972
3032
  )
2973
3033
  };
3034
+ case "POST /SASjsApi/code/lint":
3035
+ if (!code)
3036
+ throw new ApiError(
3037
+ 501,
3038
+ `This host has no code service, so it cannot answer ${routeId}.`
3039
+ );
3040
+ return {
3041
+ status: 200,
3042
+ body: await code.lint(await caller(), {
3043
+ code: body.code,
3044
+ filePath: body.filePath
3045
+ })
3046
+ };
3047
+ case "POST /SASjsApi/code/format":
3048
+ if (!code)
3049
+ throw new ApiError(
3050
+ 501,
3051
+ `This host has no code service, so it cannot answer ${routeId}.`
3052
+ );
3053
+ return {
3054
+ status: 200,
3055
+ body: await code.format(await caller(), {
3056
+ code: body.code,
3057
+ filePath: body.filePath
3058
+ })
3059
+ };
2974
3060
  case "GET /SASjsApi/info/authorizedRoutes":
2975
3061
  return {
2976
3062
  status: 200,
@@ -3091,6 +3177,12 @@ var SASjsApi = (() => {
3091
3177
  }
3092
3178
  };
3093
3179
  var HANDLED_ROUTES = [
3180
+ "GET /SASjsApi/session/{sessionId}",
3181
+ "GET /SASjsApi/session/{sessionId}/log",
3182
+ "GET /SASjsApi/session/{sessionId}/output",
3183
+ "GET /SASjsApi/session/{sessionId}/state",
3184
+ "POST /SASjsApi/code/lint",
3185
+ "POST /SASjsApi/code/format",
3094
3186
  "GET /SASjsApi/info/authorizedRoutes",
3095
3187
  "GET /SASjsApi/info/myAuthorizedRoutes",
3096
3188
  "GET /SASjsApi/drive/file",
@@ -3602,6 +3694,90 @@ var SASjsApi = (() => {
3602
3694
  };
3603
3695
  };
3604
3696
 
3697
+ // src/corpus/code.ts
3698
+ var CODE_CORPUS = [
3699
+ {
3700
+ id: "code-lint-missing-header",
3701
+ route: "POST /SASjsApi/code/lint",
3702
+ description: "answers the diagnostics for a buffer, without touching a file",
3703
+ request: {
3704
+ // the routes are permissioned; the runner resolves the fixture's admin
3705
+ subject: { userId: "user-admin", clientId: "web_app" },
3706
+ body: { code: "data _null_;\n x = 1;\nrun;\n" }
3707
+ },
3708
+ expect: {
3709
+ status: 200,
3710
+ body: [
3711
+ {
3712
+ message: "File missing Doxygen header",
3713
+ lineNumber: 1,
3714
+ startColumnNumber: 1,
3715
+ endColumnNumber: 1,
3716
+ severity: 1
3717
+ }
3718
+ ]
3719
+ }
3720
+ },
3721
+ {
3722
+ id: "code-lint-unauthenticated",
3723
+ route: "POST /SASjsApi/code/lint",
3724
+ description: "refuses a caller with no token",
3725
+ request: { body: { code: "data _null_; run;" } },
3726
+ expect: { status: 401, error: "Unauthorized" }
3727
+ },
3728
+ {
3729
+ id: "code-lint-non-string",
3730
+ route: "POST /SASjsApi/code/lint",
3731
+ description: "refuses a code value that is not a string, rather than coercing it",
3732
+ request: {
3733
+ subject: { userId: "user-admin", clientId: "web_app" },
3734
+ body: { code: 123 }
3735
+ },
3736
+ expect: { status: 400, error: '"code" must be a string' }
3737
+ },
3738
+ {
3739
+ id: "code-lint-empty",
3740
+ route: "POST /SASjsApi/code/lint",
3741
+ description: "refuses an empty buffer, which is not the same as a missing one",
3742
+ request: {
3743
+ subject: { userId: "user-admin", clientId: "web_app" },
3744
+ body: { code: "" }
3745
+ },
3746
+ expect: { status: 400, error: '"code" is not allowed to be empty' }
3747
+ },
3748
+ {
3749
+ id: "code-format-unauthenticated",
3750
+ route: "POST /SASjsApi/code/format",
3751
+ description: "refuses a caller with no token",
3752
+ request: { body: { code: "data _null_; run;" } },
3753
+ expect: { status: 401, error: "Unauthorized" }
3754
+ },
3755
+ {
3756
+ id: "code-format-non-string",
3757
+ route: "POST /SASjsApi/code/format",
3758
+ description: "refuses a code value that is not a string",
3759
+ request: {
3760
+ subject: { userId: "user-admin", clientId: "web_app" },
3761
+ body: { code: 123 }
3762
+ },
3763
+ expect: { status: 400, error: '"code" must be a string' }
3764
+ },
3765
+ {
3766
+ id: "code-format-adds-the-header",
3767
+ route: "POST /SASjsApi/code/format",
3768
+ description: "answers the formatted buffer, header block included",
3769
+ request: {
3770
+ // the routes are permissioned; the runner resolves the fixture's admin
3771
+ subject: { userId: "user-admin", clientId: "web_app" },
3772
+ body: { code: "data _null_;\n x = 1;\nrun;\n" }
3773
+ },
3774
+ expect: {
3775
+ status: 200,
3776
+ body: "/**\n @file\n @brief <Your brief here>\n\n <h4> SAS Macros </h4>\n\n**/\ndata _null_;\n x = 1;\nrun;\n"
3777
+ }
3778
+ }
3779
+ ];
3780
+
3605
3781
  // src/identity/fixture.ts
3606
3782
  var IDENTITY_FORMAT = 1;
3607
3783
  var SECONDS_IN_A_DAY2 = 86400;
@@ -4722,6 +4898,78 @@ var SASjsApi = (() => {
4722
4898
  }
4723
4899
  ];
4724
4900
 
4901
+ // src/corpus/session.ts
4902
+ var ADMIN = { userId: "user-admin", clientId: "web_app" };
4903
+ var RESTRICTED = { userId: "user-restricted", clientId: "web_app" };
4904
+ var SESSION_CORPUS = [
4905
+ {
4906
+ id: "session-summary-own",
4907
+ route: "GET /SASjsApi/session/{sessionId}",
4908
+ description: "answers the owner the summary of their own session",
4909
+ request: { subject: ADMIN, params: { sessionId: "sess-admin" } },
4910
+ expect: {
4911
+ status: 200,
4912
+ body: {
4913
+ sessionId: "sess-admin",
4914
+ state: "completed",
4915
+ pid: 4242,
4916
+ creationTimeStamp: "2026-11-07T09:00:00.000Z",
4917
+ deathTimeStamp: "2026-11-07T09:00:04.000Z",
4918
+ expiresAfterMins: 60
4919
+ }
4920
+ }
4921
+ },
4922
+ {
4923
+ id: "session-summary-as-admin",
4924
+ route: "GET /SASjsApi/session/{sessionId}",
4925
+ description: "answers an administrator another account's session",
4926
+ request: { subject: ADMIN, params: { sessionId: "sess-restricted" } },
4927
+ expect: {
4928
+ status: 200,
4929
+ body: {
4930
+ sessionId: "sess-restricted",
4931
+ state: "running",
4932
+ pid: 4243,
4933
+ creationTimeStamp: "2026-11-07T09:05:00.000Z"
4934
+ }
4935
+ }
4936
+ },
4937
+ {
4938
+ id: "session-log-own",
4939
+ route: "GET /SASjsApi/session/{sessionId}/log",
4940
+ description: "answers the log this session wrote",
4941
+ request: { subject: ADMIN, params: { sessionId: "sess-admin" } },
4942
+ expect: {
4943
+ status: 200,
4944
+ contents: "NOTE: session started\nNOTE: session completed\n"
4945
+ }
4946
+ },
4947
+ {
4948
+ id: "session-log-nothing-written",
4949
+ route: "GET /SASjsApi/session/{sessionId}/log",
4950
+ description: "answers an empty body for a session that has written nothing",
4951
+ request: { subject: ADMIN, params: { sessionId: "sess-silent" } },
4952
+ expect: { status: 200, contents: "" }
4953
+ },
4954
+ {
4955
+ id: "session-output-own",
4956
+ route: "GET /SASjsApi/session/{sessionId}/output",
4957
+ description: "answers the webout this session produced",
4958
+ request: { subject: ADMIN, params: { sessionId: "sess-admin" } },
4959
+ expect: { status: 200, contents: "<html><body>42</body></html>" }
4960
+ },
4961
+ {
4962
+ id: "session-state-own",
4963
+ route: "GET /SASjsApi/session/{sessionId}/state",
4964
+ description: "answers the run time's state for this session",
4965
+ request: { subject: RESTRICTED, params: { sessionId: "sess-restricted" } },
4966
+ expect: {
4967
+ status: 200,
4968
+ body: { state: "running", pid: 4243, lineCount: 3 }
4969
+ }
4970
+ }
4971
+ ];
4972
+
4725
4973
  // src/corpus/records.ts
4726
4974
  var SIGNED_IN_TOKENS = [
4727
4975
  {
@@ -4784,8 +5032,8 @@ var SASjsApi = (() => {
4784
5032
  }
4785
5033
  ]
4786
5034
  };
4787
- var ADMIN = "admin-access";
4788
- var RESTRICTED = "user-access";
5035
+ var ADMIN2 = "admin-access";
5036
+ var RESTRICTED2 = "user-access";
4789
5037
  var RESTRICTED_UID = "user-restricted";
4790
5038
  var ADMIN_UID = "user-admin";
4791
5039
  var RECORD_CORPUS = [
@@ -4795,7 +5043,7 @@ var SASjsApi = (() => {
4795
5043
  route: "GET /SASjsApi/user",
4796
5044
  description: "lists the accounts any signed-in caller may see",
4797
5045
  identity: ADMIN_SIGNED_IN,
4798
- request: { token: ADMIN },
5046
+ request: { token: ADMIN2 },
4799
5047
  expect: {
4800
5048
  status: 200,
4801
5049
  body: [
@@ -4819,7 +5067,7 @@ var SASjsApi = (() => {
4819
5067
  route: "GET /SASjsApi/user/{uid}",
4820
5068
  description: "returns the caller their own details, with the auto-exec code",
4821
5069
  identity: ADMIN_SIGNED_IN,
4822
- request: { token: RESTRICTED, params: { uid: RESTRICTED_UID } },
5070
+ request: { token: RESTRICTED2, params: { uid: RESTRICTED_UID } },
4823
5071
  expect: {
4824
5072
  status: 200,
4825
5073
  partial: {
@@ -4844,7 +5092,7 @@ var SASjsApi = (() => {
4844
5092
  route: "GET /SASjsApi/user/{uid}",
4845
5093
  description: "answers 404 for an identifier no account has",
4846
5094
  identity: ADMIN_SIGNED_IN,
4847
- request: { token: ADMIN, params: { uid: "user-none" } },
5095
+ request: { token: ADMIN2, params: { uid: "user-none" } },
4848
5096
  expect: { status: 404, error: "User is not found." }
4849
5097
  },
4850
5098
  {
@@ -4852,7 +5100,7 @@ var SASjsApi = (() => {
4852
5100
  route: "GET /SASjsApi/user/by/username/{username}",
4853
5101
  description: "finds an account by username",
4854
5102
  identity: ADMIN_SIGNED_IN,
4855
- request: { token: ADMIN, params: { username: "user2" } },
5103
+ request: { token: ADMIN2, params: { username: "user2" } },
4856
5104
  expect: {
4857
5105
  status: 200,
4858
5106
  partial: { uid: RESTRICTED_UID, username: "user2", isAdmin: false }
@@ -4871,7 +5119,7 @@ var SASjsApi = (() => {
4871
5119
  route: "GET /SASjsApi/user/by/username/{username}",
4872
5120
  description: "answers 404 for a username no account has",
4873
5121
  identity: ADMIN_SIGNED_IN,
4874
- request: { token: ADMIN, params: { username: "nobody" } },
5122
+ request: { token: ADMIN2, params: { username: "nobody" } },
4875
5123
  expect: { status: 404, error: "User is not found." }
4876
5124
  },
4877
5125
  {
@@ -4880,7 +5128,7 @@ var SASjsApi = (() => {
4880
5128
  description: "creates an account, sanitised, and reports it",
4881
5129
  identity: ADMIN_SIGNED_IN,
4882
5130
  request: {
4883
- token: ADMIN,
5131
+ token: ADMIN2,
4884
5132
  body: {
4885
5133
  username: "newuser",
4886
5134
  displayName: " New User ",
@@ -4905,7 +5153,7 @@ var SASjsApi = (() => {
4905
5153
  description: "refuses a creation by a caller who is not an administrator",
4906
5154
  identity: ADMIN_SIGNED_IN,
4907
5155
  request: {
4908
- token: RESTRICTED,
5156
+ token: RESTRICTED2,
4909
5157
  body: {
4910
5158
  username: "newuser",
4911
5159
  displayName: "New User",
@@ -4928,7 +5176,7 @@ var SASjsApi = (() => {
4928
5176
  description: "refuses a username that is taken",
4929
5177
  identity: ADMIN_SIGNED_IN,
4930
5178
  request: {
4931
- token: ADMIN,
5179
+ token: ADMIN2,
4932
5180
  body: { username: "user2", displayName: "Another", password: "newpass" }
4933
5181
  },
4934
5182
  expect: { status: 409, error: "Username already exists." }
@@ -4939,7 +5187,7 @@ var SASjsApi = (() => {
4939
5187
  description: "changes an account's display name",
4940
5188
  identity: ADMIN_SIGNED_IN,
4941
5189
  request: {
4942
- token: ADMIN,
5190
+ token: ADMIN2,
4943
5191
  params: { uid: RESTRICTED_UID },
4944
5192
  body: {
4945
5193
  displayName: "Renamed User",
@@ -4958,7 +5206,7 @@ var SASjsApi = (() => {
4958
5206
  description: "refuses a change to somebody else's account",
4959
5207
  identity: ADMIN_SIGNED_IN,
4960
5208
  request: {
4961
- token: RESTRICTED,
5209
+ token: RESTRICTED2,
4962
5210
  params: { uid: ADMIN_UID },
4963
5211
  body: { displayName: "Hijacked", username: "admin", password: "admin123" }
4964
5212
  },
@@ -4970,7 +5218,7 @@ var SASjsApi = (() => {
4970
5218
  description: "answers 404 with the identifier it looked up",
4971
5219
  identity: ADMIN_SIGNED_IN,
4972
5220
  request: {
4973
- token: ADMIN,
5221
+ token: ADMIN2,
4974
5222
  params: { uid: "user-none" },
4975
5223
  body: { displayName: "Nobody", username: "nobody", password: "none123" }
4976
5224
  },
@@ -4982,7 +5230,7 @@ var SASjsApi = (() => {
4982
5230
  description: "refuses a username change on a provider-managed account",
4983
5231
  identity: PROVIDER_MANAGED,
4984
5232
  request: {
4985
- token: ADMIN,
5233
+ token: ADMIN2,
4986
5234
  params: { uid: "user-directory" },
4987
5235
  body: {
4988
5236
  username: "renamed",
@@ -5001,7 +5249,7 @@ var SASjsApi = (() => {
5001
5249
  description: "refuses a username another account already has",
5002
5250
  identity: ADMIN_SIGNED_IN,
5003
5251
  request: {
5004
- token: ADMIN,
5252
+ token: ADMIN2,
5005
5253
  params: { uid: RESTRICTED_UID },
5006
5254
  body: { username: "admin", displayName: "Demo User", password: "user123" }
5007
5255
  },
@@ -5013,7 +5261,7 @@ var SASjsApi = (() => {
5013
5261
  description: "changes an account looked up by username",
5014
5262
  identity: ADMIN_SIGNED_IN,
5015
5263
  request: {
5016
- token: ADMIN,
5264
+ token: ADMIN2,
5017
5265
  params: { username: "user2" },
5018
5266
  body: {
5019
5267
  isActive: false,
@@ -5030,7 +5278,7 @@ var SASjsApi = (() => {
5030
5278
  description: "refuses a change to another account by username",
5031
5279
  identity: ADMIN_SIGNED_IN,
5032
5280
  request: {
5033
- token: RESTRICTED,
5281
+ token: RESTRICTED2,
5034
5282
  params: { username: "admin" },
5035
5283
  body: { displayName: "Hijacked", username: "admin", password: "admin123" }
5036
5284
  },
@@ -5042,7 +5290,7 @@ var SASjsApi = (() => {
5042
5290
  description: "answers 404 with the username it looked up",
5043
5291
  identity: ADMIN_SIGNED_IN,
5044
5292
  request: {
5045
- token: ADMIN,
5293
+ token: ADMIN2,
5046
5294
  params: { username: "nobody" },
5047
5295
  body: { displayName: "Nobody", username: "nobody", password: "none123" }
5048
5296
  },
@@ -5054,7 +5302,7 @@ var SASjsApi = (() => {
5054
5302
  description: "refuses a display-name change on a provider-managed account",
5055
5303
  identity: PROVIDER_MANAGED,
5056
5304
  request: {
5057
- token: ADMIN,
5305
+ token: ADMIN2,
5058
5306
  params: { username: "diruser" },
5059
5307
  body: { displayName: "Renamed", username: "diruser", password: "dir123" }
5060
5308
  },
@@ -5069,7 +5317,7 @@ var SASjsApi = (() => {
5069
5317
  description: "refuses a username another account already has",
5070
5318
  identity: ADMIN_SIGNED_IN,
5071
5319
  request: {
5072
- token: ADMIN,
5320
+ token: ADMIN2,
5073
5321
  params: { username: "user2" },
5074
5322
  body: { username: "admin", displayName: "Demo User", password: "user123" }
5075
5323
  },
@@ -5080,7 +5328,7 @@ var SASjsApi = (() => {
5080
5328
  route: "DELETE /SASjsApi/user/{uid}",
5081
5329
  description: "deletes an account as an administrator, without a password",
5082
5330
  identity: ADMIN_SIGNED_IN,
5083
- request: { token: ADMIN, params: { uid: RESTRICTED_UID }, body: {} },
5331
+ request: { token: ADMIN2, params: { uid: RESTRICTED_UID }, body: {} },
5084
5332
  expect: { status: 200, body: "Account Deleted!" }
5085
5333
  },
5086
5334
  {
@@ -5088,7 +5336,7 @@ var SASjsApi = (() => {
5088
5336
  route: "DELETE /SASjsApi/user/{uid}",
5089
5337
  description: "refuses a deletion of somebody else's account",
5090
5338
  identity: ADMIN_SIGNED_IN,
5091
- request: { token: RESTRICTED, params: { uid: ADMIN_UID }, body: {} },
5339
+ request: { token: RESTRICTED2, params: { uid: ADMIN_UID }, body: {} },
5092
5340
  expect: { status: 401, error: "Admin account required" }
5093
5341
  },
5094
5342
  {
@@ -5096,7 +5344,7 @@ var SASjsApi = (() => {
5096
5344
  route: "DELETE /SASjsApi/user/{uid}",
5097
5345
  description: "answers 404 for an identifier no account has",
5098
5346
  identity: ADMIN_SIGNED_IN,
5099
- request: { token: ADMIN, params: { uid: "user-none" }, body: {} },
5347
+ request: { token: ADMIN2, params: { uid: "user-none" }, body: {} },
5100
5348
  expect: { status: 404, error: "User is not found." }
5101
5349
  },
5102
5350
  {
@@ -5105,7 +5353,7 @@ var SASjsApi = (() => {
5105
5353
  description: "deletes an account looked up by username",
5106
5354
  identity: ADMIN_SIGNED_IN,
5107
5355
  request: {
5108
- token: ADMIN,
5356
+ token: ADMIN2,
5109
5357
  params: { username: "user2" },
5110
5358
  body: {}
5111
5359
  },
@@ -5117,7 +5365,7 @@ var SASjsApi = (() => {
5117
5365
  description: "refuses a self-deletion whose password is wrong",
5118
5366
  identity: ADMIN_SIGNED_IN,
5119
5367
  request: {
5120
- token: RESTRICTED,
5368
+ token: RESTRICTED2,
5121
5369
  params: { username: "user2" },
5122
5370
  body: { password: "wrong123" }
5123
5371
  },
@@ -5128,7 +5376,7 @@ var SASjsApi = (() => {
5128
5376
  route: "DELETE /SASjsApi/user/by/username/{username}",
5129
5377
  description: "answers 404 for a username no account has",
5130
5378
  identity: ADMIN_SIGNED_IN,
5131
- request: { token: ADMIN, params: { username: "nobody" }, body: {} },
5379
+ request: { token: ADMIN2, params: { username: "nobody" }, body: {} },
5132
5380
  expect: { status: 404, error: "User is not found." }
5133
5381
  },
5134
5382
  // ----------------------------------------------------------------- groups
@@ -5137,7 +5385,7 @@ var SASjsApi = (() => {
5137
5385
  route: "GET /SASjsApi/group",
5138
5386
  description: "lists the groups",
5139
5387
  identity: ADMIN_SIGNED_IN,
5140
- request: { token: RESTRICTED },
5388
+ request: { token: RESTRICTED2 },
5141
5389
  expect: {
5142
5390
  status: 200,
5143
5391
  body: [
@@ -5159,7 +5407,7 @@ var SASjsApi = (() => {
5159
5407
  route: "GET /SASjsApi/group/{uid}",
5160
5408
  description: "returns a group and its members",
5161
5409
  identity: ADMIN_SIGNED_IN,
5162
- request: { token: RESTRICTED, params: { uid: "group-admins" } },
5410
+ request: { token: RESTRICTED2, params: { uid: "group-admins" } },
5163
5411
  expect: {
5164
5412
  status: 200,
5165
5413
  partial: {
@@ -5182,7 +5430,7 @@ var SASjsApi = (() => {
5182
5430
  route: "GET /SASjsApi/group/{uid}",
5183
5431
  description: "answers 404 for an identifier no group has",
5184
5432
  identity: ADMIN_SIGNED_IN,
5185
- request: { token: ADMIN, params: { uid: "group-none" } },
5433
+ request: { token: ADMIN2, params: { uid: "group-none" } },
5186
5434
  expect: { status: 404, error: "Group not found." }
5187
5435
  },
5188
5436
  {
@@ -5190,7 +5438,7 @@ var SASjsApi = (() => {
5190
5438
  route: "GET /SASjsApi/group/by/groupname/{name}",
5191
5439
  description: "finds a group by name",
5192
5440
  identity: ADMIN_SIGNED_IN,
5193
- request: { token: ADMIN, params: { name: "DCGroup" } },
5441
+ request: { token: ADMIN2, params: { name: "DCGroup" } },
5194
5442
  expect: {
5195
5443
  status: 200,
5196
5444
  partial: { uid: "group-data-controller", name: "DCGroup" }
@@ -5201,7 +5449,7 @@ var SASjsApi = (() => {
5201
5449
  route: "GET /SASjsApi/group/by/groupname/{name}",
5202
5450
  description: "answers 404 for a name no group has",
5203
5451
  identity: ADMIN_SIGNED_IN,
5204
- request: { token: ADMIN, params: { name: "nope" } },
5452
+ request: { token: ADMIN2, params: { name: "nope" } },
5205
5453
  expect: { status: 404, error: "Group not found." }
5206
5454
  },
5207
5455
  {
@@ -5210,7 +5458,7 @@ var SASjsApi = (() => {
5210
5458
  description: "creates a group with no members",
5211
5459
  identity: ADMIN_SIGNED_IN,
5212
5460
  request: {
5213
- token: ADMIN,
5461
+ token: ADMIN2,
5214
5462
  body: { name: "NewGroup", description: "A new group", isActive: true }
5215
5463
  },
5216
5464
  expect: {
@@ -5229,7 +5477,7 @@ var SASjsApi = (() => {
5229
5477
  description: "refuses a creation by a caller who is not an administrator",
5230
5478
  identity: ADMIN_SIGNED_IN,
5231
5479
  request: {
5232
- token: RESTRICTED,
5480
+ token: RESTRICTED2,
5233
5481
  body: { name: "NewGroup", description: "x" }
5234
5482
  },
5235
5483
  expect: { status: 401, error: "Admin account required" }
@@ -5239,7 +5487,7 @@ var SASjsApi = (() => {
5239
5487
  route: "POST /SASjsApi/group",
5240
5488
  description: "refuses a name that is taken",
5241
5489
  identity: ADMIN_SIGNED_IN,
5242
- request: { token: ADMIN, body: { name: "DCGroup", description: "again" } },
5490
+ request: { token: ADMIN2, body: { name: "DCGroup", description: "again" } },
5243
5491
  expect: { status: 409, error: "Group name already exists." }
5244
5492
  },
5245
5493
  {
@@ -5248,7 +5496,7 @@ var SASjsApi = (() => {
5248
5496
  description: "adds a member and returns the group",
5249
5497
  identity: ADMIN_SIGNED_IN,
5250
5498
  request: {
5251
- token: ADMIN,
5499
+ token: ADMIN2,
5252
5500
  params: { groupUid: "group-admins", userUid: RESTRICTED_UID }
5253
5501
  },
5254
5502
  expect: {
@@ -5262,7 +5510,7 @@ var SASjsApi = (() => {
5262
5510
  description: "refuses a change to the reserved public group",
5263
5511
  identity: PROVIDER_MANAGED,
5264
5512
  request: {
5265
- token: ADMIN,
5513
+ token: ADMIN2,
5266
5514
  params: { groupUid: "group-public", userUid: RESTRICTED_UID }
5267
5515
  },
5268
5516
  expect: { status: 400, error: "Can't add/remove user to 'public' group." }
@@ -5273,7 +5521,7 @@ var SASjsApi = (() => {
5273
5521
  description: "refuses a membership change by a non-administrator",
5274
5522
  identity: ADMIN_SIGNED_IN,
5275
5523
  request: {
5276
- token: RESTRICTED,
5524
+ token: RESTRICTED2,
5277
5525
  params: { groupUid: "group-admins", userUid: RESTRICTED_UID }
5278
5526
  },
5279
5527
  expect: { status: 401, error: "Admin account required" }
@@ -5284,7 +5532,7 @@ var SASjsApi = (() => {
5284
5532
  description: "answers 404 for a group that does not exist",
5285
5533
  identity: ADMIN_SIGNED_IN,
5286
5534
  request: {
5287
- token: ADMIN,
5535
+ token: ADMIN2,
5288
5536
  params: { groupUid: "group-none", userUid: RESTRICTED_UID }
5289
5537
  },
5290
5538
  expect: { status: 404, error: "Group not found." }
@@ -5295,7 +5543,7 @@ var SASjsApi = (() => {
5295
5543
  description: "refuses a membership change on a provider-managed group",
5296
5544
  identity: PROVIDER_MANAGED,
5297
5545
  request: {
5298
- token: ADMIN,
5546
+ token: ADMIN2,
5299
5547
  params: { groupUid: "group-directory", userUid: RESTRICTED_UID }
5300
5548
  },
5301
5549
  expect: {
@@ -5309,7 +5557,7 @@ var SASjsApi = (() => {
5309
5557
  description: "removes a member and returns the group",
5310
5558
  identity: ADMIN_SIGNED_IN,
5311
5559
  request: {
5312
- token: ADMIN,
5560
+ token: ADMIN2,
5313
5561
  params: { groupUid: "group-data-controller", userUid: RESTRICTED_UID }
5314
5562
  },
5315
5563
  expect: {
@@ -5323,7 +5571,7 @@ var SASjsApi = (() => {
5323
5571
  description: "refuses a membership change for a provider-managed user",
5324
5572
  identity: PROVIDER_MANAGED,
5325
5573
  request: {
5326
- token: ADMIN,
5574
+ token: ADMIN2,
5327
5575
  params: { groupUid: "group-admins", userUid: "user-directory" }
5328
5576
  },
5329
5577
  expect: {
@@ -5337,7 +5585,7 @@ var SASjsApi = (() => {
5337
5585
  description: "refuses a membership change for a provider-managed user",
5338
5586
  identity: PROVIDER_MANAGED,
5339
5587
  request: {
5340
- token: ADMIN,
5588
+ token: ADMIN2,
5341
5589
  params: { groupUid: "group-admins", userUid: "user-directory" }
5342
5590
  },
5343
5591
  expect: {
@@ -5351,7 +5599,7 @@ var SASjsApi = (() => {
5351
5599
  description: "refuses a change to the reserved public group",
5352
5600
  identity: PROVIDER_MANAGED,
5353
5601
  request: {
5354
- token: ADMIN,
5602
+ token: ADMIN2,
5355
5603
  params: { groupUid: "group-public", userUid: RESTRICTED_UID }
5356
5604
  },
5357
5605
  expect: { status: 400, error: "Can't add/remove user to 'public' group." }
@@ -5362,7 +5610,7 @@ var SASjsApi = (() => {
5362
5610
  description: "refuses a membership change by a non-administrator",
5363
5611
  identity: ADMIN_SIGNED_IN,
5364
5612
  request: {
5365
- token: RESTRICTED,
5613
+ token: RESTRICTED2,
5366
5614
  params: { groupUid: "group-data-controller", userUid: RESTRICTED_UID }
5367
5615
  },
5368
5616
  expect: { status: 401, error: "Admin account required" }
@@ -5373,7 +5621,7 @@ var SASjsApi = (() => {
5373
5621
  description: "answers 404 for a member that does not exist",
5374
5622
  identity: ADMIN_SIGNED_IN,
5375
5623
  request: {
5376
- token: ADMIN,
5624
+ token: ADMIN2,
5377
5625
  params: { groupUid: "group-admins", userUid: "user-none" }
5378
5626
  },
5379
5627
  expect: { status: 404, error: "User not found." }
@@ -5384,7 +5632,7 @@ var SASjsApi = (() => {
5384
5632
  description: "refuses a membership change on a provider-managed group",
5385
5633
  identity: PROVIDER_MANAGED,
5386
5634
  request: {
5387
- token: ADMIN,
5635
+ token: ADMIN2,
5388
5636
  params: { groupUid: "group-directory", userUid: RESTRICTED_UID }
5389
5637
  },
5390
5638
  expect: {
@@ -5397,7 +5645,7 @@ var SASjsApi = (() => {
5397
5645
  route: "DELETE /SASjsApi/group/{uid}",
5398
5646
  description: "deletes a group",
5399
5647
  identity: ADMIN_SIGNED_IN,
5400
- request: { token: ADMIN, params: { uid: "group-data-controller" } },
5648
+ request: { token: ADMIN2, params: { uid: "group-data-controller" } },
5401
5649
  expect: { status: 200 }
5402
5650
  },
5403
5651
  {
@@ -5405,7 +5653,7 @@ var SASjsApi = (() => {
5405
5653
  route: "DELETE /SASjsApi/group/{uid}",
5406
5654
  description: "refuses a deletion by a caller who is not an administrator",
5407
5655
  identity: ADMIN_SIGNED_IN,
5408
- request: { token: RESTRICTED, params: { uid: "group-admins" } },
5656
+ request: { token: RESTRICTED2, params: { uid: "group-admins" } },
5409
5657
  expect: { status: 401, error: "Admin account required" }
5410
5658
  },
5411
5659
  {
@@ -5413,7 +5661,7 @@ var SASjsApi = (() => {
5413
5661
  route: "DELETE /SASjsApi/group/{uid}",
5414
5662
  description: "answers 404 for an identifier no group has",
5415
5663
  identity: ADMIN_SIGNED_IN,
5416
- request: { token: ADMIN, params: { uid: "group-none" } },
5664
+ request: { token: ADMIN2, params: { uid: "group-none" } },
5417
5665
  expect: { status: 404, error: "Group not found." }
5418
5666
  },
5419
5667
  // ------------------------------------------------------------ permissions
@@ -5422,7 +5670,7 @@ var SASjsApi = (() => {
5422
5670
  route: "GET /SASjsApi/info/authorizedRoutes",
5423
5671
  description: "answers the routes that accept a rule, to any caller",
5424
5672
  identity: ADMIN_SIGNED_IN,
5425
- request: { token: RESTRICTED },
5673
+ request: { token: RESTRICTED2 },
5426
5674
  expect: {
5427
5675
  status: 200,
5428
5676
  body: {
@@ -5446,7 +5694,7 @@ var SASjsApi = (() => {
5446
5694
  route: "GET /SASjsApi/info/myAuthorizedRoutes",
5447
5695
  description: "answers every route to an administrator",
5448
5696
  identity: ADMIN_SIGNED_IN,
5449
- request: { token: ADMIN },
5697
+ request: { token: ADMIN2 },
5450
5698
  expect: {
5451
5699
  status: 200,
5452
5700
  body: {
@@ -5470,7 +5718,7 @@ var SASjsApi = (() => {
5470
5718
  route: "GET /SASjsApi/info/myAuthorizedRoutes",
5471
5719
  description: "answers a caller only the routes its rules grant",
5472
5720
  identity: ADMIN_SIGNED_IN,
5473
- request: { token: RESTRICTED },
5721
+ request: { token: RESTRICTED2 },
5474
5722
  expect: {
5475
5723
  status: 200,
5476
5724
  // /AppStream is visible whatever the rules say; the two grants come from
@@ -5486,7 +5734,7 @@ var SASjsApi = (() => {
5486
5734
  route: "GET /SASjsApi/permission",
5487
5735
  description: "returns every rule to an administrator",
5488
5736
  identity: ADMIN_SIGNED_IN,
5489
- request: { token: ADMIN },
5737
+ request: { token: ADMIN2 },
5490
5738
  expect: {
5491
5739
  status: 200,
5492
5740
  body: [
@@ -5519,7 +5767,7 @@ var SASjsApi = (() => {
5519
5767
  route: "GET /SASjsApi/permission",
5520
5768
  description: "returns a caller only their own rules and their groups'",
5521
5769
  identity: ADMIN_SIGNED_IN,
5522
- request: { token: RESTRICTED },
5770
+ request: { token: RESTRICTED2 },
5523
5771
  expect: {
5524
5772
  status: 200,
5525
5773
  body: [
@@ -5561,7 +5809,7 @@ var SASjsApi = (() => {
5561
5809
  description: "creates a rule for a user",
5562
5810
  identity: ADMIN_SIGNED_IN,
5563
5811
  request: {
5564
- token: ADMIN,
5812
+ token: ADMIN2,
5565
5813
  body: {
5566
5814
  path: "/SASjsApi/drive/folder",
5567
5815
  type: "Route",
@@ -5581,7 +5829,7 @@ var SASjsApi = (() => {
5581
5829
  description: "creates a rule for a group",
5582
5830
  identity: ADMIN_SIGNED_IN,
5583
5831
  request: {
5584
- token: ADMIN,
5832
+ token: ADMIN2,
5585
5833
  body: {
5586
5834
  path: "/SASjsApi/drive/rename",
5587
5835
  type: "Route",
@@ -5605,7 +5853,7 @@ var SASjsApi = (() => {
5605
5853
  description: "refuses a principal type that is neither a user nor a group",
5606
5854
  identity: ADMIN_SIGNED_IN,
5607
5855
  request: {
5608
- token: ADMIN,
5856
+ token: ADMIN2,
5609
5857
  body: {
5610
5858
  path: "/SASjsApi/drive/deploy",
5611
5859
  type: "Route",
@@ -5625,7 +5873,7 @@ var SASjsApi = (() => {
5625
5873
  description: "refuses a rule assigned to an administrator",
5626
5874
  identity: ADMIN_SIGNED_IN,
5627
5875
  request: {
5628
- token: ADMIN,
5876
+ token: ADMIN2,
5629
5877
  body: {
5630
5878
  path: "/SASjsApi/drive/folder",
5631
5879
  type: "Route",
@@ -5645,7 +5893,7 @@ var SASjsApi = (() => {
5645
5893
  description: "refuses a creation by a non-administrator",
5646
5894
  identity: ADMIN_SIGNED_IN,
5647
5895
  request: {
5648
- token: RESTRICTED,
5896
+ token: RESTRICTED2,
5649
5897
  body: {
5650
5898
  path: "/SASjsApi/drive/folder",
5651
5899
  type: "Route",
@@ -5662,7 +5910,7 @@ var SASjsApi = (() => {
5662
5910
  description: "answers 404 for a principal that does not exist",
5663
5911
  identity: ADMIN_SIGNED_IN,
5664
5912
  request: {
5665
- token: ADMIN,
5913
+ token: ADMIN2,
5666
5914
  body: {
5667
5915
  path: "/SASjsApi/drive/rename",
5668
5916
  type: "Route",
@@ -5679,7 +5927,7 @@ var SASjsApi = (() => {
5679
5927
  description: "refuses a group rule that already exists",
5680
5928
  identity: ADMIN_SIGNED_IN,
5681
5929
  request: {
5682
- token: ADMIN,
5930
+ token: ADMIN2,
5683
5931
  body: {
5684
5932
  path: "/SASjsApi/drive/file",
5685
5933
  type: "Route",
@@ -5699,7 +5947,7 @@ var SASjsApi = (() => {
5699
5947
  description: "refuses a rule that already exists",
5700
5948
  identity: ADMIN_SIGNED_IN,
5701
5949
  request: {
5702
- token: ADMIN,
5950
+ token: ADMIN2,
5703
5951
  body: {
5704
5952
  path: "/SASjsApi/code/execute",
5705
5953
  type: "Route",
@@ -5719,7 +5967,7 @@ var SASjsApi = (() => {
5719
5967
  description: "flips a rule from Deny to Grant",
5720
5968
  identity: ADMIN_SIGNED_IN,
5721
5969
  request: {
5722
- token: ADMIN,
5970
+ token: ADMIN2,
5723
5971
  params: { uid: "rule-code" },
5724
5972
  body: { setting: "Grant" }
5725
5973
  },
@@ -5731,7 +5979,7 @@ var SASjsApi = (() => {
5731
5979
  description: "refuses a change by a non-administrator",
5732
5980
  identity: ADMIN_SIGNED_IN,
5733
5981
  request: {
5734
- token: RESTRICTED,
5982
+ token: RESTRICTED2,
5735
5983
  params: { uid: "rule-code" },
5736
5984
  body: { setting: "Grant" }
5737
5985
  },
@@ -5743,7 +5991,7 @@ var SASjsApi = (() => {
5743
5991
  description: "answers 404 for a rule that does not exist",
5744
5992
  identity: ADMIN_SIGNED_IN,
5745
5993
  request: {
5746
- token: ADMIN,
5994
+ token: ADMIN2,
5747
5995
  params: { uid: "rule-none" },
5748
5996
  body: { setting: "Grant" }
5749
5997
  },
@@ -5754,7 +6002,7 @@ var SASjsApi = (() => {
5754
6002
  route: "DELETE /SASjsApi/permission/{uid}",
5755
6003
  description: "deletes a rule",
5756
6004
  identity: ADMIN_SIGNED_IN,
5757
- request: { token: ADMIN, params: { uid: "rule-code" } },
6005
+ request: { token: ADMIN2, params: { uid: "rule-code" } },
5758
6006
  expect: { status: 200, body: "Permission Deleted!" }
5759
6007
  },
5760
6008
  {
@@ -5762,7 +6010,7 @@ var SASjsApi = (() => {
5762
6010
  route: "DELETE /SASjsApi/permission/{uid}",
5763
6011
  description: "refuses a deletion by a non-administrator",
5764
6012
  identity: ADMIN_SIGNED_IN,
5765
- request: { token: RESTRICTED, params: { uid: "rule-code" } },
6013
+ request: { token: RESTRICTED2, params: { uid: "rule-code" } },
5766
6014
  expect: { status: 401, error: "Admin account required" }
5767
6015
  },
5768
6016
  {
@@ -5770,7 +6018,7 @@ var SASjsApi = (() => {
5770
6018
  route: "DELETE /SASjsApi/permission/{uid}",
5771
6019
  description: "answers 404 for a rule that does not exist",
5772
6020
  identity: ADMIN_SIGNED_IN,
5773
- request: { token: ADMIN, params: { uid: "rule-none" } },
6021
+ request: { token: ADMIN2, params: { uid: "rule-none" } },
5774
6022
  expect: { status: 404, error: "Permission not found." }
5775
6023
  },
5776
6024
  // --------------------------------------------------------------- clients
@@ -5779,7 +6027,7 @@ var SASjsApi = (() => {
5779
6027
  route: "GET /SASjsApi/client",
5780
6028
  description: "lists the registered clients",
5781
6029
  identity: ADMIN_SIGNED_IN,
5782
- request: { token: ADMIN },
6030
+ request: { token: ADMIN2 },
5783
6031
  expect: {
5784
6032
  status: 200,
5785
6033
  body: [
@@ -5803,7 +6051,7 @@ var SASjsApi = (() => {
5803
6051
  route: "GET /SASjsApi/client",
5804
6052
  description: "refuses the list to a caller who is not an administrator",
5805
6053
  identity: ADMIN_SIGNED_IN,
5806
- request: { token: RESTRICTED },
6054
+ request: { token: RESTRICTED2 },
5807
6055
  expect: { status: 401, error: "Admin account required" }
5808
6056
  },
5809
6057
  {
@@ -5812,7 +6060,7 @@ var SASjsApi = (() => {
5812
6060
  description: "registers a client",
5813
6061
  identity: ADMIN_SIGNED_IN,
5814
6062
  request: {
5815
- token: ADMIN,
6063
+ token: ADMIN2,
5816
6064
  body: {
5817
6065
  clientId: "new_app",
5818
6066
  clientSecret: "new_secret",
@@ -5836,7 +6084,7 @@ var SASjsApi = (() => {
5836
6084
  description: "applies the schema defaults when the lifetimes are omitted",
5837
6085
  identity: ADMIN_SIGNED_IN,
5838
6086
  request: {
5839
- token: ADMIN,
6087
+ token: ADMIN2,
5840
6088
  body: { clientId: "default_app", clientSecret: "default_secret" }
5841
6089
  },
5842
6090
  expect: {
@@ -5855,7 +6103,7 @@ var SASjsApi = (() => {
5855
6103
  description: "refuses a registration by a non-administrator",
5856
6104
  identity: ADMIN_SIGNED_IN,
5857
6105
  request: {
5858
- token: RESTRICTED,
6106
+ token: RESTRICTED2,
5859
6107
  body: {
5860
6108
  clientId: "new_app",
5861
6109
  clientSecret: "new_secret",
@@ -5871,7 +6119,7 @@ var SASjsApi = (() => {
5871
6119
  description: "refuses a client id that is registered, with the 403 the server sends",
5872
6120
  identity: ADMIN_SIGNED_IN,
5873
6121
  request: {
5874
- token: ADMIN,
6122
+ token: ADMIN2,
5875
6123
  body: {
5876
6124
  clientId: "web_app",
5877
6125
  clientSecret: "other",
@@ -5888,7 +6136,7 @@ var SASjsApi = (() => {
5888
6136
  description: "changes the caller’s own password",
5889
6137
  identity: ADMIN_SIGNED_IN,
5890
6138
  request: {
5891
- token: RESTRICTED,
6139
+ token: RESTRICTED2,
5892
6140
  body: { currentPassword: "user123", newPassword: "changed123" }
5893
6141
  },
5894
6142
  expect: { status: 204 }
@@ -5898,7 +6146,7 @@ var SASjsApi = (() => {
5898
6146
  route: "PATCH /SASjsApi/auth/updatePassword",
5899
6147
  description: "refuses a body without the current password",
5900
6148
  identity: ADMIN_SIGNED_IN,
5901
- request: { token: RESTRICTED, body: { newPassword: "changed123" } },
6149
+ request: { token: RESTRICTED2, body: { newPassword: "changed123" } },
5902
6150
  expect: { status: 400, error: '"currentPassword" is required' }
5903
6151
  },
5904
6152
  {
@@ -5917,7 +6165,7 @@ var SASjsApi = (() => {
5917
6165
  description: "refuses a change whose current password is wrong",
5918
6166
  identity: ADMIN_SIGNED_IN,
5919
6167
  request: {
5920
- token: RESTRICTED,
6168
+ token: RESTRICTED2,
5921
6169
  body: { currentPassword: "wrong", newPassword: "changed123" }
5922
6170
  },
5923
6171
  expect: { status: 403, error: "Invalid current password!" }
@@ -5938,6 +6186,112 @@ var SASjsApi = (() => {
5938
6186
  }
5939
6187
  ];
5940
6188
 
6189
+ // src/session/service.ts
6190
+ var createSessionService = (store, host) => {
6191
+ const notFound = (id) => `Session with ID '${id}' was not found.`;
6192
+ const visible = async (caller, id) => {
6193
+ if (!caller) throw new ApiError(401, "Unauthorized");
6194
+ const reader = await store.userById(
6195
+ caller.userId
6196
+ );
6197
+ if (!reader || !reader.isActive) throw new ApiError(401, "Unauthorized");
6198
+ const session = await host.session(id);
6199
+ if (!session) throw new ApiError(404, notFound(id));
6200
+ const owner = session.owner;
6201
+ if (owner !== reader.uid && owner !== reader.username && !reader.isAdmin)
6202
+ throw new ApiError(404, notFound(id));
6203
+ return session;
6204
+ };
6205
+ return {
6206
+ async summary(caller, id) {
6207
+ const session = await visible(caller, id);
6208
+ return session.summary;
6209
+ },
6210
+ async state(caller, id) {
6211
+ await visible(caller, id);
6212
+ const state = await host.state(id);
6213
+ if (!state) throw new ApiError(404, notFound(id));
6214
+ return state;
6215
+ },
6216
+ async log(caller, id) {
6217
+ await visible(caller, id);
6218
+ const log = await host.log(id);
6219
+ if (log === void 0) throw new ApiError(404, notFound(id));
6220
+ return log;
6221
+ },
6222
+ async output(caller, id) {
6223
+ await visible(caller, id);
6224
+ const output = await host.output(id);
6225
+ if (output === void 0) throw new ApiError(404, notFound(id));
6226
+ return output;
6227
+ }
6228
+ };
6229
+ };
6230
+
6231
+ // src/session/memory-host.ts
6232
+ var DEFAULT_SESSIONS = {
6233
+ "sess-admin": {
6234
+ owner: "user-admin",
6235
+ summary: {
6236
+ sessionId: "sess-admin",
6237
+ state: "completed",
6238
+ pid: 4242,
6239
+ creationTimeStamp: "2026-11-07T09:00:00.000Z",
6240
+ deathTimeStamp: "2026-11-07T09:00:04.000Z",
6241
+ expiresAfterMins: 60
6242
+ }
6243
+ },
6244
+ "sess-restricted": {
6245
+ owner: "user-restricted",
6246
+ summary: {
6247
+ sessionId: "sess-restricted",
6248
+ state: "running",
6249
+ pid: 4243,
6250
+ creationTimeStamp: "2026-11-07T09:05:00.000Z"
6251
+ }
6252
+ },
6253
+ "sess-silent": {
6254
+ owner: "user-admin",
6255
+ summary: {
6256
+ sessionId: "sess-silent",
6257
+ state: "running",
6258
+ pid: 4244,
6259
+ creationTimeStamp: "2026-11-07T09:10:00.000Z"
6260
+ }
6261
+ }
6262
+ };
6263
+ var STATES = {
6264
+ "sess-admin": { state: "completed", pid: 4242, lineCount: 12 },
6265
+ "sess-restricted": { state: "running", pid: 4243, lineCount: 3 }
6266
+ };
6267
+ var LOGS = {
6268
+ "sess-admin": "NOTE: session started\nNOTE: session completed\n",
6269
+ "sess-restricted": "NOTE: session started\n",
6270
+ "sess-silent": ""
6271
+ };
6272
+ var OUTPUTS = {
6273
+ "sess-admin": "<html><body>42</body></html>",
6274
+ "sess-restricted": "",
6275
+ "sess-silent": ""
6276
+ };
6277
+ var MemorySessionHost = class {
6278
+ constructor(sessions = DEFAULT_SESSIONS) {
6279
+ this.sessions = sessions;
6280
+ }
6281
+ async session(id) {
6282
+ return this.sessions[id];
6283
+ }
6284
+ async state(id) {
6285
+ return STATES[id];
6286
+ }
6287
+ async log(id) {
6288
+ return LOGS[id];
6289
+ }
6290
+ async output(id) {
6291
+ return OUTPUTS[id];
6292
+ }
6293
+ };
6294
+
5941
6295
  // src/corpus/runner.ts
5942
6296
  var servicesFor = (testCase) => {
5943
6297
  const identity = new MemoryIdentityStore(
@@ -5948,7 +6302,8 @@ var SASjsApi = (() => {
5948
6302
  testCase.unwritable ? new RefusingDriveStore(testCase.seed || {}) : new MemoryDriveStore(testCase.seed || {})
5949
6303
  ),
5950
6304
  identity: createIdentityService(identity),
5951
- records: createRecordService(identity)
6305
+ records: createRecordService(identity),
6306
+ session: createSessionService(identity, new MemorySessionHost())
5952
6307
  };
5953
6308
  };
5954
6309
  var RefusingDriveStore = class extends MemoryDriveStore {