@checkstack/auth-backend 0.4.11 → 0.4.12
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/CHANGELOG.md +12 -0
- package/package.json +9 -9
- package/src/index.ts +77 -5
- package/src/router.test.ts +38 -7
- package/src/router.ts +181 -42
- package/src/teams.test.ts +84 -42
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @checkstack/auth-backend
|
|
2
2
|
|
|
3
|
+
## 0.4.12
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- c0c0ed2: Introduce generic "Login Flows" to allow authentication strategies to define their own interaction patterns (form, redirect, or oauth) during registration. This fixes an issue where LDAP login attempts were incorrectly routed through the standard social login flow by instead providing a dedicated credential collection form for LDAP.
|
|
8
|
+
- c0c0ed2: Refactor manual session creation to use a secure, bridged oRPC endpoint. This ensures that custom authentication strategies (LDAP, SAML) leverage Better-Auth's native session establishment utilities, including cryptographic signing and reliable cookie attribute management.
|
|
9
|
+
- Updated dependencies [c0c0ed2]
|
|
10
|
+
- Updated dependencies [c0c0ed2]
|
|
11
|
+
- @checkstack/backend-api@0.9.0
|
|
12
|
+
- @checkstack/auth-common@0.6.0
|
|
13
|
+
- @checkstack/command-backend@0.1.14
|
|
14
|
+
|
|
3
15
|
## 0.4.11
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@checkstack/auth-backend",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.12",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"checkstack": {
|
|
@@ -14,22 +14,22 @@
|
|
|
14
14
|
"test": "bun test"
|
|
15
15
|
},
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@checkstack/auth-common": "0.5.
|
|
18
|
-
"@checkstack/backend-api": "0.8.
|
|
19
|
-
"@checkstack/notification-common": "0.2.
|
|
20
|
-
"@checkstack/command-backend": "0.1.
|
|
17
|
+
"@checkstack/auth-common": "0.5.7",
|
|
18
|
+
"@checkstack/backend-api": "0.8.2",
|
|
19
|
+
"@checkstack/notification-common": "0.2.7",
|
|
20
|
+
"@checkstack/command-backend": "0.1.13",
|
|
21
21
|
"better-auth": "^1.4.7",
|
|
22
22
|
"drizzle-orm": "^0.45.0",
|
|
23
23
|
"hono": "^4.12.14",
|
|
24
24
|
"jose": "^6.1.3",
|
|
25
25
|
"zod": "^4.2.1",
|
|
26
|
-
"@checkstack/common": "0.6.
|
|
26
|
+
"@checkstack/common": "0.6.4",
|
|
27
27
|
"@orpc/server": "^1.13.2"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@checkstack/drizzle-helper": "0.0.
|
|
31
|
-
"@checkstack/scripts": "0.1.
|
|
32
|
-
"@checkstack/tsconfig": "0.0.
|
|
30
|
+
"@checkstack/drizzle-helper": "0.0.4",
|
|
31
|
+
"@checkstack/scripts": "0.1.2",
|
|
32
|
+
"@checkstack/tsconfig": "0.0.4",
|
|
33
33
|
"@types/node": "^20.0.0",
|
|
34
34
|
"typescript": "^5.0.0"
|
|
35
35
|
}
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { betterAuth } from "better-auth";
|
|
2
2
|
import * as socialProviderFactories from "better-auth/social-providers";
|
|
3
3
|
import { drizzleAdapter } from "better-auth/adapters/drizzle";
|
|
4
|
-
import { APIError } from "better-auth/api";
|
|
4
|
+
import { APIError, createAuthEndpoint } from "better-auth/api";
|
|
5
|
+
import { setSessionCookie } from "better-auth/cookies";
|
|
6
|
+
import { z } from "zod";
|
|
5
7
|
import {
|
|
6
8
|
createBackendPlugin,
|
|
7
9
|
coreServices,
|
|
@@ -549,6 +551,74 @@ export default createBackendPlugin({
|
|
|
549
551
|
// Default to true on fresh installs (no meta config)
|
|
550
552
|
const credentialEnabled = credentialMetaConfig?.enabled ?? true;
|
|
551
553
|
|
|
554
|
+
const baseUrl = process.env.BASE_URL;
|
|
555
|
+
if (!baseUrl) {
|
|
556
|
+
throw new Error(
|
|
557
|
+
"[auth-backend] BASE_URL environment variable is not defined.",
|
|
558
|
+
);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
const betterAuthSecret = process.env.BETTER_AUTH_SECRET;
|
|
562
|
+
if (!betterAuthSecret) {
|
|
563
|
+
throw new Error(
|
|
564
|
+
"[auth-backend] BETTER_AUTH_SECRET environment variable is not defined.",
|
|
565
|
+
);
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
const checkstackBridge = {
|
|
569
|
+
id: "checkstack-bridge",
|
|
570
|
+
endpoints: {
|
|
571
|
+
trustedLogin: createAuthEndpoint(
|
|
572
|
+
"/internal/trusted-login",
|
|
573
|
+
{
|
|
574
|
+
method: "POST",
|
|
575
|
+
body: z.object({ userId: z.string() }),
|
|
576
|
+
},
|
|
577
|
+
async (ctx) => {
|
|
578
|
+
const secretHeader = ctx.request?.headers.get(
|
|
579
|
+
"x-checkstack-internal",
|
|
580
|
+
);
|
|
581
|
+
if (
|
|
582
|
+
!secretHeader ||
|
|
583
|
+
secretHeader !== betterAuthSecret
|
|
584
|
+
) {
|
|
585
|
+
throw new APIError("UNAUTHORIZED");
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
const { userId } = ctx.body;
|
|
589
|
+
const ipAddress =
|
|
590
|
+
ctx.request?.headers
|
|
591
|
+
.get("x-forwarded-for")
|
|
592
|
+
?.split(",")[0]
|
|
593
|
+
.trim() || undefined;
|
|
594
|
+
const userAgent =
|
|
595
|
+
ctx.request?.headers.get("user-agent") || undefined;
|
|
596
|
+
|
|
597
|
+
const session =
|
|
598
|
+
await ctx.context.internalAdapter.createSession(
|
|
599
|
+
userId,
|
|
600
|
+
false,
|
|
601
|
+
{
|
|
602
|
+
ipAddress,
|
|
603
|
+
userAgent,
|
|
604
|
+
},
|
|
605
|
+
);
|
|
606
|
+
const user =
|
|
607
|
+
await ctx.context.internalAdapter.findUserById(userId);
|
|
608
|
+
|
|
609
|
+
if (!user) {
|
|
610
|
+
throw new APIError("NOT_FOUND", {
|
|
611
|
+
message: "User not found",
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
await setSessionCookie(ctx, { session, user });
|
|
616
|
+
return ctx.json({ success: true, sessionId: session.id });
|
|
617
|
+
},
|
|
618
|
+
),
|
|
619
|
+
},
|
|
620
|
+
};
|
|
621
|
+
|
|
552
622
|
// Check platform registration setting
|
|
553
623
|
const platformRegistrationConfig = await config.get(
|
|
554
624
|
PLATFORM_REGISTRATION_CONFIG_ID,
|
|
@@ -579,8 +649,7 @@ export default createBackendPlugin({
|
|
|
579
649
|
// Send password reset notification via all enabled strategies
|
|
580
650
|
// Using void to prevent timing attacks revealing email existence
|
|
581
651
|
const notificationClient = rpcClient.forPlugin(NotificationApi);
|
|
582
|
-
const frontendUrl =
|
|
583
|
-
process.env.BASE_URL || "http://localhost:5173";
|
|
652
|
+
const frontendUrl = baseUrl;
|
|
584
653
|
// SECURITY: Use URL parsing instead of brittle string splitting
|
|
585
654
|
const parsedUrl = new URL(url);
|
|
586
655
|
const resetToken = parsedUrl.searchParams.get("token");
|
|
@@ -614,8 +683,8 @@ export default createBackendPlugin({
|
|
|
614
683
|
},
|
|
615
684
|
socialProviders,
|
|
616
685
|
basePath: "/api/auth",
|
|
617
|
-
baseURL:
|
|
618
|
-
trustedOrigins: [
|
|
686
|
+
baseURL: baseUrl,
|
|
687
|
+
trustedOrigins: [baseUrl],
|
|
619
688
|
databaseHooks: {
|
|
620
689
|
user: {
|
|
621
690
|
create: {
|
|
@@ -651,6 +720,7 @@ export default createBackendPlugin({
|
|
|
651
720
|
},
|
|
652
721
|
},
|
|
653
722
|
},
|
|
723
|
+
plugins: [checkstackBridge],
|
|
654
724
|
};
|
|
655
725
|
|
|
656
726
|
return betterAuth(authOptions);
|
|
@@ -737,6 +807,8 @@ export default createBackendPlugin({
|
|
|
737
807
|
reloadAuth,
|
|
738
808
|
config,
|
|
739
809
|
accessRuleRegistry,
|
|
810
|
+
() => auth,
|
|
811
|
+
logger,
|
|
740
812
|
);
|
|
741
813
|
rpc.registerRouter(authRouter, authContract);
|
|
742
814
|
|
package/src/router.test.ts
CHANGED
|
@@ -89,6 +89,7 @@ describe("Auth Router", () => {
|
|
|
89
89
|
async () => {},
|
|
90
90
|
mockConfigService,
|
|
91
91
|
mockAccessRuleRegistry,
|
|
92
|
+
() => undefined,
|
|
92
93
|
);
|
|
93
94
|
|
|
94
95
|
it("getAccessRules returns current user access rules", async () => {
|
|
@@ -349,23 +350,53 @@ describe("Auth Router", () => {
|
|
|
349
350
|
expect(mockDb.update).toHaveBeenCalled();
|
|
350
351
|
});
|
|
351
352
|
|
|
352
|
-
it("createSession
|
|
353
|
+
it("createSession calls the internal auth bridge", async () => {
|
|
353
354
|
const context = createMockRpcContext({ user: mockServiceUser });
|
|
354
355
|
|
|
355
|
-
|
|
356
|
+
// Setup environment variables for the bridge call
|
|
357
|
+
process.env.BASE_URL = "http://localhost:3000";
|
|
358
|
+
process.env.BETTER_AUTH_SECRET = "test-secret";
|
|
359
|
+
|
|
360
|
+
const mockResponse = { sessionId: "session-123" };
|
|
361
|
+
const mockHandler = mock(async (_req: Request) => {
|
|
362
|
+
return new Response(JSON.stringify(mockResponse), {
|
|
363
|
+
status: 200,
|
|
364
|
+
headers: {
|
|
365
|
+
"Set-Cookie": "better-auth.session_token=test-token; Path=/; HttpOnly",
|
|
366
|
+
},
|
|
367
|
+
});
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
// We need to use a router instance that has access to our mock handler
|
|
371
|
+
const testRouter = createAuthRouter(
|
|
372
|
+
mockDb,
|
|
373
|
+
mockRegistry,
|
|
374
|
+
async () => {},
|
|
375
|
+
mockConfigService,
|
|
376
|
+
mockAccessRuleRegistry,
|
|
377
|
+
() => ({ handler: mockHandler }),
|
|
378
|
+
);
|
|
356
379
|
|
|
357
380
|
const result = await call(
|
|
358
|
-
|
|
381
|
+
testRouter.createSession,
|
|
359
382
|
{
|
|
360
383
|
userId: "user-123",
|
|
361
|
-
token: "session-token",
|
|
362
|
-
expiresAt,
|
|
363
384
|
},
|
|
364
385
|
{ context },
|
|
365
386
|
);
|
|
366
387
|
|
|
367
|
-
expect(result.sessionId).
|
|
368
|
-
expect(
|
|
388
|
+
expect(result.sessionId).toBe("session-123");
|
|
389
|
+
expect(result.setCookie).toContain("better-auth.session_token=test-token");
|
|
390
|
+
expect(mockHandler).toHaveBeenCalled();
|
|
391
|
+
|
|
392
|
+
// Verify the virtual request headers
|
|
393
|
+
const lastCall = mockHandler.mock.calls[0][0] as unknown as Request;
|
|
394
|
+
expect(lastCall.headers.get("Host")).toBe("localhost:3000");
|
|
395
|
+
expect(lastCall.url).toBe("http://localhost:3000/api/auth/internal/trusted-login");
|
|
396
|
+
|
|
397
|
+
// Cleanup environment variables
|
|
398
|
+
delete process.env.BASE_URL;
|
|
399
|
+
delete process.env.BETTER_AUTH_SECRET;
|
|
369
400
|
});
|
|
370
401
|
|
|
371
402
|
it("upsertExternalUser syncs roles when syncRoles provided for new user", async () => {
|
package/src/router.ts
CHANGED
|
@@ -8,7 +8,12 @@ import {
|
|
|
8
8
|
type ConfigService,
|
|
9
9
|
toJsonSchema,
|
|
10
10
|
} from "@checkstack/backend-api";
|
|
11
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
authContract,
|
|
13
|
+
passwordSchema,
|
|
14
|
+
authAccess,
|
|
15
|
+
pluginMetadata,
|
|
16
|
+
} from "@checkstack/auth-common";
|
|
12
17
|
import { qualifyAccessRuleId } from "@checkstack/common";
|
|
13
18
|
import { hashPassword } from "better-auth/crypto";
|
|
14
19
|
import * as schema from "./schema";
|
|
@@ -132,7 +137,9 @@ async function assertTeamManagementAccess({
|
|
|
132
137
|
|
|
133
138
|
const hasGlobalManage =
|
|
134
139
|
user?.accessRules?.includes("*") ||
|
|
135
|
-
user?.accessRules?.includes(
|
|
140
|
+
user?.accessRules?.includes(
|
|
141
|
+
qualifyAccessRuleId(pluginMetadata, authAccess.teams.manage),
|
|
142
|
+
);
|
|
136
143
|
|
|
137
144
|
if (hasGlobalManage) return; // Global manage allows all teams
|
|
138
145
|
|
|
@@ -157,6 +164,12 @@ async function assertTeamManagementAccess({
|
|
|
157
164
|
});
|
|
158
165
|
}
|
|
159
166
|
|
|
167
|
+
const DEFAULT_LOGGER = {
|
|
168
|
+
info: () => {},
|
|
169
|
+
error: () => {},
|
|
170
|
+
debug: () => {},
|
|
171
|
+
};
|
|
172
|
+
|
|
160
173
|
export const createAuthRouter = (
|
|
161
174
|
internalDb: SafeDatabase<typeof schema>,
|
|
162
175
|
strategyRegistry: { getStrategies: () => AuthStrategy<unknown>[] },
|
|
@@ -170,6 +183,14 @@ export const createAuthRouter = (
|
|
|
170
183
|
isPublic?: boolean;
|
|
171
184
|
}[];
|
|
172
185
|
},
|
|
186
|
+
getBetterAuth: () =>
|
|
187
|
+
| { handler: (request: Request) => Promise<Response> }
|
|
188
|
+
| undefined,
|
|
189
|
+
logger: {
|
|
190
|
+
info: (msg: string, metadata?: Record<string, unknown>) => void;
|
|
191
|
+
error: (msg: string, metadata?: Record<string, unknown>) => void;
|
|
192
|
+
debug: (msg: string, metadata?: Record<string, unknown>) => void;
|
|
193
|
+
} = DEFAULT_LOGGER,
|
|
173
194
|
) => {
|
|
174
195
|
// Public endpoint for enabled strategies (no authentication required)
|
|
175
196
|
const getEnabledStrategies = os.getEnabledStrategies.handler(async () => {
|
|
@@ -180,9 +201,15 @@ export const createAuthRouter = (
|
|
|
180
201
|
// Get enabled state from meta config
|
|
181
202
|
const enabled = await getStrategyEnabled(strategy.id, configService);
|
|
182
203
|
|
|
183
|
-
// Determine strategy type
|
|
184
|
-
|
|
185
|
-
|
|
204
|
+
// Determine strategy type (backward compatibility)
|
|
205
|
+
let type: "credential" | "social" | "ldap" | "saml" = "social";
|
|
206
|
+
if (strategy.id === "credential") {
|
|
207
|
+
type = "credential";
|
|
208
|
+
} else if (strategy.clientFlow?.type === "form") {
|
|
209
|
+
type = "ldap"; // Map generic 'form' to 'ldap' for frontend compat
|
|
210
|
+
} else if (strategy.clientFlow?.type === "redirect") {
|
|
211
|
+
type = "saml"; // Map generic 'redirect' to 'saml' for frontend compat
|
|
212
|
+
}
|
|
186
213
|
|
|
187
214
|
return {
|
|
188
215
|
id: strategy.id,
|
|
@@ -192,6 +219,7 @@ export const createAuthRouter = (
|
|
|
192
219
|
enabled,
|
|
193
220
|
icon: strategy.icon,
|
|
194
221
|
requiresManualRegistration: strategy.requiresManualRegistration,
|
|
222
|
+
clientFlow: strategy.clientFlow,
|
|
195
223
|
};
|
|
196
224
|
}),
|
|
197
225
|
);
|
|
@@ -1031,20 +1059,82 @@ export const createAuthRouter = (
|
|
|
1031
1059
|
);
|
|
1032
1060
|
|
|
1033
1061
|
const createSession = os.createSession.handler(async ({ input }) => {
|
|
1034
|
-
const { userId,
|
|
1035
|
-
const
|
|
1036
|
-
const now = new Date();
|
|
1062
|
+
const { userId, ipAddress, userAgent } = input;
|
|
1063
|
+
const auth = getBetterAuth();
|
|
1037
1064
|
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1065
|
+
if (!auth) {
|
|
1066
|
+
throw new ORPCError("INTERNAL_SERVER_ERROR", {
|
|
1067
|
+
message: "Authentication service not fully initialized.",
|
|
1068
|
+
});
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
// Construct virtual request to the internal trusted login endpoint
|
|
1072
|
+
// This allows better-auth to handle cookie signing and database persistence
|
|
1073
|
+
const baseUrl = process.env.BASE_URL;
|
|
1074
|
+
if (!baseUrl) {
|
|
1075
|
+
throw new ORPCError("INTERNAL_SERVER_ERROR", {
|
|
1076
|
+
message: "BASE_URL environment variable is not defined.",
|
|
1077
|
+
});
|
|
1078
|
+
}
|
|
1079
|
+
|
|
1080
|
+
const secret = process.env.BETTER_AUTH_SECRET;
|
|
1081
|
+
if (!secret) {
|
|
1082
|
+
throw new ORPCError("INTERNAL_SERVER_ERROR", {
|
|
1083
|
+
message: "BETTER_AUTH_SECRET environment variable is not defined.",
|
|
1084
|
+
});
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
const url = new URL(baseUrl);
|
|
1088
|
+
const req = new Request(`${url.origin}/api/auth/internal/trusted-login`, {
|
|
1089
|
+
method: "POST",
|
|
1090
|
+
headers: {
|
|
1091
|
+
"Content-Type": "application/json",
|
|
1092
|
+
"x-checkstack-internal": secret,
|
|
1093
|
+
"x-forwarded-for": ipAddress || "",
|
|
1094
|
+
"user-agent": userAgent || "",
|
|
1095
|
+
Host: url.host,
|
|
1096
|
+
},
|
|
1097
|
+
body: JSON.stringify({ userId }),
|
|
1045
1098
|
});
|
|
1046
1099
|
|
|
1047
|
-
|
|
1100
|
+
const res = await auth.handler(req);
|
|
1101
|
+
|
|
1102
|
+
if (!res.ok) {
|
|
1103
|
+
const errorText = await res.text();
|
|
1104
|
+
throw new ORPCError("INTERNAL_SERVER_ERROR", {
|
|
1105
|
+
message: `Failed to create session via bridge: ${res.status} ${errorText}`,
|
|
1106
|
+
});
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
// Extract Set-Cookie. Use getSetCookie() if available (Bun/Node 20+), otherwise fallback to get()
|
|
1110
|
+
// get() usually joins multiple cookies with a comma, which is often correct but sometimes brittle
|
|
1111
|
+
const setCookie =
|
|
1112
|
+
typeof res.headers.getSetCookie === "function"
|
|
1113
|
+
? res.headers.getSetCookie().join(", ")
|
|
1114
|
+
: res.headers.get("set-cookie");
|
|
1115
|
+
|
|
1116
|
+
if (!setCookie) {
|
|
1117
|
+
const headers: Record<string, string> = {};
|
|
1118
|
+
// eslint-disable-next-line unicorn/no-array-for-each
|
|
1119
|
+
res.headers.forEach((value, key) => {
|
|
1120
|
+
headers[key] = value;
|
|
1121
|
+
});
|
|
1122
|
+
|
|
1123
|
+
logger.error("Authentication bridge did not return session cookies", {
|
|
1124
|
+
status: res.status,
|
|
1125
|
+
headers,
|
|
1126
|
+
});
|
|
1127
|
+
throw new ORPCError("INTERNAL_SERVER_ERROR", {
|
|
1128
|
+
message: "Authentication service did not return session cookies.",
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
const body = (await res.json()) as { sessionId: string };
|
|
1133
|
+
|
|
1134
|
+
return {
|
|
1135
|
+
sessionId: body.sessionId,
|
|
1136
|
+
setCookie,
|
|
1137
|
+
};
|
|
1048
1138
|
});
|
|
1049
1139
|
|
|
1050
1140
|
// ==========================================================================
|
|
@@ -1500,33 +1590,37 @@ export const createAuthRouter = (
|
|
|
1500
1590
|
},
|
|
1501
1591
|
);
|
|
1502
1592
|
|
|
1503
|
-
const addTeamManager = os.addTeamManager.handler(
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1593
|
+
const addTeamManager = os.addTeamManager.handler(
|
|
1594
|
+
async ({ input, context }) => {
|
|
1595
|
+
await assertTeamManagementAccess({
|
|
1596
|
+
user: context.user,
|
|
1597
|
+
teamId: input.teamId,
|
|
1598
|
+
internalDb,
|
|
1599
|
+
});
|
|
1600
|
+
await internalDb
|
|
1601
|
+
.insert(schema.teamManager)
|
|
1602
|
+
.values({ userId: input.userId, teamId: input.teamId })
|
|
1603
|
+
.onConflictDoNothing();
|
|
1604
|
+
},
|
|
1605
|
+
);
|
|
1514
1606
|
|
|
1515
|
-
const removeTeamManager = os.removeTeamManager.handler(
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1607
|
+
const removeTeamManager = os.removeTeamManager.handler(
|
|
1608
|
+
async ({ input, context }) => {
|
|
1609
|
+
await assertTeamManagementAccess({
|
|
1610
|
+
user: context.user,
|
|
1611
|
+
teamId: input.teamId,
|
|
1612
|
+
internalDb,
|
|
1613
|
+
});
|
|
1614
|
+
await internalDb
|
|
1615
|
+
.delete(schema.teamManager)
|
|
1616
|
+
.where(
|
|
1617
|
+
and(
|
|
1618
|
+
eq(schema.teamManager.userId, input.userId),
|
|
1619
|
+
eq(schema.teamManager.teamId, input.teamId),
|
|
1620
|
+
),
|
|
1621
|
+
);
|
|
1622
|
+
},
|
|
1623
|
+
);
|
|
1530
1624
|
|
|
1531
1625
|
const getResourceTeamAccess = os.getResourceTeamAccess.handler(
|
|
1532
1626
|
async ({ input }) => {
|
|
@@ -1787,6 +1881,50 @@ export const createAuthRouter = (
|
|
|
1787
1881
|
},
|
|
1788
1882
|
);
|
|
1789
1883
|
|
|
1884
|
+
const getOwnStrategyConfig = os.getOwnStrategyConfig.handler(
|
|
1885
|
+
async ({ context }) => {
|
|
1886
|
+
if (context.user?.type !== "service") {
|
|
1887
|
+
throw new ORPCError("UNAUTHORIZED", {
|
|
1888
|
+
message: "This endpoint is only callable by services.",
|
|
1889
|
+
});
|
|
1890
|
+
}
|
|
1891
|
+
|
|
1892
|
+
const callerPluginId = context.user?.pluginId;
|
|
1893
|
+
|
|
1894
|
+
// Infer strategyId from pluginId (e.g. auth-ldap-backend -> ldap)
|
|
1895
|
+
const strategyId = callerPluginId
|
|
1896
|
+
.replace(/^auth-/, "")
|
|
1897
|
+
.replace(/-backend$/, "");
|
|
1898
|
+
|
|
1899
|
+
const strategy = strategyRegistry
|
|
1900
|
+
.getStrategies()
|
|
1901
|
+
.find((s) => s.id === strategyId);
|
|
1902
|
+
|
|
1903
|
+
if (!strategy) {
|
|
1904
|
+
throw new ORPCError("NOT_FOUND", {
|
|
1905
|
+
message: `No strategy found for plugin ${callerPluginId} (inferred strategy ID: ${strategyId})`,
|
|
1906
|
+
});
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
// Load full (non-redacted) config from ConfigService
|
|
1910
|
+
// These configurations are stored in the auth-backend's scope
|
|
1911
|
+
const config = await configService.get(
|
|
1912
|
+
strategy.id,
|
|
1913
|
+
strategy.configSchema,
|
|
1914
|
+
strategy.configVersion,
|
|
1915
|
+
strategy.migrations,
|
|
1916
|
+
);
|
|
1917
|
+
|
|
1918
|
+
if (!config) {
|
|
1919
|
+
throw new ORPCError("NOT_FOUND", {
|
|
1920
|
+
message: `Configuration not found for strategy ${strategyId}`,
|
|
1921
|
+
});
|
|
1922
|
+
}
|
|
1923
|
+
|
|
1924
|
+
return { config: config as Record<string, unknown> };
|
|
1925
|
+
},
|
|
1926
|
+
);
|
|
1927
|
+
|
|
1790
1928
|
return os.router({
|
|
1791
1929
|
getEnabledStrategies,
|
|
1792
1930
|
accessRules: accessRulesHandler,
|
|
@@ -1820,6 +1958,7 @@ export const createAuthRouter = (
|
|
|
1820
1958
|
updateApplication,
|
|
1821
1959
|
deleteApplication,
|
|
1822
1960
|
regenerateApplicationSecret,
|
|
1961
|
+
getOwnStrategyConfig,
|
|
1823
1962
|
// Teams
|
|
1824
1963
|
getTeams,
|
|
1825
1964
|
getTeam,
|
package/src/teams.test.ts
CHANGED
|
@@ -137,7 +137,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
137
137
|
mockRegistry,
|
|
138
138
|
async () => {},
|
|
139
139
|
mockConfigService,
|
|
140
|
-
mockAccessRuleRegistry
|
|
140
|
+
mockAccessRuleRegistry,
|
|
141
|
+
() => undefined
|
|
141
142
|
);
|
|
142
143
|
|
|
143
144
|
const context = createMockRpcContext({ user: mockAdminUser });
|
|
@@ -187,7 +188,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
187
188
|
mockRegistry,
|
|
188
189
|
async () => {},
|
|
189
190
|
mockConfigService,
|
|
190
|
-
mockAccessRuleRegistry
|
|
191
|
+
mockAccessRuleRegistry,
|
|
192
|
+
() => undefined
|
|
191
193
|
);
|
|
192
194
|
|
|
193
195
|
const context = createMockRpcContext({ user: mockAdminUser });
|
|
@@ -252,7 +254,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
252
254
|
mockRegistry,
|
|
253
255
|
async () => {},
|
|
254
256
|
mockConfigService,
|
|
255
|
-
mockAccessRuleRegistry
|
|
257
|
+
mockAccessRuleRegistry,
|
|
258
|
+
() => undefined
|
|
256
259
|
);
|
|
257
260
|
|
|
258
261
|
// Use mockRegularUser who has only auth.teams.read access
|
|
@@ -309,7 +312,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
309
312
|
mockRegistry,
|
|
310
313
|
async () => {},
|
|
311
314
|
mockConfigService,
|
|
312
|
-
mockAccessRuleRegistry
|
|
315
|
+
mockAccessRuleRegistry,
|
|
316
|
+
() => undefined
|
|
313
317
|
);
|
|
314
318
|
|
|
315
319
|
const context = createMockRpcContext({ user: mockRegularUser });
|
|
@@ -333,7 +337,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
333
337
|
mockRegistry,
|
|
334
338
|
async () => {},
|
|
335
339
|
mockConfigService,
|
|
336
|
-
mockAccessRuleRegistry
|
|
340
|
+
mockAccessRuleRegistry,
|
|
341
|
+
() => undefined
|
|
337
342
|
);
|
|
338
343
|
|
|
339
344
|
const context = createMockRpcContext({ user: mockAdminUser });
|
|
@@ -389,7 +394,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
389
394
|
mockRegistry,
|
|
390
395
|
async () => {},
|
|
391
396
|
mockConfigService,
|
|
392
|
-
mockAccessRuleRegistry
|
|
397
|
+
mockAccessRuleRegistry,
|
|
398
|
+
() => undefined
|
|
393
399
|
);
|
|
394
400
|
|
|
395
401
|
const context = createMockRpcContext({ user: mockAdminUser });
|
|
@@ -423,7 +429,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
423
429
|
mockRegistry,
|
|
424
430
|
async () => {},
|
|
425
431
|
mockConfigService,
|
|
426
|
-
mockAccessRuleRegistry
|
|
432
|
+
mockAccessRuleRegistry,
|
|
433
|
+
() => undefined
|
|
427
434
|
);
|
|
428
435
|
|
|
429
436
|
const context = createMockRpcContext({ user: mockAdminUser });
|
|
@@ -453,7 +460,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
453
460
|
mockRegistry,
|
|
454
461
|
async () => {},
|
|
455
462
|
mockConfigService,
|
|
456
|
-
mockAccessRuleRegistry
|
|
463
|
+
mockAccessRuleRegistry,
|
|
464
|
+
() => undefined
|
|
457
465
|
);
|
|
458
466
|
|
|
459
467
|
const context = createMockRpcContext({ user: mockAdminUser });
|
|
@@ -487,7 +495,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
487
495
|
mockRegistry,
|
|
488
496
|
async () => {},
|
|
489
497
|
mockConfigService,
|
|
490
|
-
mockAccessRuleRegistry
|
|
498
|
+
mockAccessRuleRegistry,
|
|
499
|
+
() => undefined
|
|
491
500
|
);
|
|
492
501
|
|
|
493
502
|
const context = createMockRpcContext({ user: mockAdminUser });
|
|
@@ -520,7 +529,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
520
529
|
mockRegistry,
|
|
521
530
|
async () => {},
|
|
522
531
|
mockConfigService,
|
|
523
|
-
mockAccessRuleRegistry
|
|
532
|
+
mockAccessRuleRegistry,
|
|
533
|
+
() => undefined
|
|
524
534
|
);
|
|
525
535
|
|
|
526
536
|
const context = createMockRpcContext({ user: mockAdminUser });
|
|
@@ -557,7 +567,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
557
567
|
mockRegistry,
|
|
558
568
|
async () => {},
|
|
559
569
|
mockConfigService,
|
|
560
|
-
mockAccessRuleRegistry
|
|
570
|
+
mockAccessRuleRegistry,
|
|
571
|
+
() => undefined
|
|
561
572
|
);
|
|
562
573
|
|
|
563
574
|
const context = createMockRpcContext({ user: mockAdminUser });
|
|
@@ -596,7 +607,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
596
607
|
mockRegistry,
|
|
597
608
|
async () => {},
|
|
598
609
|
mockConfigService,
|
|
599
|
-
mockAccessRuleRegistry
|
|
610
|
+
mockAccessRuleRegistry,
|
|
611
|
+
() => undefined
|
|
600
612
|
);
|
|
601
613
|
|
|
602
614
|
const context = createMockRpcContext({ user: mockAdminUser });
|
|
@@ -621,7 +633,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
621
633
|
mockRegistry,
|
|
622
634
|
async () => {},
|
|
623
635
|
mockConfigService,
|
|
624
|
-
mockAccessRuleRegistry
|
|
636
|
+
mockAccessRuleRegistry,
|
|
637
|
+
() => undefined
|
|
625
638
|
);
|
|
626
639
|
|
|
627
640
|
const context = createMockRpcContext({ user: mockAdminUser });
|
|
@@ -658,7 +671,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
658
671
|
mockRegistry,
|
|
659
672
|
async () => {},
|
|
660
673
|
mockConfigService,
|
|
661
|
-
mockAccessRuleRegistry
|
|
674
|
+
mockAccessRuleRegistry,
|
|
675
|
+
() => undefined
|
|
662
676
|
);
|
|
663
677
|
|
|
664
678
|
const context = createMockRpcContext({ user: mockAdminUser });
|
|
@@ -683,7 +697,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
683
697
|
mockRegistry,
|
|
684
698
|
async () => {},
|
|
685
699
|
mockConfigService,
|
|
686
|
-
mockAccessRuleRegistry
|
|
700
|
+
mockAccessRuleRegistry,
|
|
701
|
+
() => undefined
|
|
687
702
|
);
|
|
688
703
|
|
|
689
704
|
const context = createMockRpcContext({ user: mockAdminUser });
|
|
@@ -716,7 +731,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
716
731
|
mockRegistry,
|
|
717
732
|
async () => {},
|
|
718
733
|
mockConfigService,
|
|
719
|
-
mockAccessRuleRegistry
|
|
734
|
+
mockAccessRuleRegistry,
|
|
735
|
+
() => undefined
|
|
720
736
|
);
|
|
721
737
|
|
|
722
738
|
const context = createMockRpcContext({ user: mockAdminUser });
|
|
@@ -763,7 +779,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
763
779
|
mockRegistry,
|
|
764
780
|
async () => {},
|
|
765
781
|
mockConfigService,
|
|
766
|
-
mockAccessRuleRegistry
|
|
782
|
+
mockAccessRuleRegistry,
|
|
783
|
+
() => undefined
|
|
767
784
|
);
|
|
768
785
|
|
|
769
786
|
const context = createMockRpcContext({ user: mockAdminUser });
|
|
@@ -808,7 +825,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
808
825
|
mockRegistry,
|
|
809
826
|
async () => {},
|
|
810
827
|
mockConfigService,
|
|
811
|
-
mockAccessRuleRegistry
|
|
828
|
+
mockAccessRuleRegistry,
|
|
829
|
+
() => undefined
|
|
812
830
|
);
|
|
813
831
|
|
|
814
832
|
const context = createMockRpcContext({ user: mockAdminUser });
|
|
@@ -848,7 +866,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
848
866
|
mockRegistry,
|
|
849
867
|
async () => {},
|
|
850
868
|
mockConfigService,
|
|
851
|
-
mockAccessRuleRegistry
|
|
869
|
+
mockAccessRuleRegistry,
|
|
870
|
+
() => undefined
|
|
852
871
|
);
|
|
853
872
|
|
|
854
873
|
const context = createMockRpcContext({ user: mockAdminUser });
|
|
@@ -878,7 +897,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
878
897
|
mockRegistry,
|
|
879
898
|
async () => {},
|
|
880
899
|
mockConfigService,
|
|
881
|
-
mockAccessRuleRegistry
|
|
900
|
+
mockAccessRuleRegistry,
|
|
901
|
+
() => undefined
|
|
882
902
|
);
|
|
883
903
|
|
|
884
904
|
const context = createMockRpcContext({ user: mockAdminUser });
|
|
@@ -914,7 +934,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
914
934
|
mockRegistry,
|
|
915
935
|
async () => {},
|
|
916
936
|
mockConfigService,
|
|
917
|
-
mockAccessRuleRegistry
|
|
937
|
+
mockAccessRuleRegistry,
|
|
938
|
+
() => undefined
|
|
918
939
|
);
|
|
919
940
|
|
|
920
941
|
const context = createMockRpcContext({ user: mockServiceUser });
|
|
@@ -947,7 +968,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
947
968
|
mockRegistry,
|
|
948
969
|
async () => {},
|
|
949
970
|
mockConfigService,
|
|
950
|
-
mockAccessRuleRegistry
|
|
971
|
+
mockAccessRuleRegistry,
|
|
972
|
+
() => undefined
|
|
951
973
|
);
|
|
952
974
|
|
|
953
975
|
const context = createMockRpcContext({ user: mockServiceUser });
|
|
@@ -998,7 +1020,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
998
1020
|
mockRegistry,
|
|
999
1021
|
async () => {},
|
|
1000
1022
|
mockConfigService,
|
|
1001
|
-
mockAccessRuleRegistry
|
|
1023
|
+
mockAccessRuleRegistry,
|
|
1024
|
+
() => undefined
|
|
1002
1025
|
);
|
|
1003
1026
|
|
|
1004
1027
|
const context = createMockRpcContext({ user: mockServiceUser });
|
|
@@ -1049,7 +1072,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
1049
1072
|
mockRegistry,
|
|
1050
1073
|
async () => {},
|
|
1051
1074
|
mockConfigService,
|
|
1052
|
-
mockAccessRuleRegistry
|
|
1075
|
+
mockAccessRuleRegistry,
|
|
1076
|
+
() => undefined
|
|
1053
1077
|
);
|
|
1054
1078
|
|
|
1055
1079
|
const context = createMockRpcContext({ user: mockServiceUser });
|
|
@@ -1102,7 +1126,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
1102
1126
|
mockRegistry,
|
|
1103
1127
|
async () => {},
|
|
1104
1128
|
mockConfigService,
|
|
1105
|
-
mockAccessRuleRegistry
|
|
1129
|
+
mockAccessRuleRegistry,
|
|
1130
|
+
() => undefined
|
|
1106
1131
|
);
|
|
1107
1132
|
|
|
1108
1133
|
const context = createMockRpcContext({ user: mockServiceUser });
|
|
@@ -1155,7 +1180,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
1155
1180
|
mockRegistry,
|
|
1156
1181
|
async () => {},
|
|
1157
1182
|
mockConfigService,
|
|
1158
|
-
mockAccessRuleRegistry
|
|
1183
|
+
mockAccessRuleRegistry,
|
|
1184
|
+
() => undefined
|
|
1159
1185
|
);
|
|
1160
1186
|
|
|
1161
1187
|
const context = createMockRpcContext({ user: mockServiceUser });
|
|
@@ -1206,7 +1232,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
1206
1232
|
mockRegistry,
|
|
1207
1233
|
async () => {},
|
|
1208
1234
|
mockConfigService,
|
|
1209
|
-
mockAccessRuleRegistry
|
|
1235
|
+
mockAccessRuleRegistry,
|
|
1236
|
+
() => undefined
|
|
1210
1237
|
);
|
|
1211
1238
|
|
|
1212
1239
|
const context = createMockRpcContext({ user: mockServiceUser });
|
|
@@ -1252,7 +1279,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
1252
1279
|
mockRegistry,
|
|
1253
1280
|
async () => {},
|
|
1254
1281
|
mockConfigService,
|
|
1255
|
-
mockAccessRuleRegistry
|
|
1282
|
+
mockAccessRuleRegistry,
|
|
1283
|
+
() => undefined
|
|
1256
1284
|
);
|
|
1257
1285
|
|
|
1258
1286
|
const context = createMockRpcContext({ user: mockServiceUser });
|
|
@@ -1303,7 +1331,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
1303
1331
|
mockRegistry,
|
|
1304
1332
|
async () => {},
|
|
1305
1333
|
mockConfigService,
|
|
1306
|
-
mockAccessRuleRegistry
|
|
1334
|
+
mockAccessRuleRegistry,
|
|
1335
|
+
() => undefined
|
|
1307
1336
|
);
|
|
1308
1337
|
|
|
1309
1338
|
const context = createMockRpcContext({ user: mockServiceUser });
|
|
@@ -1356,7 +1385,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
1356
1385
|
mockRegistry,
|
|
1357
1386
|
async () => {},
|
|
1358
1387
|
mockConfigService,
|
|
1359
|
-
mockAccessRuleRegistry
|
|
1388
|
+
mockAccessRuleRegistry,
|
|
1389
|
+
() => undefined
|
|
1360
1390
|
);
|
|
1361
1391
|
|
|
1362
1392
|
const context = createMockRpcContext({ user: mockServiceUser });
|
|
@@ -1414,7 +1444,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
1414
1444
|
mockRegistry,
|
|
1415
1445
|
async () => {},
|
|
1416
1446
|
mockConfigService,
|
|
1417
|
-
mockAccessRuleRegistry
|
|
1447
|
+
mockAccessRuleRegistry,
|
|
1448
|
+
() => undefined
|
|
1418
1449
|
);
|
|
1419
1450
|
|
|
1420
1451
|
const context = createMockRpcContext({ user: mockServiceUser });
|
|
@@ -1465,7 +1496,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
1465
1496
|
mockRegistry,
|
|
1466
1497
|
async () => {},
|
|
1467
1498
|
mockConfigService,
|
|
1468
|
-
mockAccessRuleRegistry
|
|
1499
|
+
mockAccessRuleRegistry,
|
|
1500
|
+
() => undefined
|
|
1469
1501
|
);
|
|
1470
1502
|
|
|
1471
1503
|
const context = createMockRpcContext({ user: mockServiceUser });
|
|
@@ -1518,7 +1550,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
1518
1550
|
mockRegistry,
|
|
1519
1551
|
async () => {},
|
|
1520
1552
|
mockConfigService,
|
|
1521
|
-
mockAccessRuleRegistry
|
|
1553
|
+
mockAccessRuleRegistry,
|
|
1554
|
+
() => undefined
|
|
1522
1555
|
);
|
|
1523
1556
|
|
|
1524
1557
|
const context = createMockRpcContext({ user: mockServiceUser });
|
|
@@ -1571,7 +1604,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
1571
1604
|
mockRegistry,
|
|
1572
1605
|
async () => {},
|
|
1573
1606
|
mockConfigService,
|
|
1574
|
-
mockAccessRuleRegistry
|
|
1607
|
+
mockAccessRuleRegistry,
|
|
1608
|
+
() => undefined
|
|
1575
1609
|
);
|
|
1576
1610
|
|
|
1577
1611
|
const context = createMockRpcContext({ user: mockServiceUser });
|
|
@@ -1601,7 +1635,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
1601
1635
|
mockRegistry,
|
|
1602
1636
|
async () => {},
|
|
1603
1637
|
mockConfigService,
|
|
1604
|
-
mockAccessRuleRegistry
|
|
1638
|
+
mockAccessRuleRegistry,
|
|
1639
|
+
() => undefined
|
|
1605
1640
|
);
|
|
1606
1641
|
|
|
1607
1642
|
const context = createMockRpcContext({ user: mockServiceUser });
|
|
@@ -1639,7 +1674,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
1639
1674
|
mockRegistry,
|
|
1640
1675
|
async () => {},
|
|
1641
1676
|
mockConfigService,
|
|
1642
|
-
mockAccessRuleRegistry
|
|
1677
|
+
mockAccessRuleRegistry,
|
|
1678
|
+
() => undefined
|
|
1643
1679
|
);
|
|
1644
1680
|
|
|
1645
1681
|
const context = createMockRpcContext({ user: mockServiceUser });
|
|
@@ -1702,7 +1738,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
1702
1738
|
mockRegistry,
|
|
1703
1739
|
async () => {},
|
|
1704
1740
|
mockConfigService,
|
|
1705
|
-
mockAccessRuleRegistry
|
|
1741
|
+
mockAccessRuleRegistry,
|
|
1742
|
+
() => undefined
|
|
1706
1743
|
);
|
|
1707
1744
|
|
|
1708
1745
|
const context = createMockRpcContext({ user: mockServiceUser });
|
|
@@ -1750,7 +1787,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
1750
1787
|
mockRegistry,
|
|
1751
1788
|
async () => {},
|
|
1752
1789
|
mockConfigService,
|
|
1753
|
-
mockAccessRuleRegistry
|
|
1790
|
+
mockAccessRuleRegistry,
|
|
1791
|
+
() => undefined
|
|
1754
1792
|
);
|
|
1755
1793
|
|
|
1756
1794
|
const context = createMockRpcContext({ user: mockServiceUser });
|
|
@@ -1813,7 +1851,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
1813
1851
|
mockRegistry,
|
|
1814
1852
|
async () => {},
|
|
1815
1853
|
mockConfigService,
|
|
1816
|
-
mockAccessRuleRegistry
|
|
1854
|
+
mockAccessRuleRegistry,
|
|
1855
|
+
() => undefined
|
|
1817
1856
|
);
|
|
1818
1857
|
|
|
1819
1858
|
const context = createMockRpcContext({ user: mockServiceUser });
|
|
@@ -1870,7 +1909,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
1870
1909
|
mockRegistry,
|
|
1871
1910
|
async () => {},
|
|
1872
1911
|
mockConfigService,
|
|
1873
|
-
mockAccessRuleRegistry
|
|
1912
|
+
mockAccessRuleRegistry,
|
|
1913
|
+
() => undefined
|
|
1874
1914
|
);
|
|
1875
1915
|
|
|
1876
1916
|
const context = createMockRpcContext({ user: mockServiceUser });
|
|
@@ -1933,7 +1973,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
1933
1973
|
mockRegistry,
|
|
1934
1974
|
async () => {},
|
|
1935
1975
|
mockConfigService,
|
|
1936
|
-
mockAccessRuleRegistry
|
|
1976
|
+
mockAccessRuleRegistry,
|
|
1977
|
+
() => undefined
|
|
1937
1978
|
);
|
|
1938
1979
|
|
|
1939
1980
|
const context = createMockRpcContext({ user: mockServiceUser });
|
|
@@ -1966,7 +2007,8 @@ describe("Teams and Resource Access Control", () => {
|
|
|
1966
2007
|
mockRegistry,
|
|
1967
2008
|
async () => {},
|
|
1968
2009
|
mockConfigService,
|
|
1969
|
-
mockAccessRuleRegistry
|
|
2010
|
+
mockAccessRuleRegistry,
|
|
2011
|
+
() => undefined
|
|
1970
2012
|
);
|
|
1971
2013
|
|
|
1972
2014
|
const context = createMockRpcContext({ user: mockServiceUser });
|