Skip to content

Commit

Permalink
chore: Make --token applicable to all other commands (#105)
Browse files Browse the repository at this point in the history
* make token applicable to all other commands

* fixes

* _

* fix broken token listing
  • Loading branch information
codekeyz authored Oct 3, 2024
1 parent 361bf34 commit a02bdd2
Show file tree
Hide file tree
Showing 7 changed files with 83 additions and 57 deletions.
14 changes: 0 additions & 14 deletions packages/globe_cli/lib/src/command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,20 +46,6 @@ abstract class BaseGlobeCommand extends Command<int> {
}

ScopeValidator declareScopeArguments() {
argParser
..addOption(
'org',
abbr: 'o',
help: 'The organization ID used by this command. '
'Defaults to what was previously linked using `globe link`.',
)
..addOption(
'project',
abbr: 'p',
help: 'The Project ID used by this command. '
'Defaults to what was previously linked using `globe link`.',
);

return () => scope.validate(argResults);
}
}
66 changes: 66 additions & 0 deletions packages/globe_cli/lib/src/command_runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import 'utils/api.dart';
import 'utils/auth.dart';
import 'utils/http_server.dart';
import 'utils/metadata.dart';
import 'utils/prompts.dart';
import 'utils/scope.dart';

class GlobeCliCommandRunner extends CompletionCommandRunner<int> {
Expand All @@ -41,6 +42,23 @@ class GlobeCliCommandRunner extends CompletionCommandRunner<int> {
'api',
help: 'Switches the CLI to use a different running API.',
hide: true,
)
..addOption(
'token',
abbr: 't',
help: 'Set the API token for cli.',
)
..addOption(
'project',
abbr: 'p',
help: 'Set the Project ID used by this command. '
'Defaults to what was previously linked using `globe link`.',
)
..addOption(
'org',
abbr: 'o',
help: 'Set the Organization ID used by this command. '
'Defaults to what was previously linked using `globe link`.',
);

// Register singleton utils.
Expand All @@ -67,6 +85,7 @@ class GlobeCliCommandRunner extends CompletionCommandRunner<int> {
@override
Future<int> run(Iterable<String> args) async {
final GlobeMetadata metadata;

try {
final topLevelResults = parse(args);
if (topLevelResults['verbose'] == true) {
Expand Down Expand Up @@ -109,10 +128,54 @@ class GlobeCliCommandRunner extends CompletionCommandRunner<int> {
GetIt.instance.registerSingleton<GlobeMetadata>(metadata);
GetIt.instance.registerSingleton<GlobeScope>(scope);

final maybeToken = topLevelResults['token'];
final maybeProjectId = topLevelResults['project'];
final maybeOrgId = topLevelResults['org'];

Organization? org;
Project? project;

if (maybeToken != null) {
api.auth.loginWithApiToken(jwt: maybeToken as String);
org = await selectOrganization(
logger: _logger,
api: api,
onNoOrganizationsError: () => _logger.err(
'API Token provided is invalid or is not associated with any organizations.',
),
);
}

// Load the current project scope.
scope.loadScope();
auth.loadSession();

final currentSession = auth.currentSession;

if (maybeOrgId != null) {
if (currentSession == null) throw Exception('Auth required.');
final orgs = await api.getOrganizations();
org = orgs.firstWhere(
(org) => org.id == maybeOrgId,
orElse: () => throw Exception('Project #$maybeProjectId not found.'),
);
}

if (maybeProjectId != null) {
if (currentSession == null) throw Exception('Auth required.');
if (org == null) throw Exception('Organization not found.');

final projects = await api.getProjects(org: org.id);
project = projects.firstWhere(
(project) => project.id == maybeProjectId,
orElse: () => throw Exception('Project #$maybeProjectId not found.'),
);
}

if (org != null && project != null) {
scope.setScope(orgId: org.id, projectId: project.id);
}

return await runCommand(topLevelResults) ?? ExitCode.success.code;
// TODO(rrousselGit) why are we checking FormatExceptions here?
} on FormatException catch (e, stackTrace) {
Expand All @@ -132,6 +195,9 @@ class GlobeCliCommandRunner extends CompletionCommandRunner<int> {
..info('')
..info(e.usage);
return ExitCode.usage.code;
} on Exception catch (e) {
_logger.err(e.toString());
return ExitCode.software.code;
}
}

Expand Down
25 changes: 0 additions & 25 deletions packages/globe_cli/lib/src/commands/deploy_command.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,6 @@ class DeployCommand extends BaseGlobeCommand {
..addFlag(
'logs',
help: 'Shows build logs for the deployment.',
)
..addOption(
'token',
abbr: 't',
help: 'Set the API token for deployment. Also needs --project',
);

_validator = declareScopeArguments();
Expand All @@ -50,26 +45,6 @@ class DeployCommand extends BaseGlobeCommand {

@override
Future<int> run() async {
if (argResults?['token'] != null && argResults?['project'] != null) {
final token = argResults!['token'] as String;
final project = argResults!['project'] as String;
api.auth.loginWithApiToken(jwt: token);

final organizations = await api.getOrganizations();
logger.detail('Found ${organizations.length} organizations');

if (organizations.isEmpty) {
logger.err(
'API Token provided is invalid or is not associated with any organizations.',
);
return ExitCode.usage.code;
}

scope.setScope(orgId: organizations.first.id, projectId: project);
} else {
requireAuth();
}

// If there is no scope, ask the user to link the project.
if (!scope.hasScope()) {
await linkProject(logger: logger, api: api);
Expand Down
2 changes: 1 addition & 1 deletion packages/globe_cli/lib/src/package_info.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// GENERATED CODE. DO NOT EDIT BY HAND.

const name = 'globe_cli';
const name = 'globe';
const version = '0.0.12';
const description = 'Globe CLI';
const executable = 'globe';
3 changes: 1 addition & 2 deletions packages/globe_cli/lib/src/utils/api.dart
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,6 @@ class Token {
'organizationUuid': final String organizationUuid,
'expiresAt': final String expiresAt,
'projects': final List<dynamic> projects,
'value': final String? value,
} =>
Token._(
uuid: uuid,
Expand All @@ -705,7 +704,7 @@ class Token {
cliTokenClaimProject: projects
.map((e) => (e as Map)['projectUuid'].toString())
.toList(),
value: value,
value: json['value']?.toString(),
),
_ => throw const FormatException('Token'),
};
Expand Down
13 changes: 9 additions & 4 deletions packages/globe_cli/lib/src/utils/prompts.dart
Original file line number Diff line number Diff line change
Expand Up @@ -82,16 +82,21 @@ Future<ScopeMetadata> linkProject({
Future<Organization> selectOrganization({
required Logger logger,
required GlobeApi api,
void Function()? onNoOrganizationsError,
}) async {
logger.detail('Fetching user organizations');
final organizations = await api.getOrganizations();
logger.detail('Found ${organizations.length} organizations');

if (organizations.isEmpty) {
logger.detail(
'No organizations found, this is likely a new account which is still being setup. Please try again in a few seconds.',
);
logger.err('Your account is still being setup, please try again.');
if (onNoOrganizationsError == null) {
logger.detail(
'No organizations found, this is likely a new account which is still being setup. Please try again in a few seconds.',
);
logger.err('Your account is still being setup, please try again.');
} else {
onNoOrganizationsError.call();
}
exitOverride(1);
}

Expand Down
17 changes: 6 additions & 11 deletions packages/globe_cli/lib/src/utils/scope.dart
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,8 @@ class GlobeScope {
return current != null;
}

Future<Organization> _findOrg(ArgResults? argResults) async {
final orgId = argResults?['org'] ?? current?.orgId;

Future<Organization> _findOrg() async {
final orgId = current?.orgId;
if (orgId is! String) return selectOrganization(logger: logger, api: api);

final organizations = await api.getOrganizations();
Expand All @@ -70,12 +69,8 @@ class GlobeScope {
);
}

Future<Project> _findProject(
ArgResults? argResults,
Organization org,
) async {
final projectId = argResults?['project'] ?? current?.projectId;

Future<Project> _findProject(Organization org) async {
final projectId = current?.projectId;
if (projectId is! String) {
return selectProject(org, logger: logger, api: api);
}
Expand All @@ -92,8 +87,8 @@ class GlobeScope {

Future<ScopeValidation> validate(ArgResults? argResults) async {
try {
final organization = await _findOrg(argResults);
final project = await _findProject(argResults, organization);
final organization = await _findOrg();
final project = await _findProject(organization);

logger.detail('Validated scope: ${organization.slug}/${project.slug}');

Expand Down

0 comments on commit a02bdd2

Please sign in to comment.