@@ -369,4 +369,163 @@ export const registerCommands = (context: vscode.ExtensionContext, configuration
369
369
? terminal . sendText ( `${ devProxyExe } --discover --watch-process-names ${ processNames . trim ( ) } ` )
370
370
: terminal . sendText ( `${ devProxyExe } --discover` ) ;
371
371
} ) ) ;
372
+
373
+ context . subscriptions . push (
374
+ vscode . commands . registerCommand ( 'dev-proxy-toolkit.jwt-create' , async ( ) => {
375
+ try {
376
+ // Collect JWT parameters through input dialogs with sensible defaults
377
+ const name = await vscode . window . showInputBox ( {
378
+ prompt : 'Enter the name of the user to create the token for' ,
379
+ placeHolder : 'Dev Proxy' ,
380
+ value : 'Dev Proxy' ,
381
+ title : 'JWT Generation - User Name'
382
+ } ) ;
383
+
384
+ if ( name === undefined ) {
385
+ return ; // User cancelled
386
+ }
387
+
388
+ const issuer = await vscode . window . showInputBox ( {
389
+ prompt : 'Enter the issuer of the token' ,
390
+ placeHolder : 'dev-proxy' ,
391
+ value : 'dev-proxy' ,
392
+ title : 'JWT Generation - Issuer'
393
+ } ) ;
394
+
395
+ if ( issuer === undefined ) {
396
+ return ; // User cancelled
397
+ }
398
+
399
+ const audiences = await vscode . window . showInputBox ( {
400
+ prompt : 'Enter the audiences (comma-separated for multiple)' ,
401
+ placeHolder : 'https://myserver.com' ,
402
+ value : 'https://myserver.com' ,
403
+ title : 'JWT Generation - Audiences'
404
+ } ) ;
405
+
406
+ if ( audiences === undefined ) {
407
+ return ; // User cancelled
408
+ }
409
+
410
+ const roles = await vscode . window . showInputBox ( {
411
+ prompt : 'Enter roles (comma-separated, leave empty for none)' ,
412
+ placeHolder : 'admin,user' ,
413
+ value : '' ,
414
+ title : 'JWT Generation - Roles (Optional)'
415
+ } ) ;
416
+
417
+ if ( roles === undefined ) {
418
+ return ; // User cancelled
419
+ }
420
+
421
+ const scopes = await vscode . window . showInputBox ( {
422
+ prompt : 'Enter scopes (comma-separated, leave empty for none)' ,
423
+ placeHolder : 'read,write' ,
424
+ value : '' ,
425
+ title : 'JWT Generation - Scopes (Optional)'
426
+ } ) ;
427
+
428
+ if ( scopes === undefined ) {
429
+ return ; // User cancelled
430
+ }
431
+
432
+ const claims = await vscode . window . showInputBox ( {
433
+ prompt : 'Enter custom claims in format name:value (comma-separated, leave empty for none)' ,
434
+ placeHolder : 'custom:claim,department:engineering' ,
435
+ value : '' ,
436
+ title : 'JWT Generation - Custom Claims (Optional)'
437
+ } ) ;
438
+
439
+ if ( claims === undefined ) {
440
+ return ; // User cancelled
441
+ }
442
+
443
+ const validFor = await vscode . window . showInputBox ( {
444
+ prompt : 'Enter token validity duration in minutes' ,
445
+ placeHolder : '60' ,
446
+ value : '60' ,
447
+ title : 'JWT Generation - Validity Duration' ,
448
+ validateInput : ( value : string ) => {
449
+ const num = parseInt ( value ) ;
450
+ if ( isNaN ( num ) || num <= 0 ) {
451
+ return 'Please enter a positive number' ;
452
+ }
453
+ return undefined ;
454
+ }
455
+ } ) ;
456
+
457
+ if ( validFor === undefined ) {
458
+ return ; // User cancelled
459
+ }
460
+
461
+ // Build the command with all parameters
462
+ let command = `${ devProxyExe } jwt create --name "${ name } " --issuer "${ issuer } " --valid-for ${ validFor } ` ;
463
+
464
+ // Add audiences (can have multiple)
465
+ const audienceList = audiences . split ( ',' ) . map ( a => a . trim ( ) ) . filter ( a => a ) ;
466
+ audienceList . forEach ( audience => {
467
+ command += ` --audiences "${ audience } "` ;
468
+ } ) ;
469
+
470
+ // Add roles if provided
471
+ const roleList = roles . split ( ',' ) . map ( r => r . trim ( ) ) . filter ( r => r ) ;
472
+ roleList . forEach ( role => {
473
+ command += ` --roles "${ role } "` ;
474
+ } ) ;
475
+
476
+ // Add scopes if provided
477
+ const scopeList = scopes . split ( ',' ) . map ( s => s . trim ( ) ) . filter ( s => s ) ;
478
+ scopeList . forEach ( scope => {
479
+ command += ` --scopes "${ scope } "` ;
480
+ } ) ;
481
+
482
+ // Add custom claims if provided
483
+ const claimList = claims . split ( ',' ) . map ( c => c . trim ( ) ) . filter ( c => c ) ;
484
+ claimList . forEach ( claim => {
485
+ if ( claim . includes ( ':' ) ) {
486
+ command += ` --claims "${ claim } "` ;
487
+ }
488
+ } ) ;
489
+
490
+ // Show progress and execute the command
491
+ await vscode . window . withProgress ( {
492
+ location : vscode . ProgressLocation . Notification ,
493
+ title : 'Generating JWT...' ,
494
+ cancellable : false
495
+ } , async ( ) => {
496
+ try {
497
+ const result = await executeCommand ( command ) ;
498
+
499
+ // Extract the token from the result (it should be on the last non-empty line)
500
+ const lines = result . split ( '\n' ) . filter ( line => line . trim ( ) ) ;
501
+ const token = lines [ lines . length - 1 ] . trim ( ) ;
502
+
503
+ // Show the token in a dialog with copy option
504
+ const choice = await vscode . window . showInformationMessage (
505
+ 'JWT generated successfully!' ,
506
+ { modal : true } ,
507
+ 'Copy to Clipboard' ,
508
+ 'Show Token'
509
+ ) ;
510
+
511
+ if ( choice === 'Copy to Clipboard' ) {
512
+ await vscode . env . clipboard . writeText ( token ) ;
513
+ vscode . window . showInformationMessage ( 'JWT copied to clipboard' ) ;
514
+ } else if ( choice === 'Show Token' ) {
515
+ // Create a new untitled document to show the token
516
+ const document = await vscode . workspace . openTextDocument ( {
517
+ content : `JWT Generated: ${ new Date ( ) . toISOString ( ) } \n\nToken: ${ token } \n\nCommand used:\n${ command } ` ,
518
+ language : 'plaintext'
519
+ } ) ;
520
+ await vscode . window . showTextDocument ( document ) ;
521
+ }
522
+ } catch ( error ) {
523
+ vscode . window . showErrorMessage ( `Failed to generate JWT token: ${ error } ` ) ;
524
+ }
525
+ } ) ;
526
+
527
+ } catch ( error ) {
528
+ vscode . window . showErrorMessage ( `Error in JWT generation: ${ error } ` ) ;
529
+ }
530
+ } ) ) ;
372
531
} ;
0 commit comments