alp-node-auth 12.0.1 → 13.1.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.
@@ -0,0 +1,94 @@
1
+ import assert from "node:assert/strict";
2
+ import { test } from "node:test";
3
+ // eslint-disable-next-line import-x/no-unresolved
4
+ import { createRouterBuilder } from "router-segments";
5
+ // eslint-disable-next-line import-x/extensions
6
+ import type { AuthController } from "./createAuthController.ts";
7
+ // eslint-disable-next-line import-x/extensions
8
+ import { createRoutes } from "./createRoutes.ts";
9
+
10
+ const createControllerMock = (): AuthController => ({
11
+ login: () => undefined,
12
+ addScope: () => undefined,
13
+ response: () => undefined,
14
+ logout: () => undefined,
15
+ });
16
+
17
+ type AuthRouteRef = (segment: any) => void;
18
+
19
+ const buildRouter = (routes: ReturnType<typeof createRoutes>) => {
20
+ const builder = createRouterBuilder<never, unknown>();
21
+ for (const [path, refOrSegment] of Object.values(routes)) {
22
+ if (refOrSegment.length === 1) {
23
+ builder.addSegment(path, refOrSegment as AuthRouteRef);
24
+ } else {
25
+ builder.add(path, refOrSegment);
26
+ }
27
+ }
28
+ return builder.createRouter();
29
+ };
30
+
31
+ test("returns the expected route keys", () => {
32
+ const routes = createRoutes(createControllerMock());
33
+ assert.deepEqual(Object.keys(routes), ["login", "addScope", "logout"]);
34
+ });
35
+
36
+ test("maps each route to its path", () => {
37
+ const routes = createRoutes(createControllerMock());
38
+ assert.equal(routes.login[0], "/login{/:strategy}");
39
+ assert.equal(routes.addScope[0], "/add-scope/:strategy/:scopeKey");
40
+ assert.equal(routes.logout[0], "/logout");
41
+ });
42
+
43
+ test("wires addScope and logout to the controller refs", () => {
44
+ const controller = createControllerMock();
45
+ const routes = createRoutes(controller);
46
+ assert.equal(routes.addScope[1], controller.addScope);
47
+ assert.equal(routes.logout[1], controller.logout);
48
+ });
49
+
50
+ test("login route builds into a router with an optional strategy param", () => {
51
+ const controller = createControllerMock();
52
+ const router = buildRouter(createRoutes(controller));
53
+
54
+ assert.equal(router.toPath("login"), "/login");
55
+
56
+ const withoutStrategy = router.find("/login");
57
+ assert.ok(withoutStrategy, "expected /login to match");
58
+ assert.equal(withoutStrategy.ref, controller.login);
59
+
60
+ const withStrategy = router.find("/login/google");
61
+ assert.ok(withStrategy, "expected /login/google to match");
62
+ assert.equal(withStrategy.ref, controller.login);
63
+ assert.equal(withStrategy.namedParams?.get("strategy"), "google");
64
+ });
65
+
66
+ test("login segment registers the response sub-route", () => {
67
+ const controller = createControllerMock();
68
+ const router = buildRouter(createRoutes(controller));
69
+
70
+ const response = router.find("/login/google/response");
71
+ assert.ok(response, "expected /login/google/response to match");
72
+ assert.equal(response.ref, controller.response);
73
+ assert.equal(response.namedParams?.get("strategy"), "google");
74
+ });
75
+
76
+ test("addScope route resolves both named params", () => {
77
+ const controller = createControllerMock();
78
+ const router = buildRouter(createRoutes(controller));
79
+
80
+ const match = router.find("/add-scope/google/calendar");
81
+ assert.ok(match, "expected /add-scope/google/calendar to match");
82
+ assert.equal(match.ref, controller.addScope);
83
+ assert.equal(match.namedParams?.get("strategy"), "google");
84
+ assert.equal(match.namedParams?.get("scopeKey"), "calendar");
85
+ });
86
+
87
+ test("logout route resolves to the controller ref", () => {
88
+ const controller = createControllerMock();
89
+ const router = buildRouter(createRoutes(controller));
90
+
91
+ const match = router.find("/logout");
92
+ assert.ok(match, "expected /logout to match");
93
+ assert.equal(match.ref, controller.logout);
94
+ });
@@ -8,7 +8,7 @@ export interface AuthRoutes {
8
8
 
9
9
  export const createRoutes = (controller: AuthController): AuthRoutes => ({
10
10
  login: [
11
- "/login/:strategy?",
11
+ "/login{/:strategy}",
12
12
  (segment: any) => {
13
13
  segment.add("/response", controller.response, "authResponse");
14
14
  segment.defaultRoute(controller.login, "login");
package/src/index.ts CHANGED
@@ -2,6 +2,7 @@ import type { IncomingMessage } from "node:http";
2
2
  import { promisify } from "node:util";
3
3
  import type { Context, ContextState, NodeApplication } from "alp-node";
4
4
  import jsonwebtoken from "jsonwebtoken";
5
+ // eslint-disable-next-line import-x/no-unresolved
5
6
  import { Logger } from "nightingale-logger";
6
7
  import type MongoUsersManager from "./MongoUsersManager";
7
8
  import type {
@@ -4,6 +4,7 @@
4
4
  /* eslint-disable camelcase */
5
5
  import { EventEmitter } from "node:events";
6
6
  import type { Context, NodeConfig } from "alp-node";
7
+ // eslint-disable-next-line import-x/no-unresolved
7
8
  import { Logger } from "nightingale-logger";
8
9
  import type { Strategy as Oauth2Strategy } from "../../../strategies/strategies.d";
9
10
  import type { Account, AccountId, User, UserSanitized } from "../../types";
@@ -3,9 +3,9 @@
3
3
  import type { Tokens } from "../authentification/types";
4
4
  import type { AccountService, FullName } from "./types";
5
5
 
6
- export default class UserAccountGoogleService<ScopeKeys extends "login">
7
- implements AccountService<ScopeKeys>
8
- {
6
+ export default class UserAccountGoogleService<
7
+ ScopeKeys extends "login",
8
+ > implements AccountService<ScopeKeys> {
9
9
  scopeKeyToScope: Record<ScopeKeys, string>;
10
10
 
11
11
  constructor(scopeKeyToScope: Record<Exclude<"login", ScopeKeys>, string>) {
@@ -4,9 +4,9 @@ import type { AccountService, FullName } from "./types";
4
4
 
5
5
  // https://api.slack.com/methods/users.identity
6
6
 
7
- export default class UserAccountSlackService<ScopeKeys extends "login">
8
- implements AccountService<ScopeKeys>
9
- {
7
+ export default class UserAccountSlackService<
8
+ ScopeKeys extends "login",
9
+ > implements AccountService<ScopeKeys> {
10
10
  scopeKeyToScope: Record<ScopeKeys, string>;
11
11
 
12
12
  constructor(scopeKeyToScope: Record<Exclude<"login", ScopeKeys>, string>) {
@@ -1,4 +1,5 @@
1
1
  import { EventEmitter } from "node:events";
2
+ // eslint-disable-next-line import-x/no-unresolved
2
3
  import { Logger } from "nightingale-logger";
3
4
  import type MongoUsersManager from "../../MongoUsersManager";
4
5
  import type { Account, AccountId, User, UserSanitized } from "../../types";