From 1b956bc90a47f169f958fce3ad8e7bd4c75ed023 Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Thu, 8 Feb 2024 15:15:10 +0000 Subject: [PATCH 01/23] setup commands for token create & delete --- .../globe_cli/lib/src/command_runner.dart | 1 + .../globe_cli/lib/src/commands/commands.dart | 1 + .../commands/token/token_create_command.dart | 37 +++++++++++++++++++ .../commands/token/token_delete_command.dart | 18 +++++++++ .../lib/src/commands/token_command.dart | 15 ++++++++ 5 files changed, 72 insertions(+) create mode 100644 packages/globe_cli/lib/src/commands/token/token_create_command.dart create mode 100644 packages/globe_cli/lib/src/commands/token/token_delete_command.dart create mode 100644 packages/globe_cli/lib/src/commands/token_command.dart diff --git a/packages/globe_cli/lib/src/command_runner.dart b/packages/globe_cli/lib/src/command_runner.dart index cadcb226..6f203aa7 100644 --- a/packages/globe_cli/lib/src/command_runner.dart +++ b/packages/globe_cli/lib/src/command_runner.dart @@ -50,6 +50,7 @@ class GlobeCliCommandRunner extends CompletionCommandRunner { addCommand(LinkCommand()); addCommand(UnlinkCommand()); addCommand(BuildLogsCommand()); + addCommand(TokenCommand()); } final Logger _logger; diff --git a/packages/globe_cli/lib/src/commands/commands.dart b/packages/globe_cli/lib/src/commands/commands.dart index b5c486e6..8b8f39b7 100644 --- a/packages/globe_cli/lib/src/commands/commands.dart +++ b/packages/globe_cli/lib/src/commands/commands.dart @@ -2,4 +2,5 @@ export 'deploy_command.dart'; export 'link_command.dart'; export 'login_command.dart'; export 'logout_command.dart'; +export 'token_command.dart'; export 'unlink_command.dart'; diff --git a/packages/globe_cli/lib/src/commands/token/token_create_command.dart b/packages/globe_cli/lib/src/commands/token/token_create_command.dart new file mode 100644 index 00000000..738c4b95 --- /dev/null +++ b/packages/globe_cli/lib/src/commands/token/token_create_command.dart @@ -0,0 +1,37 @@ +import 'dart:async'; + +import '../../command.dart'; + +class TokenCreateCommand extends BaseGlobeCommand { + TokenCreateCommand() { + argParser + ..addOption( + 'name', + // abbr: 'n', + help: 'Specify name to identity token.', + ) + ..addOption( + 'expiry', + // abbr: 'x', + help: 'Specify lifespan of token.', + ) + ..addOption( + 'project', + // abbr: 'p', + help: 'Specify projects(s) to associate token with.', + ); + } + + @override + String get description => 'Create auth tokens for your projects.'; + + @override + String get name => 'create'; + + @override + FutureOr run() async { + requireAuth(); + + return 0; + } +} diff --git a/packages/globe_cli/lib/src/commands/token/token_delete_command.dart b/packages/globe_cli/lib/src/commands/token/token_delete_command.dart new file mode 100644 index 00000000..b3659c01 --- /dev/null +++ b/packages/globe_cli/lib/src/commands/token/token_delete_command.dart @@ -0,0 +1,18 @@ +import 'dart:async'; + +import '../../command.dart'; + +class TokenDeleteCommand extends BaseGlobeCommand { + @override + String get description => 'Delete token associated with project.'; + + @override + String get name => 'delete'; + + @override + FutureOr run() async { + requireAuth(); + + return 0; + } +} diff --git a/packages/globe_cli/lib/src/commands/token_command.dart b/packages/globe_cli/lib/src/commands/token_command.dart new file mode 100644 index 00000000..00bd47f5 --- /dev/null +++ b/packages/globe_cli/lib/src/commands/token_command.dart @@ -0,0 +1,15 @@ +import '../command.dart'; +import 'token/token_create_command.dart'; +import 'token/token_delete_command.dart'; + +class TokenCommand extends BaseGlobeCommand { + TokenCommand() { + addSubcommand(TokenCreateCommand()); + addSubcommand(TokenDeleteCommand()); + } + @override + String get description => 'Manage globe auth tokens.'; + + @override + String get name => 'token'; +} From 59766bd3e950b3e27681851eded362d4b80fa79d Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Mon, 12 Feb 2024 01:59:20 +0000 Subject: [PATCH 02/23] implement token create command --- .../commands/token/token_create_command.dart | 38 +++++++++- packages/globe_cli/lib/src/utils/api.dart | 73 +++++++++++++++++++ packages/globe_cli/lib/src/utils/prompts.dart | 44 +++++++++++ 3 files changed, 154 insertions(+), 1 deletion(-) diff --git a/packages/globe_cli/lib/src/commands/token/token_create_command.dart b/packages/globe_cli/lib/src/commands/token/token_create_command.dart index 738c4b95..74ea31c8 100644 --- a/packages/globe_cli/lib/src/commands/token/token_create_command.dart +++ b/packages/globe_cli/lib/src/commands/token/token_create_command.dart @@ -1,6 +1,10 @@ import 'dart:async'; +import 'package:mason_logger/mason_logger.dart'; + import '../../command.dart'; +import '../../utils/api.dart'; +import '../../utils/prompts.dart'; class TokenCreateCommand extends BaseGlobeCommand { TokenCreateCommand() { @@ -32,6 +36,38 @@ class TokenCreateCommand extends BaseGlobeCommand { FutureOr run() async { requireAuth(); - return 0; + final validated = await scope.validate(); + + final projects = await selectProjects( + validated.organization, + logger: logger, + api: api, + scope: scope, + ); + if (projects.isEmpty) { + return ExitCode.software.code; + } + + final projectNames = projects.map((e) => cyan.wrap(e.slug)).join(', '); + final createTokenProgress = + logger.progress('Creating Token for $projectNames'); + + try { + final token = await api.createToken( + orgId: validated.organization.slug, + name: 'New Token', + projectUuids: projects.map((e) => e.id).toList(), + expiresAt: DateTime(2024, 12), + ); + createTokenProgress.complete("Here's your token: ${cyan.wrap(token)}"); + return ExitCode.success.code; + } on ApiException catch (e) { + createTokenProgress.fail('✗ Failed to create token: ${e.message}'); + return ExitCode.software.code; + } catch (e, s) { + createTokenProgress.fail('✗ Failed to create token: $e'); + logger.detail(s.toString()); + return ExitCode.software.code; + } } } diff --git a/packages/globe_cli/lib/src/utils/api.dart b/packages/globe_cli/lib/src/utils/api.dart index f139963c..603871af 100644 --- a/packages/globe_cli/lib/src/utils/api.dart +++ b/packages/globe_cli/lib/src/utils/api.dart @@ -219,6 +219,41 @@ class GlobeApi { return Deployment.fromJson(response); } + + Future createToken({ + required String orgId, + required String name, + required List projectUuids, + required DateTime expiresAt, + }) async { + requireAuth(); + logger.detail('API Request: POST /orgs/$orgId/api-tokens'); + + final body = json.encode({ + 'name': name, + 'projectUuids': projectUuids, + 'expiresAt': expiresAt.toIso8601String() + }); + + // create token + var response = _handleResponse( + await http.post( + _buildUri('/orgs/$orgId/api-tokens'), + headers: headers, + body: body, + ), + )! as Map; + final token = Token.fromJson(response); + + // get token value + response = _handleResponse( + await http.get( + _buildUri('/orgs/$orgId/api-tokens/${token.uuid}/generate'), + headers: headers, + ), + )! as Map; + return response['token'].toString(); + } } class Settings { @@ -564,3 +599,41 @@ enum OrganizationType { } } } + +class Token { + final String uuid; + final String name; + final String organizationUuid; + final DateTime expiresAt; + final List cliTokenClaimProject; + + const Token._({ + required this.uuid, + required this.name, + required this.organizationUuid, + required this.expiresAt, + required this.cliTokenClaimProject, + }); + + factory Token.fromJson(Map json) { + return switch (json) { + { + 'uuid': final String uuid, + 'name': final String name, + 'organizationUuid': final String organizationUuid, + 'expiresAt': final String expiresAt, + 'cliTokenClaimProject': final List cliTokenClaimProject, + } => + Token._( + uuid: uuid, + name: name, + organizationUuid: organizationUuid, + expiresAt: DateTime.parse(expiresAt), + cliTokenClaimProject: cliTokenClaimProject + .map((e) => (e as Map)['projectUuid'].toString()) + .toList(), + ), + _ => throw const FormatException('Token'), + }; + } +} diff --git a/packages/globe_cli/lib/src/utils/prompts.dart b/packages/globe_cli/lib/src/utils/prompts.dart index 3e231057..e5ba252b 100644 --- a/packages/globe_cli/lib/src/utils/prompts.dart +++ b/packages/globe_cli/lib/src/utils/prompts.dart @@ -314,3 +314,47 @@ Future selectProject( return projects.firstWhere((p) => p.id == selectedProject); } + +Future> selectProjects( + Organization organization, { + required Logger logger, + required GlobeApi api, + required GlobeScope scope, +}) async { + logger.detail('Fetching organization projects'); + final projects = await api.getProjects(org: organization.id); + logger.detail('Found ${projects.length} projects'); + + if (projects.isEmpty) { + logger.detail( + 'No projects found, you need to create a new project first.', + ); + logger.err('No projects found.'); + exitOverride(1); + } + + /// If there's only one, automatically select it. + if (projects.length == 1) { + final project = projects.first; + logger.detail('Automatically selecting ${project.slug}.'); + return projects; + } + + final projectsMap = projects + .fold>({}, (prev, curr) => prev..[curr.slug] = curr); + + /// Ask user to choose zero or more options. + final selections = logger.chooseAny( + 'Select projects to associate token with:', + choices: projectsMap.keys.toList(), + ); + + if (selections.isEmpty) { + logger.detail( + 'No projects selected, you need to select atleast one project.', + ); + logger.err('No projects selected.'); + } + + return selections.map((e) => projectsMap[e]!).toList(); +} From 4510167af9203ae2b05355ebe1efd6b55e597605 Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Mon, 12 Feb 2024 02:56:41 +0000 Subject: [PATCH 03/23] use token name & expiry from command args --- .../commands/token/token_create_command.dart | 28 +++++++++++++++---- packages/globe_cli/lib/src/utils/prompts.dart | 22 +++++++++++++-- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/packages/globe_cli/lib/src/commands/token/token_create_command.dart b/packages/globe_cli/lib/src/commands/token/token_create_command.dart index 74ea31c8..9e1bf29f 100644 --- a/packages/globe_cli/lib/src/commands/token/token_create_command.dart +++ b/packages/globe_cli/lib/src/commands/token/token_create_command.dart @@ -3,6 +3,7 @@ import 'dart:async'; import 'package:mason_logger/mason_logger.dart'; import '../../command.dart'; +import '../../exit.dart'; import '../../utils/api.dart'; import '../../utils/prompts.dart'; @@ -11,17 +12,18 @@ class TokenCreateCommand extends BaseGlobeCommand { argParser ..addOption( 'name', - // abbr: 'n', + abbr: 'n', + mandatory: true, help: 'Specify name to identity token.', ) ..addOption( 'expiry', - // abbr: 'x', + abbr: 'e', + mandatory: true, help: 'Specify lifespan of token.', ) ..addOption( 'project', - // abbr: 'p', help: 'Specify projects(s) to associate token with.', ); } @@ -36,6 +38,21 @@ class TokenCreateCommand extends BaseGlobeCommand { FutureOr run() async { requireAuth(); + final name = argResults?['name'] as String; + final dateString = argResults?['expiry'] as String; + final expiry = DateTime.tryParse(dateString)?.toUtc(); + if (expiry == null) { + logger.err( + 'Invalid date format.\nDate format should be ${cyan.wrap('2012-02-27')} or ${cyan.wrap('2012-02-27 13:27:00"')}', + ); + exitOverride(1); + } + + final projectIds = (argResults?['project'] as String?) + ?.split(',') + .map((e) => e.trim()) + .toList(); + final validated = await scope.validate(); final projects = await selectProjects( @@ -43,6 +60,7 @@ class TokenCreateCommand extends BaseGlobeCommand { logger: logger, api: api, scope: scope, + ids: projectIds, ); if (projects.isEmpty) { return ExitCode.software.code; @@ -55,9 +73,9 @@ class TokenCreateCommand extends BaseGlobeCommand { try { final token = await api.createToken( orgId: validated.organization.slug, - name: 'New Token', + name: name, projectUuids: projects.map((e) => e.id).toList(), - expiresAt: DateTime(2024, 12), + expiresAt: expiry, ); createTokenProgress.complete("Here's your token: ${cyan.wrap(token)}"); return ExitCode.success.code; diff --git a/packages/globe_cli/lib/src/utils/prompts.dart b/packages/globe_cli/lib/src/utils/prompts.dart index e5ba252b..0d4c395d 100644 --- a/packages/globe_cli/lib/src/utils/prompts.dart +++ b/packages/globe_cli/lib/src/utils/prompts.dart @@ -315,11 +315,15 @@ Future selectProject( return projects.firstWhere((p) => p.id == selectedProject); } +/// Prompts the user to select single or multiple projects. +/// +/// Optionally pass [ids] to only verify projects Ids actually exist Future> selectProjects( Organization organization, { required Logger logger, required GlobeApi api, required GlobeScope scope, + List? ids, }) async { logger.detail('Fetching organization projects'); final projects = await api.getProjects(org: organization.id); @@ -333,6 +337,18 @@ Future> selectProjects( exitOverride(1); } + /// If ids passed, verify they exist + if (ids != null && ids.isNotEmpty) { + final projectsById = projects + .fold>({}, (prev, curr) => prev..[curr.id] = curr); + final invalidIds = ids.where((id) => projectsById[id] == null); + if (invalidIds.isNotEmpty) { + logger.err('Project not found: ${cyan.wrap(invalidIds.join(', '))}.'); + exitOverride(1); + } + return ids.map((id) => projectsById[id]!).toList(); + } + /// If there's only one, automatically select it. if (projects.length == 1) { final project = projects.first; @@ -340,13 +356,13 @@ Future> selectProjects( return projects; } - final projectsMap = projects + final projectsBySlug = projects .fold>({}, (prev, curr) => prev..[curr.slug] = curr); /// Ask user to choose zero or more options. final selections = logger.chooseAny( 'Select projects to associate token with:', - choices: projectsMap.keys.toList(), + choices: projectsBySlug.keys.toList(), ); if (selections.isEmpty) { @@ -356,5 +372,5 @@ Future> selectProjects( logger.err('No projects selected.'); } - return selections.map((e) => projectsMap[e]!).toList(); + return selections.map((e) => projectsBySlug[e]!).toList(); } From 0663b73d068501f3f1888fc9931461aaeeb4b46c Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Mon, 12 Feb 2024 03:27:58 +0000 Subject: [PATCH 04/23] fix formatting --- packages/globe_cli/lib/src/utils/api.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/globe_cli/lib/src/utils/api.dart b/packages/globe_cli/lib/src/utils/api.dart index 603871af..ea80896d 100644 --- a/packages/globe_cli/lib/src/utils/api.dart +++ b/packages/globe_cli/lib/src/utils/api.dart @@ -232,7 +232,7 @@ class GlobeApi { final body = json.encode({ 'name': name, 'projectUuids': projectUuids, - 'expiresAt': expiresAt.toIso8601String() + 'expiresAt': expiresAt.toIso8601String(), }); // create token From 03e9020c80d3f0fb1ae7c59d9d8b4ee13b42dc42 Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Mon, 12 Feb 2024 03:40:45 +0000 Subject: [PATCH 05/23] use multi-option for project argument --- .../commands/token/token_create_command.dart | 10 +++------- packages/globe_cli/lib/src/utils/api.dart | 18 ++++++++---------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/packages/globe_cli/lib/src/commands/token/token_create_command.dart b/packages/globe_cli/lib/src/commands/token/token_create_command.dart index 9e1bf29f..406c1e91 100644 --- a/packages/globe_cli/lib/src/commands/token/token_create_command.dart +++ b/packages/globe_cli/lib/src/commands/token/token_create_command.dart @@ -22,14 +22,14 @@ class TokenCreateCommand extends BaseGlobeCommand { mandatory: true, help: 'Specify lifespan of token.', ) - ..addOption( + ..addMultiOption( 'project', help: 'Specify projects(s) to associate token with.', ); } @override - String get description => 'Create auth tokens for your projects.'; + String get description => 'Create globe auth token.'; @override String get name => 'create'; @@ -39,6 +39,7 @@ class TokenCreateCommand extends BaseGlobeCommand { requireAuth(); final name = argResults?['name'] as String; + final projectIds = argResults?['project'] as List?; final dateString = argResults?['expiry'] as String; final expiry = DateTime.tryParse(dateString)?.toUtc(); if (expiry == null) { @@ -48,11 +49,6 @@ class TokenCreateCommand extends BaseGlobeCommand { exitOverride(1); } - final projectIds = (argResults?['project'] as String?) - ?.split(',') - .map((e) => e.trim()) - .toList(); - final validated = await scope.validate(); final projects = await selectProjects( diff --git a/packages/globe_cli/lib/src/utils/api.dart b/packages/globe_cli/lib/src/utils/api.dart index ea80896d..4002dfbf 100644 --- a/packages/globe_cli/lib/src/utils/api.dart +++ b/packages/globe_cli/lib/src/utils/api.dart @@ -227,7 +227,9 @@ class GlobeApi { required DateTime expiresAt, }) async { requireAuth(); - logger.detail('API Request: POST /orgs/$orgId/api-tokens'); + + final createTokenPath = '/orgs/$orgId/api-tokens'; + logger.detail('API Request: POST $createTokenPath'); final body = json.encode({ 'name': name, @@ -237,20 +239,16 @@ class GlobeApi { // create token var response = _handleResponse( - await http.post( - _buildUri('/orgs/$orgId/api-tokens'), - headers: headers, - body: body, - ), + await http.post(_buildUri(createTokenPath), headers: headers, body: body), )! as Map; final token = Token.fromJson(response); + final generateTokenPath = '/orgs/$orgId/api-tokens/${token.uuid}/generate'; + logger.detail('API Request: POST $generateTokenPath'); + // get token value response = _handleResponse( - await http.get( - _buildUri('/orgs/$orgId/api-tokens/${token.uuid}/generate'), - headers: headers, - ), + await http.get(_buildUri(generateTokenPath), headers: headers), )! as Map; return response['token'].toString(); } From 16353d2c63922642e55ad339b340683adecdd165 Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Mon, 12 Feb 2024 03:59:34 +0000 Subject: [PATCH 06/23] return both token id and value --- .../commands/token/token_create_command.dart | 4 ++- .../commands/token/token_delete_command.dart | 30 ++++++++++++++++++- packages/globe_cli/lib/src/utils/api.dart | 18 +++++++++-- 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/packages/globe_cli/lib/src/commands/token/token_create_command.dart b/packages/globe_cli/lib/src/commands/token/token_create_command.dart index 406c1e91..dffb2a62 100644 --- a/packages/globe_cli/lib/src/commands/token/token_create_command.dart +++ b/packages/globe_cli/lib/src/commands/token/token_create_command.dart @@ -73,7 +73,9 @@ class TokenCreateCommand extends BaseGlobeCommand { projectUuids: projects.map((e) => e.id).toList(), expiresAt: expiry, ); - createTokenProgress.complete("Here's your token: ${cyan.wrap(token)}"); + createTokenProgress.complete( + "Here's your token:\nID: ${cyan.wrap(token.id)}\nToken: ${cyan.wrap(token.value)}", + ); return ExitCode.success.code; } on ApiException catch (e) { createTokenProgress.fail('✗ Failed to create token: ${e.message}'); diff --git a/packages/globe_cli/lib/src/commands/token/token_delete_command.dart b/packages/globe_cli/lib/src/commands/token/token_delete_command.dart index b3659c01..c0141936 100644 --- a/packages/globe_cli/lib/src/commands/token/token_delete_command.dart +++ b/packages/globe_cli/lib/src/commands/token/token_delete_command.dart @@ -1,10 +1,20 @@ import 'dart:async'; +import 'package:mason_logger/mason_logger.dart'; + import '../../command.dart'; +import '../../utils/api.dart'; class TokenDeleteCommand extends BaseGlobeCommand { + TokenDeleteCommand() { + argParser.addOption( + 'tokenId', + mandatory: true, + help: 'Specify globe auth token to delete.', + ); + } @override - String get description => 'Delete token associated with project.'; + String get description => 'Delete globe auth token.'; @override String get name => 'delete'; @@ -13,6 +23,24 @@ class TokenDeleteCommand extends BaseGlobeCommand { FutureOr run() async { requireAuth(); + final tokenId = argResults?['tokenId'] as String; + final validated = await scope.validate(); + + final deleteTokenProgress = + logger.progress('Deleting Token: ${cyan.wrap(tokenId)}'); + + try { + await api.deleteToken(orgId: validated.organization.id, tokenId: tokenId); + deleteTokenProgress.complete('Token deleted'); + } on ApiException catch (e) { + deleteTokenProgress.fail('✗ Failed to delete token: ${e.message}'); + return ExitCode.software.code; + } catch (e, s) { + deleteTokenProgress.fail('✗ Failed to delete token: $e'); + logger.detail(s.toString()); + return ExitCode.software.code; + } + return 0; } } diff --git a/packages/globe_cli/lib/src/utils/api.dart b/packages/globe_cli/lib/src/utils/api.dart index 4002dfbf..ab60a1e6 100644 --- a/packages/globe_cli/lib/src/utils/api.dart +++ b/packages/globe_cli/lib/src/utils/api.dart @@ -220,7 +220,7 @@ class GlobeApi { return Deployment.fromJson(response); } - Future createToken({ + Future<({String id, String value})> createToken({ required String orgId, required String name, required List projectUuids, @@ -250,7 +250,21 @@ class GlobeApi { response = _handleResponse( await http.get(_buildUri(generateTokenPath), headers: headers), )! as Map; - return response['token'].toString(); + return (id: token.uuid, value: response['token'].toString()); + } + + Future deleteToken({ + required String orgId, + required String tokenId, + }) async { + requireAuth(); + + final deleteTokenPath = '/orgs/$orgId/api-tokens/$tokenId'; + logger.detail('API Request: DELETE $deleteTokenPath'); + + _handleResponse( + await http.delete(_buildUri(deleteTokenPath), headers: headers), + )! as Map; } } From 1dbd0bcbd47c8c0e3bf8f2f1fedb6c8f536c8489 Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Mon, 12 Feb 2024 04:01:43 +0000 Subject: [PATCH 07/23] toUtc before send to api --- .../globe_cli/lib/src/commands/token/token_create_command.dart | 2 +- packages/globe_cli/lib/src/utils/api.dart | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/globe_cli/lib/src/commands/token/token_create_command.dart b/packages/globe_cli/lib/src/commands/token/token_create_command.dart index dffb2a62..0ee4b452 100644 --- a/packages/globe_cli/lib/src/commands/token/token_create_command.dart +++ b/packages/globe_cli/lib/src/commands/token/token_create_command.dart @@ -41,7 +41,7 @@ class TokenCreateCommand extends BaseGlobeCommand { final name = argResults?['name'] as String; final projectIds = argResults?['project'] as List?; final dateString = argResults?['expiry'] as String; - final expiry = DateTime.tryParse(dateString)?.toUtc(); + final expiry = DateTime.tryParse(dateString); if (expiry == null) { logger.err( 'Invalid date format.\nDate format should be ${cyan.wrap('2012-02-27')} or ${cyan.wrap('2012-02-27 13:27:00"')}', diff --git a/packages/globe_cli/lib/src/utils/api.dart b/packages/globe_cli/lib/src/utils/api.dart index ab60a1e6..2703045a 100644 --- a/packages/globe_cli/lib/src/utils/api.dart +++ b/packages/globe_cli/lib/src/utils/api.dart @@ -234,7 +234,7 @@ class GlobeApi { final body = json.encode({ 'name': name, 'projectUuids': projectUuids, - 'expiresAt': expiresAt.toIso8601String(), + 'expiresAt': expiresAt.toUtc().toIso8601String(), }); // create token From 4a351fee989c8febf4564ed5bbf3c0d5bf952830 Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Mon, 12 Feb 2024 04:16:18 +0000 Subject: [PATCH 08/23] tiny fix --- .../lib/src/commands/token/token_delete_command.dart | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/globe_cli/lib/src/commands/token/token_delete_command.dart b/packages/globe_cli/lib/src/commands/token/token_delete_command.dart index c0141936..937b8c58 100644 --- a/packages/globe_cli/lib/src/commands/token/token_delete_command.dart +++ b/packages/globe_cli/lib/src/commands/token/token_delete_command.dart @@ -30,7 +30,10 @@ class TokenDeleteCommand extends BaseGlobeCommand { logger.progress('Deleting Token: ${cyan.wrap(tokenId)}'); try { - await api.deleteToken(orgId: validated.organization.id, tokenId: tokenId); + await api.deleteToken( + orgId: validated.organization.slug, + tokenId: tokenId, + ); deleteTokenProgress.complete('Token deleted'); } on ApiException catch (e) { deleteTokenProgress.fail('✗ Failed to delete token: ${e.message}'); From 4269f34281bad600c13f87c1ff2c5a09844ceae6 Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Mon, 12 Feb 2024 04:20:04 +0000 Subject: [PATCH 09/23] tiny fix --- .../lib/src/commands/token/token_create_command.dart | 6 +----- packages/globe_cli/lib/src/utils/prompts.dart | 1 + 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/globe_cli/lib/src/commands/token/token_create_command.dart b/packages/globe_cli/lib/src/commands/token/token_create_command.dart index 0ee4b452..007b5e87 100644 --- a/packages/globe_cli/lib/src/commands/token/token_create_command.dart +++ b/packages/globe_cli/lib/src/commands/token/token_create_command.dart @@ -50,7 +50,6 @@ class TokenCreateCommand extends BaseGlobeCommand { } final validated = await scope.validate(); - final projects = await selectProjects( validated.organization, logger: logger, @@ -58,11 +57,8 @@ class TokenCreateCommand extends BaseGlobeCommand { scope: scope, ids: projectIds, ); - if (projects.isEmpty) { - return ExitCode.software.code; - } - final projectNames = projects.map((e) => cyan.wrap(e.slug)).join(', '); + final createTokenProgress = logger.progress('Creating Token for $projectNames'); diff --git a/packages/globe_cli/lib/src/utils/prompts.dart b/packages/globe_cli/lib/src/utils/prompts.dart index 0d4c395d..4b02cd9d 100644 --- a/packages/globe_cli/lib/src/utils/prompts.dart +++ b/packages/globe_cli/lib/src/utils/prompts.dart @@ -370,6 +370,7 @@ Future> selectProjects( 'No projects selected, you need to select atleast one project.', ); logger.err('No projects selected.'); + exitOverride(1); } return selections.map((e) => projectsBySlug[e]!).toList(); From 5e5f6023ade0c2b4d236a9f9a74684922d2228d7 Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Mon, 12 Feb 2024 11:28:36 +0000 Subject: [PATCH 10/23] tiny fix --- .../globe_cli/lib/src/commands/token/token_create_command.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/globe_cli/lib/src/commands/token/token_create_command.dart b/packages/globe_cli/lib/src/commands/token/token_create_command.dart index 007b5e87..1770fada 100644 --- a/packages/globe_cli/lib/src/commands/token/token_create_command.dart +++ b/packages/globe_cli/lib/src/commands/token/token_create_command.dart @@ -44,7 +44,7 @@ class TokenCreateCommand extends BaseGlobeCommand { final expiry = DateTime.tryParse(dateString); if (expiry == null) { logger.err( - 'Invalid date format.\nDate format should be ${cyan.wrap('2012-02-27')} or ${cyan.wrap('2012-02-27 13:27:00"')}', + 'Invalid date format.\nDate format should be ${cyan.wrap('2012-02-27')} or ${cyan.wrap('2012-02-27 13:27:00')}', ); exitOverride(1); } From 0a12c2f1032c75d4e2dd050d002e86190d7743b9 Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Fri, 16 Feb 2024 12:04:32 +0000 Subject: [PATCH 11/23] wip --- .../lib/src/commands/token/token_create_command.dart | 2 +- .../lib/src/commands/token/token_delete_command.dart | 2 +- packages/globe_cli/lib/src/utils/api.dart | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/globe_cli/lib/src/commands/token/token_create_command.dart b/packages/globe_cli/lib/src/commands/token/token_create_command.dart index 1770fada..053b3712 100644 --- a/packages/globe_cli/lib/src/commands/token/token_create_command.dart +++ b/packages/globe_cli/lib/src/commands/token/token_create_command.dart @@ -64,7 +64,7 @@ class TokenCreateCommand extends BaseGlobeCommand { try { final token = await api.createToken( - orgId: validated.organization.slug, + orgId: validated.organization.id, name: name, projectUuids: projects.map((e) => e.id).toList(), expiresAt: expiry, diff --git a/packages/globe_cli/lib/src/commands/token/token_delete_command.dart b/packages/globe_cli/lib/src/commands/token/token_delete_command.dart index 937b8c58..f4614ba9 100644 --- a/packages/globe_cli/lib/src/commands/token/token_delete_command.dart +++ b/packages/globe_cli/lib/src/commands/token/token_delete_command.dart @@ -31,7 +31,7 @@ class TokenDeleteCommand extends BaseGlobeCommand { try { await api.deleteToken( - orgId: validated.organization.slug, + orgId: validated.organization.id, tokenId: tokenId, ); deleteTokenProgress.complete('Token deleted'); diff --git a/packages/globe_cli/lib/src/utils/api.dart b/packages/globe_cli/lib/src/utils/api.dart index 2703045a..cf839be3 100644 --- a/packages/globe_cli/lib/src/utils/api.dart +++ b/packages/globe_cli/lib/src/utils/api.dart @@ -634,14 +634,14 @@ class Token { 'name': final String name, 'organizationUuid': final String organizationUuid, 'expiresAt': final String expiresAt, - 'cliTokenClaimProject': final List cliTokenClaimProject, + 'projects': final List projects, } => Token._( uuid: uuid, name: name, organizationUuid: organizationUuid, expiresAt: DateTime.parse(expiresAt), - cliTokenClaimProject: cliTokenClaimProject + cliTokenClaimProject: projects .map((e) => (e as Map)['projectUuid'].toString()) .toList(), ), From 86f6cdde55fce5090a5947453b2677241dc12fd1 Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Fri, 16 Feb 2024 12:09:25 +0000 Subject: [PATCH 12/23] wip --- packages/globe_cli/lib/src/utils/api.dart | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/globe_cli/lib/src/utils/api.dart b/packages/globe_cli/lib/src/utils/api.dart index cf839be3..a9bdc8f0 100644 --- a/packages/globe_cli/lib/src/utils/api.dart +++ b/packages/globe_cli/lib/src/utils/api.dart @@ -238,19 +238,20 @@ class GlobeApi { }); // create token - var response = _handleResponse( + final response = _handleResponse( await http.post(_buildUri(createTokenPath), headers: headers, body: body), )! as Map; final token = Token.fromJson(response); final generateTokenPath = '/orgs/$orgId/api-tokens/${token.uuid}/generate'; - logger.detail('API Request: POST $generateTokenPath'); + logger.detail('API Request: GET $generateTokenPath'); // get token value - response = _handleResponse( + final tokenValue = _handleResponse( await http.get(_buildUri(generateTokenPath), headers: headers), - )! as Map; - return (id: token.uuid, value: response['token'].toString()); + )! as String; + + return (id: token.uuid, value: tokenValue); } Future deleteToken({ From b4201c50d93a2a76d405e7c56894975d7536069e Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Tue, 20 Feb 2024 11:28:23 +0000 Subject: [PATCH 13/23] make token creation interactive when args not provided --- .../src/commands/token/token_create_command.dart | 15 ++++++++------- packages/globe_cli/lib/src/utils/prompts.dart | 2 +- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/packages/globe_cli/lib/src/commands/token/token_create_command.dart b/packages/globe_cli/lib/src/commands/token/token_create_command.dart index 053b3712..51827bd3 100644 --- a/packages/globe_cli/lib/src/commands/token/token_create_command.dart +++ b/packages/globe_cli/lib/src/commands/token/token_create_command.dart @@ -13,13 +13,11 @@ class TokenCreateCommand extends BaseGlobeCommand { ..addOption( 'name', abbr: 'n', - mandatory: true, help: 'Specify name to identity token.', ) ..addOption( 'expiry', abbr: 'e', - mandatory: true, help: 'Specify lifespan of token.', ) ..addMultiOption( @@ -38,9 +36,13 @@ class TokenCreateCommand extends BaseGlobeCommand { FutureOr run() async { requireAuth(); - final name = argResults?['name'] as String; - final projectIds = argResults?['project'] as List?; - final dateString = argResults?['expiry'] as String; + final validated = await scope.validate(); + + final name = + argResults?['name']?.toString() ?? logger.prompt('❓ Name for token:'); + final dateString = argResults?['expiry']?.toString() ?? + logger.prompt('❓ Expiry (yyyy-mm-dd):'); + final expiry = DateTime.tryParse(dateString); if (expiry == null) { logger.err( @@ -49,13 +51,12 @@ class TokenCreateCommand extends BaseGlobeCommand { exitOverride(1); } - final validated = await scope.validate(); final projects = await selectProjects( validated.organization, logger: logger, api: api, scope: scope, - ids: projectIds, + ids: argResults?['project'] as List?, ); final projectNames = projects.map((e) => cyan.wrap(e.slug)).join(', '); diff --git a/packages/globe_cli/lib/src/utils/prompts.dart b/packages/globe_cli/lib/src/utils/prompts.dart index 4b02cd9d..abb0bb4c 100644 --- a/packages/globe_cli/lib/src/utils/prompts.dart +++ b/packages/globe_cli/lib/src/utils/prompts.dart @@ -361,7 +361,7 @@ Future> selectProjects( /// Ask user to choose zero or more options. final selections = logger.chooseAny( - 'Select projects to associate token with:', + '❓ Select projects to associate token with:', choices: projectsBySlug.keys.toList(), ); From b33a7ae91c78b7bad0f7ae41f1f55cab1a0d32f6 Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Wed, 21 Feb 2024 11:32:49 +0000 Subject: [PATCH 14/23] add command to list globe tokens --- .../commands/token/token_list_command.dart | 55 +++++++++++++++++++ .../lib/src/commands/token_command.dart | 2 + packages/globe_cli/lib/src/utils/api.dart | 19 +++++++ 3 files changed, 76 insertions(+) create mode 100644 packages/globe_cli/lib/src/commands/token/token_list_command.dart diff --git a/packages/globe_cli/lib/src/commands/token/token_list_command.dart b/packages/globe_cli/lib/src/commands/token/token_list_command.dart new file mode 100644 index 00000000..deb710a5 --- /dev/null +++ b/packages/globe_cli/lib/src/commands/token/token_list_command.dart @@ -0,0 +1,55 @@ +import 'dart:async'; + +import 'package:mason_logger/mason_logger.dart'; + +import '../../command.dart'; +import '../../utils/api.dart'; + +class TokenListCommand extends BaseGlobeCommand { + @override + String get description => 'List globe auth tokens for current project'; + + @override + String get name => 'list'; + + @override + FutureOr? run() async { + requireAuth(); + + final validated = await scope.validate(); + final projectName = cyan.wrap(validated.project.slug); + + final listTokenProgress = + logger.progress('Listing Tokens for $projectName'); + + try { + final tokens = await api.listTokens( + orgId: validated.organization.id, + projectUuids: [validated.project.id], + ); + if (tokens.isEmpty) { + listTokenProgress.fail('No Tokens found for $projectName'); + return ExitCode.success.code; + } + + String tokenLog(Token token) => ''' +---------------------------------- + ID: ${cyan.wrap(token.uuid)} + Name: ${token.name} + Expiry: ${token.expiresAt.toLocal()}'''; + + listTokenProgress.complete( + 'Tokens for $projectName\n${tokens.map(tokenLog).join('\n')}', + ); + + return ExitCode.success.code; + } on ApiException catch (e) { + listTokenProgress.fail('✗ Failed to create token: ${e.message}'); + return ExitCode.software.code; + } catch (e, s) { + listTokenProgress.fail('✗ Failed to create token: $e'); + logger.detail(s.toString()); + return ExitCode.software.code; + } + } +} diff --git a/packages/globe_cli/lib/src/commands/token_command.dart b/packages/globe_cli/lib/src/commands/token_command.dart index 00bd47f5..0d164731 100644 --- a/packages/globe_cli/lib/src/commands/token_command.dart +++ b/packages/globe_cli/lib/src/commands/token_command.dart @@ -1,11 +1,13 @@ import '../command.dart'; import 'token/token_create_command.dart'; import 'token/token_delete_command.dart'; +import 'token/token_list_command.dart'; class TokenCommand extends BaseGlobeCommand { TokenCommand() { addSubcommand(TokenCreateCommand()); addSubcommand(TokenDeleteCommand()); + addSubcommand(TokenListCommand()); } @override String get description => 'Manage globe auth tokens.'; diff --git a/packages/globe_cli/lib/src/utils/api.dart b/packages/globe_cli/lib/src/utils/api.dart index a9bdc8f0..8e0dd87c 100644 --- a/packages/globe_cli/lib/src/utils/api.dart +++ b/packages/globe_cli/lib/src/utils/api.dart @@ -254,6 +254,25 @@ class GlobeApi { return (id: token.uuid, value: tokenValue); } + Future> listTokens({ + required String orgId, + required List projectUuids, + }) async { + requireAuth(); + + final listTokensPath = + '/orgs/$orgId/api-tokens?projects=${projectUuids.join(',')}'; + logger.detail('API Request: GET $listTokensPath'); + + final response = _handleResponse( + await http.get(_buildUri(listTokensPath), headers: headers), + )! as List; + + return response + .map((e) => Token.fromJson(e as Map)) + .toList(); + } + Future deleteToken({ required String orgId, required String tokenId, From 5ccb88c48072597cffe3a930c27a00a138273861 Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Wed, 21 Feb 2024 15:36:28 +0000 Subject: [PATCH 15/23] wip --- .../lib/src/commands/token/token_create_command.dart | 6 +++--- .../lib/src/commands/token/token_delete_command.dart | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/globe_cli/lib/src/commands/token/token_create_command.dart b/packages/globe_cli/lib/src/commands/token/token_create_command.dart index 51827bd3..1ad8bf0c 100644 --- a/packages/globe_cli/lib/src/commands/token/token_create_command.dart +++ b/packages/globe_cli/lib/src/commands/token/token_create_command.dart @@ -38,10 +38,10 @@ class TokenCreateCommand extends BaseGlobeCommand { final validated = await scope.validate(); - final name = - argResults?['name']?.toString() ?? logger.prompt('❓ Name for token:'); + final name = argResults?['name']?.toString() ?? + logger.prompt('❓ Provide name for token:'); final dateString = argResults?['expiry']?.toString() ?? - logger.prompt('❓ Expiry (yyyy-mm-dd):'); + logger.prompt('❓ Set Expiry (yyyy-mm-dd):'); final expiry = DateTime.tryParse(dateString); if (expiry == null) { diff --git a/packages/globe_cli/lib/src/commands/token/token_delete_command.dart b/packages/globe_cli/lib/src/commands/token/token_delete_command.dart index f4614ba9..76045536 100644 --- a/packages/globe_cli/lib/src/commands/token/token_delete_command.dart +++ b/packages/globe_cli/lib/src/commands/token/token_delete_command.dart @@ -9,8 +9,8 @@ class TokenDeleteCommand extends BaseGlobeCommand { TokenDeleteCommand() { argParser.addOption( 'tokenId', - mandatory: true, - help: 'Specify globe auth token to delete.', + abbr: 't', + help: 'Specify globe auth token id.', ); } @override @@ -23,7 +23,8 @@ class TokenDeleteCommand extends BaseGlobeCommand { FutureOr run() async { requireAuth(); - final tokenId = argResults?['tokenId'] as String; + final tokenId = (argResults?['tokenId'] as String?) ?? + logger.prompt('❓ Provide id for token:'); final validated = await scope.validate(); final deleteTokenProgress = From b0582b5387b146ddf2434b86322db8663b89d2cb Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Wed, 21 Feb 2024 15:39:33 +0000 Subject: [PATCH 16/23] wip --- .../globe_cli/lib/src/commands/token/token_list_command.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/globe_cli/lib/src/commands/token/token_list_command.dart b/packages/globe_cli/lib/src/commands/token/token_list_command.dart index deb710a5..39051d6f 100644 --- a/packages/globe_cli/lib/src/commands/token/token_list_command.dart +++ b/packages/globe_cli/lib/src/commands/token/token_list_command.dart @@ -44,10 +44,10 @@ class TokenListCommand extends BaseGlobeCommand { return ExitCode.success.code; } on ApiException catch (e) { - listTokenProgress.fail('✗ Failed to create token: ${e.message}'); + listTokenProgress.fail('✗ Failed to list tokens: ${e.message}'); return ExitCode.software.code; } catch (e, s) { - listTokenProgress.fail('✗ Failed to create token: $e'); + listTokenProgress.fail('✗ Failed to list tokens: $e'); logger.detail(s.toString()); return ExitCode.software.code; } From 5f155297ae5f16b2fedb2c4d6438205cca866906 Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Wed, 21 Feb 2024 16:06:07 +0000 Subject: [PATCH 17/23] update docs --- docs/cli/commands/token.mdx | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 docs/cli/commands/token.mdx diff --git a/docs/cli/commands/token.mdx b/docs/cli/commands/token.mdx new file mode 100644 index 00000000..def0e5ff --- /dev/null +++ b/docs/cli/commands/token.mdx @@ -0,0 +1,27 @@ +--- +title: Globe Tokens +description: Create, Delete & List globe auth tokens from the command line. +--- + +# Create + +The `create` command allows you to create auth tokens for your projects. You can use this token to +login to Globe in any environment. + +## Usage + +You can run the command interactively by running + +```bash +globe token create +``` + +or in-lined by providing necessary arguments + +```bash +globe token create --name="Foo Bar" --expiry="yyyy-mm-dd" --project="project-ids-go-here" +``` + +- `--name`- specify name to identity token. +- `--expiry` - specify lifespan of token. +- `--project` - specify projects(s) to associate token with. From 7191093411b98a68ec637af3d9b2b000b120ad5a Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Wed, 21 Feb 2024 16:08:37 +0000 Subject: [PATCH 18/23] wip --- docs/cli/commands/token.mdx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/cli/commands/token.mdx b/docs/cli/commands/token.mdx index def0e5ff..24f42d27 100644 --- a/docs/cli/commands/token.mdx +++ b/docs/cli/commands/token.mdx @@ -18,10 +18,12 @@ globe token create or in-lined by providing necessary arguments +- `--name`- specify name to identity token. +- `--expiry` - specify lifespan of token. +- `--project` - specify projects(s) to associate token with. + ```bash globe token create --name="Foo Bar" --expiry="yyyy-mm-dd" --project="project-ids-go-here" ``` -- `--name`- specify name to identity token. -- `--expiry` - specify lifespan of token. -- `--project` - specify projects(s) to associate token with. + From 188f34b736de4bc12309cbf9f7a2f67f8edc6778 Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Wed, 21 Feb 2024 16:26:59 +0000 Subject: [PATCH 19/23] wip --- docs/cli/commands/token.mdx | 18 ++++++++++++++++++ .../commands/token/token_delete_command.dart | 2 +- 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/docs/cli/commands/token.mdx b/docs/cli/commands/token.mdx index 24f42d27..8fb52181 100644 --- a/docs/cli/commands/token.mdx +++ b/docs/cli/commands/token.mdx @@ -26,4 +26,22 @@ or in-lined by providing necessary arguments globe token create --name="Foo Bar" --expiry="yyyy-mm-dd" --project="project-ids-go-here" ``` +# List Tokens +The `list` command lists all tokens associated with the current project. + +## Usage + +```bash +globe token list +``` + +# Delete Token + +The `delete` command allows you to delete token by providing token ID. + +## Usage + +```bash +globe token delete +``` \ No newline at end of file diff --git a/packages/globe_cli/lib/src/commands/token/token_delete_command.dart b/packages/globe_cli/lib/src/commands/token/token_delete_command.dart index 76045536..425e6e8d 100644 --- a/packages/globe_cli/lib/src/commands/token/token_delete_command.dart +++ b/packages/globe_cli/lib/src/commands/token/token_delete_command.dart @@ -23,9 +23,9 @@ class TokenDeleteCommand extends BaseGlobeCommand { FutureOr run() async { requireAuth(); + final validated = await scope.validate(); final tokenId = (argResults?['tokenId'] as String?) ?? logger.prompt('❓ Provide id for token:'); - final validated = await scope.validate(); final deleteTokenProgress = logger.progress('Deleting Token: ${cyan.wrap(tokenId)}'); From 5c7d37c903f7e7dbf8ae7b704060c113cdf7b4c4 Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Wed, 21 Feb 2024 19:58:40 +0000 Subject: [PATCH 20/23] Update docs/cli/commands/token.mdx Co-authored-by: Nabeel Parkar --- docs/cli/commands/token.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cli/commands/token.mdx b/docs/cli/commands/token.mdx index 8fb52181..bf160cfd 100644 --- a/docs/cli/commands/token.mdx +++ b/docs/cli/commands/token.mdx @@ -20,7 +20,7 @@ or in-lined by providing necessary arguments - `--name`- specify name to identity token. - `--expiry` - specify lifespan of token. -- `--project` - specify projects(s) to associate token with. +- `--project` - specify projects(s) to associate the token with. ```bash globe token create --name="Foo Bar" --expiry="yyyy-mm-dd" --project="project-ids-go-here" From 592a39bd5fc5ba23a655a9180c59d67970d64863 Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Wed, 21 Feb 2024 19:58:52 +0000 Subject: [PATCH 21/23] Update docs/cli/commands/token.mdx Co-authored-by: Nabeel Parkar --- docs/cli/commands/token.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cli/commands/token.mdx b/docs/cli/commands/token.mdx index bf160cfd..2c398072 100644 --- a/docs/cli/commands/token.mdx +++ b/docs/cli/commands/token.mdx @@ -19,7 +19,7 @@ globe token create or in-lined by providing necessary arguments - `--name`- specify name to identity token. -- `--expiry` - specify lifespan of token. +- `--expiry` - specify lifespan of the token. - `--project` - specify projects(s) to associate the token with. ```bash From db7b6dda648f69decac083487b4a32e89c4f805e Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Wed, 21 Feb 2024 19:59:02 +0000 Subject: [PATCH 22/23] Update docs/cli/commands/token.mdx Co-authored-by: Nabeel Parkar --- docs/cli/commands/token.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cli/commands/token.mdx b/docs/cli/commands/token.mdx index 2c398072..d22d7667 100644 --- a/docs/cli/commands/token.mdx +++ b/docs/cli/commands/token.mdx @@ -18,7 +18,7 @@ globe token create or in-lined by providing necessary arguments -- `--name`- specify name to identity token. +- `--name`- specify name to identity the token. - `--expiry` - specify lifespan of the token. - `--project` - specify projects(s) to associate the token with. From 61e5d29e3741e022f2246cf1065eb2980dda9b88 Mon Sep 17 00:00:00 2001 From: Chima Precious Date: Wed, 21 Feb 2024 20:01:38 +0000 Subject: [PATCH 23/23] wip --- docs/cli/commands/token.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/cli/commands/token.mdx b/docs/cli/commands/token.mdx index d22d7667..f349dfa3 100644 --- a/docs/cli/commands/token.mdx +++ b/docs/cli/commands/token.mdx @@ -43,5 +43,5 @@ The `delete` command allows you to delete token by providing token ID. ## Usage ```bash -globe token delete +globe token delete --tokenId="token-id-goes-here" ``` \ No newline at end of file