@makolabs/ripple 1.6.4 → 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.
@@ -349,19 +349,46 @@ async function refreshTokenIfSelfUpdate(userId) {
349
349
  export const updateUserPermissions = command('unchecked', async (options) => {
350
350
  const { userId, permissions } = options;
351
351
  try {
352
- // Fetch all keys for this specific user (not paginated, gets all keys)
352
+ // Fetch user's active keys
353
353
  const allKeysData = await makeAdminRequest(`/admin/keys?client_id=${CLIENT_ID}&sub=${userId}`);
354
- // Find ALL active keys for this user (not just one)
355
354
  const userKeys = (allKeysData?.data?.data || []).filter((key) => key.status === 'active');
356
- // Create new key first, then delete old ones (safer order)
357
- const newKey = await createUserPermissions(userId, permissions);
358
- // Only delete old keys after new key is successfully created
359
- if (userKeys.length > 0 && newKey) {
360
- await Promise.all(userKeys.map((key) => makeAdminRequest(`/admin/keys/${key.id}`, {
361
- method: 'DELETE'
362
- }).catch((err) => {
363
- console.warn(`[updateUserPermissions] Failed to delete key ${key.id}:`, err);
364
- })));
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
+ }
365
392
  }
366
393
  await refreshTokenIfSelfUpdate(userId);
367
394
  }
@@ -379,30 +406,39 @@ export const generateApiKey = command('unchecked', async (options) => {
379
406
  if (filteredPermissions.length === 0 && PERMISSION_PREFIX) {
380
407
  filteredPermissions = [`${PERMISSION_PREFIX}readonly`];
381
408
  }
382
- let oldKeyId = null;
383
- if (options.revokeOld) {
384
- try {
385
- const allKeysData = await makeAdminRequest('/admin/keys');
386
- if (allKeysData?.data?.data && Array.isArray(allKeysData.data.data)) {
387
- const userKey = allKeysData.data.data.find((key) => key.sub === options.userId && key.client_id === CLIENT_ID && key.status === 'active');
388
- if (userKey) {
389
- oldKeyId = userKey.id;
390
- }
391
- }
392
- }
393
- catch (e) {
394
- 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');
395
428
  }
396
429
  }
397
- const createData = await createUserPermissions(options.userId, filteredPermissions);
398
- if (!createData) {
399
- throw new Error('Failed to create admin key');
400
- }
401
- const newApiKey = createData?.data?.key;
402
- if (!newApiKey) {
403
- console.error('[generateApiKey] No API key in response:', createData);
404
- 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
+ }
405
440
  }
441
+ // Update Clerk profile with new key
406
442
  try {
407
443
  const currentUser = await makeClerkRequest(`/users/${options.userId}`);
408
444
  await makeClerkRequest(`/users/${options.userId}`, {
@@ -419,22 +455,11 @@ export const generateApiKey = command('unchecked', async (options) => {
419
455
  console.error('[generateApiKey] Failed to update Clerk profile:', clerkError);
420
456
  console.warn('[generateApiKey] Key generated but could not update Clerk profile');
421
457
  }
422
- if (oldKeyId) {
423
- try {
424
- await makeAdminRequest(`/admin/keys/${oldKeyId}`, {
425
- method: 'DELETE'
426
- });
427
- }
428
- catch (revokeError) {
429
- console.error('[generateApiKey] Failed to revoke old key:', revokeError);
430
- console.warn('[generateApiKey] New key generated but could not revoke old key');
431
- }
432
- }
433
458
  const result = {
434
459
  success: true,
435
460
  apiKey: newApiKey,
436
- message: oldKeyId
437
- ? 'New API key generated and old key revoked successfully'
461
+ message: wasRotated
462
+ ? 'API key rotated successfully'
438
463
  : 'API key generated successfully'
439
464
  };
440
465
  return JSON.parse(JSON.stringify(result));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@makolabs/ripple",
3
- "version": "1.6.4",
3
+ "version": "1.6.5",
4
4
  "description": "Simple Svelte 5 powered component library ✨",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "repository": {