Skip to content

Commit cea928c

Browse files
authored
feat(cli): Add --token parameter to auth login (#346)
Allow logging into the CLI with a token for non-interactive environments. Also adds a `auth whoami` command for getting the current user info.
1 parent a39cb38 commit cea928c

File tree

4 files changed

+72
-1
lines changed

4 files changed

+72
-1
lines changed

apps/cli/lib/src/commands/auth/auth_command.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
import 'package:celest_cli/src/commands/auth/login_command.dart';
22
import 'package:celest_cli/src/commands/auth/logout_command.dart';
33
import 'package:celest_cli/src/commands/auth/token_command.dart';
4+
import 'package:celest_cli/src/commands/auth/whoami_command.dart';
45
import 'package:celest_cli/src/commands/celest_command.dart';
56

67
final class AuthCommand extends CelestCommand {
78
AuthCommand() {
89
addSubcommand(LoginCommand());
910
addSubcommand(LogoutCommand());
1011
addSubcommand(TokenCommand());
12+
addSubcommand(WhoamiCommand());
1113
}
1214

1315
@override

apps/cli/lib/src/commands/auth/login_command.dart

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,60 @@
1+
import 'package:cedar/cedar.dart';
12
import 'package:celest_auth/celest_auth.dart';
23
import 'package:celest_cli/src/commands/auth/authenticate.dart';
34
import 'package:celest_cli/src/commands/auth/cli_auth.dart';
45
import 'package:celest_cli/src/commands/celest_command.dart';
56
import 'package:celest_cli/src/context.dart';
7+
import 'package:celest_cli/src/exceptions.dart';
8+
import 'package:corks_cedar/corks_cedar.dart';
69

710
final class LoginCommand extends CelestCommand with Authenticate {
11+
LoginCommand() {
12+
argParser.addOption(
13+
'token',
14+
help: 'Use a token to authenticate instead of the interactive CLI flow.',
15+
);
16+
}
17+
818
@override
919
String get name => 'login';
1020

1121
@override
1222
String get description => 'Login to Celest Cloud.';
1323

24+
String? get token => argResults?['token'] as String?;
25+
26+
Future<int> _loginWithToken(String token) async {
27+
final cork = CedarCork.parse(token);
28+
final userId = switch (cork.claims) {
29+
Entity(parents: [EntityUid(type: 'Celest::User', :final id)]) => id,
30+
_ => throw CliException('Invalid token passed with --token flag.'),
31+
};
32+
auth.localStorage.write('userId', userId);
33+
await auth.secureStorage.write('cork', token);
34+
35+
final authState = await auth.init();
36+
logger.finest('Auth state: $authState');
37+
if (authState case Authenticated(:final user)) {
38+
cliLogger.success(
39+
'You have been logged in as: ${user.primaryEmail?.email}',
40+
);
41+
return 0;
42+
}
43+
44+
// Failed to authenticate with the token.
45+
auth.localStorage.delete('userId');
46+
await auth.secureStorage.delete('cork');
47+
throw CliException('Failed to authenticate with token.');
48+
}
49+
1450
@override
1551
Future<int> run() async {
1652
await super.run();
1753

54+
if (token case final token?) {
55+
return _loginWithToken(token);
56+
}
57+
1858
final authState = await auth.init();
1959
logger.finest('Auth state: $authState');
2060
switch (authState) {
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import 'dart:convert';
2+
import 'dart:io';
3+
4+
import 'package:celest_cli/src/commands/auth/authenticate.dart';
5+
import 'package:celest_cli/src/commands/celest_command.dart';
6+
7+
final class WhoamiCommand extends CelestCommand with Authenticate {
8+
@override
9+
String get name => 'whoami';
10+
11+
@override
12+
String get description => 'Print the current authenticated user\'s info.';
13+
14+
@override
15+
Future<int> run() async {
16+
await super.run();
17+
18+
final user = await assertAuthenticated();
19+
if (jsonOutput) {
20+
stdout.write(jsonEncode(user.toJson()));
21+
} else {
22+
stdout.writeln(user.toString());
23+
}
24+
25+
return 0;
26+
}
27+
}

apps/cli/lib/src/commands/celest_command.dart

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import 'dart:io';
44

55
import 'package:args/command_runner.dart';
66
import 'package:celest_cli/src/cli/cli_runtime.dart';
7+
import 'package:celest_cli/src/commands/auth/auth_command.dart';
78
import 'package:celest_cli/src/context.dart';
89
import 'package:celest_cli/src/models.dart';
910
import 'package:celest_cli/src/releases/celest_release_info.dart';
@@ -124,7 +125,8 @@ abstract base class CelestCommand extends Command<int> {
124125
'cli',
125126
properties: {
126127
'command': name,
127-
'args': argResults!.arguments.join(' '),
128+
// Don't record args for auth commands, which may contain tokens.
129+
if (parent is! AuthCommand) 'args': argResults!.arguments.join(' '),
128130
'environment': kCliEnvironment,
129131
'version': version,
130132
'sdk_version': Sdk.current.version.toString(),

0 commit comments

Comments
 (0)