@enterprisestandard/esv 0.0.5-beta.20260115.1 → 0.0.5-beta.20260115.2

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,134 @@
1
+ /**
2
+ * Cryptographic utilities for the ESV mock server
3
+ *
4
+ * Generates ephemeral RSA keys on startup for signing JWTs.
5
+ * Uses only Node.js built-in crypto module.
6
+ */
7
+ import * as crypto from 'node:crypto';
8
+ // Key pair generated on module load
9
+ let privateKey;
10
+ let publicKey;
11
+ let keyId;
12
+ /**
13
+ * Initialize the cryptographic keys
14
+ * Called on server startup
15
+ */
16
+ export function initializeKeys() {
17
+ const { publicKey: pubKey, privateKey: privKey } = crypto.generateKeyPairSync('rsa', {
18
+ modulusLength: 2048,
19
+ });
20
+ privateKey = privKey;
21
+ publicKey = pubKey;
22
+ keyId = crypto.randomBytes(8).toString('hex');
23
+ }
24
+ /**
25
+ * Get the key ID
26
+ */
27
+ export function getKeyId() {
28
+ return keyId;
29
+ }
30
+ /**
31
+ * Base64URL encode a buffer or string
32
+ */
33
+ function base64UrlEncode(data) {
34
+ const buffer = typeof data === 'string' ? Buffer.from(data) : data;
35
+ return buffer.toString('base64url');
36
+ }
37
+ /**
38
+ * Base64URL decode a string
39
+ */
40
+ function base64UrlDecode(data) {
41
+ return Buffer.from(data, 'base64url');
42
+ }
43
+ /**
44
+ * Sign a JWT with the private key
45
+ */
46
+ export function signJwt(payload, expiresInSeconds = 3600) {
47
+ const now = Math.floor(Date.now() / 1000);
48
+ const header = {
49
+ alg: 'RS256',
50
+ typ: 'JWT',
51
+ kid: keyId,
52
+ };
53
+ const claims = {
54
+ ...payload,
55
+ iat: now,
56
+ exp: now + expiresInSeconds,
57
+ };
58
+ const encodedHeader = base64UrlEncode(JSON.stringify(header));
59
+ const encodedPayload = base64UrlEncode(JSON.stringify(claims));
60
+ const signatureInput = `${encodedHeader}.${encodedPayload}`;
61
+ const sign = crypto.createSign('RSA-SHA256');
62
+ sign.update(signatureInput);
63
+ const signature = sign.sign(privateKey);
64
+ return `${signatureInput}.${base64UrlEncode(signature)}`;
65
+ }
66
+ /**
67
+ * Verify a JWT signature
68
+ */
69
+ export function verifyJwt(token) {
70
+ try {
71
+ const parts = token.split('.');
72
+ if (parts.length !== 3) {
73
+ return { valid: false, error: 'Invalid JWT format' };
74
+ }
75
+ const [encodedHeader, encodedPayload, encodedSignature] = parts;
76
+ const signatureInput = `${encodedHeader}.${encodedPayload}`;
77
+ const signature = base64UrlDecode(encodedSignature);
78
+ const verify = crypto.createVerify('RSA-SHA256');
79
+ verify.update(signatureInput);
80
+ const isValid = verify.verify(publicKey, signature);
81
+ if (!isValid) {
82
+ return { valid: false, error: 'Invalid signature' };
83
+ }
84
+ const payload = JSON.parse(base64UrlDecode(encodedPayload).toString('utf-8'));
85
+ // Check expiration
86
+ const now = Math.floor(Date.now() / 1000);
87
+ if (payload.exp && payload.exp < now) {
88
+ return { valid: false, error: 'Token expired' };
89
+ }
90
+ return { valid: true, payload };
91
+ }
92
+ catch (error) {
93
+ return { valid: false, error: error instanceof Error ? error.message : 'Unknown error' };
94
+ }
95
+ }
96
+ /**
97
+ * Get the JWKS (JSON Web Key Set) for the public key
98
+ */
99
+ export function getJwks() {
100
+ const jwk = publicKey.export({ format: 'jwk' });
101
+ return {
102
+ keys: [
103
+ {
104
+ kty: jwk.kty,
105
+ n: jwk.n,
106
+ e: jwk.e,
107
+ kid: keyId,
108
+ use: 'sig',
109
+ alg: 'RS256',
110
+ },
111
+ ],
112
+ };
113
+ }
114
+ /**
115
+ * Generate a random string for codes, states, etc.
116
+ */
117
+ export function generateRandomString(length = 32) {
118
+ return crypto.randomBytes(length).toString('hex').substring(0, length);
119
+ }
120
+ /**
121
+ * Generate a UUID
122
+ */
123
+ export function generateUUID() {
124
+ return crypto.randomUUID();
125
+ }
126
+ /**
127
+ * Verify PKCE code challenge
128
+ */
129
+ export function verifyCodeChallenge(codeVerifier, codeChallenge) {
130
+ const hash = crypto.createHash('sha256').update(codeVerifier).digest();
131
+ const computed = base64UrlEncode(hash);
132
+ return computed === codeChallenge;
133
+ }
134
+ //# sourceMappingURL=crypto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"crypto.js","sourceRoot":"","sources":["../../src/server/crypto.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AAEtC,oCAAoC;AACpC,IAAI,UAA4B,CAAC;AACjC,IAAI,SAA2B,CAAC;AAChC,IAAI,KAAa,CAAC;AAElB;;;GAGG;AACH,MAAM,UAAU,cAAc;IAC5B,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,GAAG,MAAM,CAAC,mBAAmB,CAAC,KAAK,EAAE;QACnF,aAAa,EAAE,IAAI;KACpB,CAAC,CAAC;IAEH,UAAU,GAAG,OAAO,CAAC;IACrB,SAAS,GAAG,MAAM,CAAC;IACnB,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;AAChD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ;IACtB,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,IAAqB;IAC5C,MAAM,MAAM,GAAG,OAAO,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACnE,OAAO,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,IAAY;IACnC,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,OAAO,CAAC,OAAgC,EAAE,mBAA2B,IAAI;IACvF,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;IAE1C,MAAM,MAAM,GAAG;QACb,GAAG,EAAE,OAAO;QACZ,GAAG,EAAE,KAAK;QACV,GAAG,EAAE,KAAK;KACX,CAAC;IAEF,MAAM,MAAM,GAAG;QACb,GAAG,OAAO;QACV,GAAG,EAAE,GAAG;QACR,GAAG,EAAE,GAAG,GAAG,gBAAgB;KAC5B,CAAC;IAEF,MAAM,aAAa,GAAG,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAC9D,MAAM,cAAc,GAAG,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC;IAC/D,MAAM,cAAc,GAAG,GAAG,aAAa,IAAI,cAAc,EAAE,CAAC;IAE5D,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC;IAC7C,IAAI,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;IAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAExC,OAAO,GAAG,cAAc,IAAI,eAAe,CAAC,SAAS,CAAC,EAAE,CAAC;AAC3D,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,SAAS,CAAC,KAAa;IACrC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAC;QACvD,CAAC;QAED,MAAM,CAAC,aAAa,EAAE,cAAc,EAAE,gBAAgB,CAAC,GAAG,KAAK,CAAC;QAChE,MAAM,cAAc,GAAG,GAAG,aAAa,IAAI,cAAc,EAAE,CAAC;QAC5D,MAAM,SAAS,GAAG,eAAe,CAAC,gBAAgB,CAAC,CAAC;QAEpD,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC;QACjD,MAAM,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC;QAC9B,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;QAEpD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC;QACtD,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;QAE9E,mBAAmB;QACnB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;QAC1C,IAAI,OAAO,CAAC,GAAG,IAAI,OAAO,CAAC,GAAG,GAAG,GAAG,EAAE,CAAC;YACrC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;QAClD,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,EAAE,CAAC;IAC3F,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,OAAO;IACrB,MAAM,GAAG,GAAG,SAAS,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAEhD,OAAO;QACL,IAAI,EAAE;YACJ;gBACE,GAAG,EAAE,GAAG,CAAC,GAAa;gBACtB,CAAC,EAAE,GAAG,CAAC,CAAW;gBAClB,CAAC,EAAE,GAAG,CAAC,CAAW;gBAClB,GAAG,EAAE,KAAK;gBACV,GAAG,EAAE,KAAK;gBACV,GAAG,EAAE,OAAO;aACb;SACF;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAAiB,EAAE;IACtD,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;AACzE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY;IAC1B,OAAO,MAAM,CAAC,UAAU,EAAE,CAAC;AAC7B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,YAAoB,EAAE,aAAqB;IAC7E,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM,EAAE,CAAC;IACvE,MAAM,QAAQ,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACvC,OAAO,QAAQ,KAAK,aAAa,CAAC;AACpC,CAAC"}
@@ -0,0 +1,402 @@
1
+ /**
2
+ * IAM/SCIM endpoint handlers for the ESV mock server
3
+ *
4
+ * Implements SCIM 2.0 endpoints for user and group management.
5
+ */
6
+ import { generateUUID } from './crypto.js';
7
+ import { createGroup, createUser, deleteGroup, deleteUser, getGroup, getGroups, getUser, getUsers, updateGroup, updateUser, } from './state.js';
8
+ const SCIM_CONTENT_TYPE = 'application/scim+json';
9
+ /**
10
+ * Parse JSON request body
11
+ */
12
+ async function parseJsonBody(req) {
13
+ return new Promise((resolve, reject) => {
14
+ let body = '';
15
+ req.on('data', (chunk) => {
16
+ body += chunk.toString();
17
+ });
18
+ req.on('end', () => {
19
+ try {
20
+ resolve(body ? JSON.parse(body) : {});
21
+ }
22
+ catch (error) {
23
+ reject(error);
24
+ }
25
+ });
26
+ req.on('error', reject);
27
+ });
28
+ }
29
+ /**
30
+ * Validate authorization header
31
+ */
32
+ function validateAuth(req, res) {
33
+ const auth = req.headers.authorization;
34
+ if (!auth || !auth.startsWith('Bearer ')) {
35
+ res.writeHead(401, { 'Content-Type': SCIM_CONTENT_TYPE });
36
+ res.end(JSON.stringify({
37
+ schemas: ['urn:ietf:params:scim:api:messages:2.0:Error'],
38
+ status: '401',
39
+ detail: 'Authorization required',
40
+ }));
41
+ return false;
42
+ }
43
+ // We accept any bearer token for testing
44
+ return true;
45
+ }
46
+ /**
47
+ * Send SCIM error response
48
+ */
49
+ function sendScimError(res, status, detail, scimType) {
50
+ res.writeHead(status, { 'Content-Type': SCIM_CONTENT_TYPE });
51
+ res.end(JSON.stringify({
52
+ schemas: ['urn:ietf:params:scim:api:messages:2.0:Error'],
53
+ status: String(status),
54
+ scimType,
55
+ detail,
56
+ }));
57
+ }
58
+ /**
59
+ * Send SCIM list response
60
+ */
61
+ function sendListResponse(res, resources, totalResults) {
62
+ res.writeHead(200, { 'Content-Type': SCIM_CONTENT_TYPE });
63
+ res.end(JSON.stringify({
64
+ schemas: ['urn:ietf:params:scim:api:messages:2.0:ListResponse'],
65
+ totalResults: totalResults ?? resources.length,
66
+ startIndex: 1,
67
+ itemsPerPage: resources.length,
68
+ Resources: resources,
69
+ }));
70
+ }
71
+ /**
72
+ * Handle IAM/SCIM requests
73
+ */
74
+ export async function handleIamRequest(req, res, pathname) {
75
+ // Remove /iam prefix
76
+ const iamPath = pathname.replace(/^\/iam/, '');
77
+ // Validate auth for all requests
78
+ if (!validateAuth(req, res)) {
79
+ return;
80
+ }
81
+ // Parse path to determine resource and ID
82
+ const usersMatch = iamPath.match(/^\/Users(?:\/([^/]+))?$/);
83
+ const groupsMatch = iamPath.match(/^\/Groups(?:\/([^/]+))?$/);
84
+ if (usersMatch) {
85
+ const userId = usersMatch[1];
86
+ await handleUsersRequest(req, res, userId);
87
+ return;
88
+ }
89
+ if (groupsMatch) {
90
+ const groupId = groupsMatch[1];
91
+ await handleGroupsRequest(req, res, groupId);
92
+ return;
93
+ }
94
+ sendScimError(res, 404, 'Resource not found');
95
+ }
96
+ /**
97
+ * Handle /Users requests
98
+ */
99
+ async function handleUsersRequest(req, res, userId) {
100
+ if (userId) {
101
+ // Operations on a specific user
102
+ switch (req.method) {
103
+ case 'GET':
104
+ handleGetUser(res, userId);
105
+ break;
106
+ case 'PUT':
107
+ await handleReplaceUser(req, res, userId);
108
+ break;
109
+ case 'PATCH':
110
+ await handlePatchUser(req, res, userId);
111
+ break;
112
+ case 'DELETE':
113
+ handleDeleteUser(res, userId);
114
+ break;
115
+ default:
116
+ sendScimError(res, 405, 'Method not allowed');
117
+ }
118
+ }
119
+ else {
120
+ // Operations on users collection
121
+ switch (req.method) {
122
+ case 'GET':
123
+ handleListUsers(res);
124
+ break;
125
+ case 'POST':
126
+ await handleCreateUser(req, res);
127
+ break;
128
+ default:
129
+ sendScimError(res, 405, 'Method not allowed');
130
+ }
131
+ }
132
+ }
133
+ /**
134
+ * Handle /Groups requests
135
+ */
136
+ async function handleGroupsRequest(req, res, groupId) {
137
+ if (groupId) {
138
+ // Operations on a specific group
139
+ switch (req.method) {
140
+ case 'GET':
141
+ handleGetGroup(res, groupId);
142
+ break;
143
+ case 'PUT':
144
+ await handleReplaceGroup(req, res, groupId);
145
+ break;
146
+ case 'PATCH':
147
+ await handlePatchGroup(req, res, groupId);
148
+ break;
149
+ case 'DELETE':
150
+ handleDeleteGroup(res, groupId);
151
+ break;
152
+ default:
153
+ sendScimError(res, 405, 'Method not allowed');
154
+ }
155
+ }
156
+ else {
157
+ // Operations on groups collection
158
+ switch (req.method) {
159
+ case 'GET':
160
+ handleListGroups(res);
161
+ break;
162
+ case 'POST':
163
+ await handleCreateGroup(req, res);
164
+ break;
165
+ default:
166
+ sendScimError(res, 405, 'Method not allowed');
167
+ }
168
+ }
169
+ }
170
+ // ========== User Handlers ==========
171
+ function handleListUsers(res) {
172
+ const users = getUsers();
173
+ sendListResponse(res, users);
174
+ }
175
+ function handleGetUser(res, id) {
176
+ const user = getUser(id);
177
+ if (!user) {
178
+ sendScimError(res, 404, `User ${id} not found`, 'invalidValue');
179
+ return;
180
+ }
181
+ res.writeHead(200, { 'Content-Type': SCIM_CONTENT_TYPE });
182
+ res.end(JSON.stringify(user));
183
+ }
184
+ async function handleCreateUser(req, res) {
185
+ try {
186
+ const body = (await parseJsonBody(req));
187
+ if (!body.userName) {
188
+ sendScimError(res, 400, 'userName is required', 'invalidValue');
189
+ return;
190
+ }
191
+ const user = {
192
+ id: generateUUID(),
193
+ schemas: body.schemas || [
194
+ 'urn:ietf:params:scim:schemas:core:2.0:User',
195
+ 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User',
196
+ ],
197
+ userName: body.userName,
198
+ displayName: body.displayName,
199
+ name: body.name,
200
+ emails: body.emails,
201
+ active: body.active ?? true,
202
+ externalId: body.externalId,
203
+ groups: [],
204
+ 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User': body['urn:ietf:params:scim:schemas:extension:enterprise:2.0:User'],
205
+ };
206
+ const created = createUser(user);
207
+ res.writeHead(201, { 'Content-Type': SCIM_CONTENT_TYPE });
208
+ res.end(JSON.stringify(created));
209
+ }
210
+ catch (_error) {
211
+ sendScimError(res, 400, 'Invalid request body');
212
+ }
213
+ }
214
+ async function handleReplaceUser(req, res, id) {
215
+ const existing = getUser(id);
216
+ if (!existing) {
217
+ sendScimError(res, 404, `User ${id} not found`, 'invalidValue');
218
+ return;
219
+ }
220
+ try {
221
+ const body = (await parseJsonBody(req));
222
+ const updated = updateUser(id, { ...body, id });
223
+ if (updated) {
224
+ res.writeHead(200, { 'Content-Type': SCIM_CONTENT_TYPE });
225
+ res.end(JSON.stringify(updated));
226
+ }
227
+ else {
228
+ sendScimError(res, 404, `User ${id} not found`);
229
+ }
230
+ }
231
+ catch (_error) {
232
+ sendScimError(res, 400, 'Invalid request body');
233
+ }
234
+ }
235
+ async function handlePatchUser(req, res, id) {
236
+ const existing = getUser(id);
237
+ if (!existing) {
238
+ sendScimError(res, 404, `User ${id} not found`, 'invalidValue');
239
+ return;
240
+ }
241
+ try {
242
+ const body = (await parseJsonBody(req));
243
+ const operations = body.Operations || [];
244
+ const updated = { ...existing };
245
+ for (const op of operations) {
246
+ if (op.op === 'replace' && op.path && op.value !== undefined) {
247
+ // Simple path handling for common cases
248
+ if (op.path === 'displayName') {
249
+ updated.displayName = op.value;
250
+ }
251
+ else if (op.path === 'active') {
252
+ updated.active = op.value;
253
+ }
254
+ else if (op.path.startsWith('name.')) {
255
+ const namePart = op.path.split('.')[1];
256
+ updated.name = { ...updated.name, [namePart]: op.value };
257
+ }
258
+ }
259
+ else if (op.op === 'add' && op.path && op.value !== undefined) {
260
+ if (op.path === 'emails') {
261
+ updated.emails = [...(updated.emails || []), ...(op.value || [])];
262
+ }
263
+ }
264
+ else if (op.op === 'remove' && op.path) {
265
+ if (op.path === 'displayName') {
266
+ updated.displayName = undefined;
267
+ }
268
+ }
269
+ }
270
+ const result = updateUser(id, updated);
271
+ if (result) {
272
+ res.writeHead(200, { 'Content-Type': SCIM_CONTENT_TYPE });
273
+ res.end(JSON.stringify(result));
274
+ }
275
+ else {
276
+ sendScimError(res, 404, `User ${id} not found`);
277
+ }
278
+ }
279
+ catch (_error) {
280
+ sendScimError(res, 400, 'Invalid request body');
281
+ }
282
+ }
283
+ function handleDeleteUser(res, id) {
284
+ const deleted = deleteUser(id);
285
+ if (!deleted) {
286
+ sendScimError(res, 404, `User ${id} not found`, 'invalidValue');
287
+ return;
288
+ }
289
+ res.writeHead(204);
290
+ res.end();
291
+ }
292
+ // ========== Group Handlers ==========
293
+ function handleListGroups(res) {
294
+ const groups = getGroups();
295
+ sendListResponse(res, groups);
296
+ }
297
+ function handleGetGroup(res, id) {
298
+ const group = getGroup(id);
299
+ if (!group) {
300
+ sendScimError(res, 404, `Group ${id} not found`, 'invalidValue');
301
+ return;
302
+ }
303
+ res.writeHead(200, { 'Content-Type': SCIM_CONTENT_TYPE });
304
+ res.end(JSON.stringify(group));
305
+ }
306
+ async function handleCreateGroup(req, res) {
307
+ try {
308
+ const body = (await parseJsonBody(req));
309
+ if (!body.displayName) {
310
+ sendScimError(res, 400, 'displayName is required', 'invalidValue');
311
+ return;
312
+ }
313
+ const group = {
314
+ id: generateUUID(),
315
+ schemas: body.schemas || ['urn:ietf:params:scim:schemas:core:2.0:Group'],
316
+ displayName: body.displayName,
317
+ externalId: body.externalId,
318
+ members: body.members || [],
319
+ };
320
+ const created = createGroup(group);
321
+ res.writeHead(201, { 'Content-Type': SCIM_CONTENT_TYPE });
322
+ res.end(JSON.stringify(created));
323
+ }
324
+ catch (_error) {
325
+ sendScimError(res, 400, 'Invalid request body');
326
+ }
327
+ }
328
+ async function handleReplaceGroup(req, res, id) {
329
+ const existing = getGroup(id);
330
+ if (!existing) {
331
+ sendScimError(res, 404, `Group ${id} not found`, 'invalidValue');
332
+ return;
333
+ }
334
+ try {
335
+ const body = (await parseJsonBody(req));
336
+ const updated = updateGroup(id, { ...body, id });
337
+ if (updated) {
338
+ res.writeHead(200, { 'Content-Type': SCIM_CONTENT_TYPE });
339
+ res.end(JSON.stringify(updated));
340
+ }
341
+ else {
342
+ sendScimError(res, 404, `Group ${id} not found`);
343
+ }
344
+ }
345
+ catch (_error) {
346
+ sendScimError(res, 400, 'Invalid request body');
347
+ }
348
+ }
349
+ async function handlePatchGroup(req, res, id) {
350
+ const existing = getGroup(id);
351
+ if (!existing) {
352
+ sendScimError(res, 404, `Group ${id} not found`, 'invalidValue');
353
+ return;
354
+ }
355
+ try {
356
+ const body = (await parseJsonBody(req));
357
+ const operations = body.Operations || [];
358
+ const updated = { ...existing };
359
+ for (const op of operations) {
360
+ if (op.op === 'replace' && op.path && op.value !== undefined) {
361
+ if (op.path === 'displayName') {
362
+ updated.displayName = op.value;
363
+ }
364
+ }
365
+ else if (op.op === 'add' && op.path && op.value !== undefined) {
366
+ if (op.path === 'members') {
367
+ updated.members = [...(updated.members || []), ...(op.value || [])];
368
+ }
369
+ }
370
+ else if (op.op === 'remove' && op.path) {
371
+ if (op.path.startsWith('members[')) {
372
+ // Parse member filter like members[value eq "user-id"]
373
+ const match = op.path.match(/members\[value eq "([^"]+)"\]/);
374
+ if (match) {
375
+ updated.members = (updated.members || []).filter((m) => m.value !== match[1]);
376
+ }
377
+ }
378
+ }
379
+ }
380
+ const result = updateGroup(id, updated);
381
+ if (result) {
382
+ res.writeHead(200, { 'Content-Type': SCIM_CONTENT_TYPE });
383
+ res.end(JSON.stringify(result));
384
+ }
385
+ else {
386
+ sendScimError(res, 404, `Group ${id} not found`);
387
+ }
388
+ }
389
+ catch (_error) {
390
+ sendScimError(res, 400, 'Invalid request body');
391
+ }
392
+ }
393
+ function handleDeleteGroup(res, id) {
394
+ const deleted = deleteGroup(id);
395
+ if (!deleted) {
396
+ sendScimError(res, 404, `Group ${id} not found`, 'invalidValue');
397
+ return;
398
+ }
399
+ res.writeHead(204);
400
+ res.end();
401
+ }
402
+ //# sourceMappingURL=iam.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"iam.js","sourceRoot":"","sources":["../../src/server/iam.ts"],"names":[],"mappings":"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"}