@makolabs/ripple 1.6.3 → 1.6.5

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.
@@ -285,6 +285,7 @@ async function fetchUserPermissions(userId) {
285
285
  return [];
286
286
  }
287
287
  catch (error) {
288
+ console.error('[fetchUserPermissions] Error fetching user permissions:', error);
288
289
  try {
289
290
  const allKeysData = await makeAdminRequest('/admin/keys');
290
291
  const userKey = allKeysData.data.data.find((key) => key.sub === userId && key.client_id === CLIENT_ID && key.status === 'active');
@@ -348,20 +349,47 @@ async function refreshTokenIfSelfUpdate(userId) {
348
349
  export const updateUserPermissions = command('unchecked', async (options) => {
349
350
  const { userId, permissions } = options;
350
351
  try {
351
- // Fetch all keys for this specific user (not paginated, gets all keys)
352
+ // Fetch user's active keys
352
353
  const allKeysData = await makeAdminRequest(`/admin/keys?client_id=${CLIENT_ID}&sub=${userId}`);
353
- // Find ALL active keys for this user (not just one)
354
354
  const userKeys = (allKeysData?.data?.data || []).filter((key) => key.status === 'active');
355
- // Delete all old active keys to ensure clean state
356
- if (userKeys.length > 0) {
357
- await Promise.all(userKeys.map((key) => makeAdminRequest(`/admin/keys/${key.id}`, {
358
- method: 'DELETE'
359
- }).catch((err) => {
360
- console.warn(`[updateUserPermissions] Failed to delete key ${key.id}:`, err);
361
- })));
355
+ const filteredPermissions = PERMISSION_PREFIX
356
+ ? permissions.filter((scope) => scope.startsWith(PERMISSION_PREFIX))
357
+ : permissions;
358
+ if (userKeys.length === 0) {
359
+ // No active key exists, create new one
360
+ const newKeyResult = await createUserPermissions(userId, permissions);
361
+ const newApiKey = newKeyResult?.data?.key;
362
+ if (newApiKey) {
363
+ const currentUser = await makeClerkRequest(`/users/${userId}`);
364
+ await makeClerkRequest(`/users/${userId}`, {
365
+ method: 'PATCH',
366
+ body: JSON.stringify({
367
+ private_metadata: {
368
+ ...(currentUser.private_metadata || {}),
369
+ mako_api_key: newApiKey
370
+ }
371
+ })
372
+ });
373
+ }
374
+ }
375
+ else {
376
+ // Use PUT to update existing key (per Mako Auth API spec)
377
+ const keyId = userKeys[0].id;
378
+ await makeAdminRequest(`/admin/keys/${keyId}`, {
379
+ method: 'PUT',
380
+ body: JSON.stringify({
381
+ scopes: filteredPermissions
382
+ })
383
+ });
384
+ // Clean up any extra keys (there should only be one)
385
+ if (userKeys.length > 1) {
386
+ await Promise.all(userKeys.slice(1).map((key) => makeAdminRequest(`/admin/keys/${key.id}`, {
387
+ method: 'DELETE'
388
+ }).catch((err) => {
389
+ console.warn(`[updateUserPermissions] Failed to delete extra key ${key.id}:`, err);
390
+ })));
391
+ }
362
392
  }
363
- // Create one new key with updated permissions
364
- await createUserPermissions(userId, permissions);
365
393
  await refreshTokenIfSelfUpdate(userId);
366
394
  }
367
395
  catch (error) {
@@ -378,30 +406,39 @@ export const generateApiKey = command('unchecked', async (options) => {
378
406
  if (filteredPermissions.length === 0 && PERMISSION_PREFIX) {
379
407
  filteredPermissions = [`${PERMISSION_PREFIX}readonly`];
380
408
  }
381
- let oldKeyId = null;
382
- if (options.revokeOld) {
383
- try {
384
- const allKeysData = await makeAdminRequest('/admin/keys');
385
- if (allKeysData?.data?.data && Array.isArray(allKeysData.data.data)) {
386
- const userKey = allKeysData.data.data.find((key) => key.sub === options.userId && key.client_id === CLIENT_ID && key.status === 'active');
387
- if (userKey) {
388
- oldKeyId = userKey.id;
389
- }
390
- }
391
- }
392
- catch (e) {
393
- console.warn('[generateApiKey] Could not fetch existing key for revocation:', e);
409
+ // Check if user has existing active key
410
+ const allKeysData = await makeAdminRequest(`/admin/keys?client_id=${CLIENT_ID}&sub=${options.userId}`);
411
+ const userKeys = (allKeysData?.data?.data || []).filter((key) => key.status === 'active');
412
+ let newApiKey;
413
+ let wasRotated = false;
414
+ if (userKeys.length > 0 && options.revokeOld) {
415
+ // Use rotate endpoint (per Mako Auth API spec)
416
+ const keyId = userKeys[0].id;
417
+ const rotateResult = await makeAdminRequest(`/admin/keys/${keyId}/rotate`, {
418
+ method: 'POST',
419
+ body: JSON.stringify({
420
+ scopes: filteredPermissions
421
+ })
422
+ });
423
+ // Rotate endpoint returns key in data.key field
424
+ newApiKey = rotateResult?.data?.key;
425
+ wasRotated = true;
426
+ if (!newApiKey) {
427
+ throw new Error('Failed to rotate API key - no key in response');
394
428
  }
395
429
  }
396
- const createData = await createUserPermissions(options.userId, filteredPermissions);
397
- if (!createData) {
398
- throw new Error('Failed to create admin key');
399
- }
400
- const newApiKey = createData?.data?.key;
401
- if (!newApiKey) {
402
- console.error('[generateApiKey] No API key in response:', createData);
403
- throw new Error('Failed to generate API key - no key in response');
430
+ else {
431
+ // Create new key if none exists or revokeOld is false
432
+ const createData = await createUserPermissions(options.userId, filteredPermissions);
433
+ if (!createData) {
434
+ throw new Error('Failed to create admin key');
435
+ }
436
+ newApiKey = createData?.data?.key;
437
+ if (!newApiKey) {
438
+ throw new Error('Failed to generate API key - no key in response');
439
+ }
404
440
  }
441
+ // Update Clerk profile with new key
405
442
  try {
406
443
  const currentUser = await makeClerkRequest(`/users/${options.userId}`);
407
444
  await makeClerkRequest(`/users/${options.userId}`, {
@@ -418,22 +455,11 @@ export const generateApiKey = command('unchecked', async (options) => {
418
455
  console.error('[generateApiKey] Failed to update Clerk profile:', clerkError);
419
456
  console.warn('[generateApiKey] Key generated but could not update Clerk profile');
420
457
  }
421
- if (oldKeyId) {
422
- try {
423
- await makeAdminRequest(`/admin/keys/${oldKeyId}`, {
424
- method: 'DELETE'
425
- });
426
- }
427
- catch (revokeError) {
428
- console.error('[generateApiKey] Failed to revoke old key:', revokeError);
429
- console.warn('[generateApiKey] New key generated but could not revoke old key');
430
- }
431
- }
432
458
  const result = {
433
459
  success: true,
434
460
  apiKey: newApiKey,
435
- message: oldKeyId
436
- ? 'New API key generated and old key revoked successfully'
461
+ message: wasRotated
462
+ ? 'API key rotated successfully'
437
463
  : 'API key generated successfully'
438
464
  };
439
465
  return JSON.parse(JSON.stringify(result));
@@ -164,7 +164,7 @@
164
164
  role: formData.role,
165
165
  permissions: formData.permissions
166
166
  };
167
-
167
+
168
168
  await onSave(userData, mode);
169
169
  handleClose();
170
170
  } catch (error) {
@@ -177,7 +177,7 @@
177
177
 
178
178
  function handleRoleChange(roleValue: string) {
179
179
  const role = roles?.find((r: Role) => r.value === roleValue);
180
-
180
+
181
181
  // Reassign entire formData object to ensure Svelte 5 reactivity
182
182
  formData = {
183
183
  ...formData,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@makolabs/ripple",
3
- "version": "1.6.3",
3
+ "version": "1.6.5",
4
4
  "description": "Simple Svelte 5 powered component library ✨",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "repository": {