Login command (#2479)
diff --git a/lib/src/command/login.dart b/lib/src/command/login.dart
new file mode 100644
index 0000000..5af099a
--- /dev/null
+++ b/lib/src/command/login.dart
@@ -0,0 +1,64 @@
+// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:convert';
+
+import '../command.dart';
+import '../http.dart';
+import '../log.dart' as log;
+import '../oauth2.dart' as oauth2;
+
+/// Handles the `login` pub command.
+class LoginCommand extends PubCommand {
+ @override
+ String get name => 'login';
+ @override
+ String get description => 'Log into pub.dev.';
+ @override
+ String get invocation => 'pub login';
+
+ LoginCommand();
+
+ @override
+ Future<void> runProtected() async {
+ final credentials = oauth2.loadCredentials(cache);
+ if (credentials == null) {
+ final userInfo = await retrieveUserInfo();
+ log.message('You are now logged in as $userInfo');
+ } else {
+ final userInfo = await retrieveUserInfo();
+ if (userInfo == null) {
+ log.warning('Your credentials seems broken.\n'
+ 'Run `pub logout` to delete your credentials and try again.');
+ }
+ log.warning('You are already logged in as $userInfo\n'
+ 'Run `pub logout` to log out and try again.');
+ }
+ }
+
+ Future<_UserInfo> retrieveUserInfo() async {
+ return await oauth2.withClient(cache, (client) async {
+ final discovery = await httpClient
+ .get('https://accounts.google.com/.well-known/openid-configuration');
+ final userInfoEndpoint = json.decode(discovery.body)['userinfo_endpoint'];
+ final userInfoRequest = await client.get(userInfoEndpoint);
+ if (userInfoRequest.statusCode != 200) return null;
+ try {
+ final userInfo = json.decode(userInfoRequest.body);
+ return _UserInfo(userInfo['name'], userInfo['email']);
+ } on FormatException {
+ return null;
+ }
+ });
+ }
+}
+
+class _UserInfo {
+ final String name;
+ final String email;
+ _UserInfo(this.name, this.email);
+ @override
+ String toString() => '<$email> "$name"';
+}
diff --git a/lib/src/command/logout.dart b/lib/src/command/logout.dart
index ea5b340..04ffe12 100644
--- a/lib/src/command/logout.dart
+++ b/lib/src/command/logout.dart
@@ -12,7 +12,7 @@
@override
String get name => 'logout';
@override
- String get description => 'Log out of pub.dartlang.org.';
+ String get description => 'Log out of pub.dev.';
@override
bool get takesArguments => false;
diff --git a/lib/src/command_runner.dart b/lib/src/command_runner.dart
index 532cb0e..f36d5b4 100644
--- a/lib/src/command_runner.dart
+++ b/lib/src/command_runner.dart
@@ -19,6 +19,7 @@
import 'command/global.dart';
import 'command/lish.dart';
import 'command/list_package_dirs.dart';
+import 'command/login.dart';
import 'command/logout.dart';
import 'command/outdated.dart';
import 'command/remove.dart';
@@ -119,6 +120,7 @@
addCommand(ServeCommand());
addCommand(UpgradeCommand());
addCommand(UploaderCommand());
+ addCommand(LoginCommand());
addCommand(LogoutCommand());
addCommand(VersionCommand());
}
diff --git a/lib/src/oauth2.dart b/lib/src/oauth2.dart
index 6095640..fe0cef1 100644
--- a/lib/src/oauth2.dart
+++ b/lib/src/oauth2.dart
@@ -121,7 +121,7 @@
/// If saved credentials are available, those are used; otherwise, the user is
/// prompted to authorize the pub client.
Future<Client> _getClient(SystemCache cache) async {
- var credentials = _loadCredentials(cache);
+ var credentials = loadCredentials(cache);
if (credentials == null) return await _authorize();
var client = Client(credentials,
@@ -139,7 +139,7 @@
///
/// If the credentials can't be loaded for any reason, the returned [Future]
/// completes to `null`.
-Credentials _loadCredentials(SystemCache cache) {
+Credentials loadCredentials(SystemCache cache) {
log.fine('Loading OAuth2 credentials.');
try {
@@ -200,7 +200,6 @@
log.message('Authorization received, processing...');
var queryString = request.url.query ?? '';
-
// Closing the server here is safe, since it will wait until the response
// is sent to actually shut down.
server.close();
diff --git a/lib/src/pub_embeddable_command.dart b/lib/src/pub_embeddable_command.dart
index b774e4a..2bc6133 100644
--- a/lib/src/pub_embeddable_command.dart
+++ b/lib/src/pub_embeddable_command.dart
@@ -12,6 +12,7 @@
import 'command/get.dart';
import 'command/global.dart';
import 'command/lish.dart';
+import 'command/login.dart';
import 'command/logout.dart';
import 'command/outdated.dart';
import 'command/remove.dart';
@@ -56,6 +57,7 @@
addSubcommand(RunCommand(deprecated: true));
addSubcommand(UpgradeCommand());
addSubcommand(UploaderCommand());
+ addSubcommand(LoginCommand());
addSubcommand(LogoutCommand());
}
diff --git a/lib/src/utils.dart b/lib/src/utils.dart
index 1713f9c..347f68e 100644
--- a/lib/src/utils.dart
+++ b/lib/src/utils.dart
@@ -127,7 +127,7 @@
if (!completer.isCompleted) completer.completeError(error, stackTrace);
});
} else {
- runZoned(wrappedCallback, onError: (e, stackTrace) {
+ runZonedGuarded(wrappedCallback, (e, stackTrace) {
if (stackTrace == null) {
stackTrace = Chain.current();
} else {
diff --git a/test/embedding/goldens/helptext.txt b/test/embedding/goldens/helptext.txt
index 227d857..864e30f 100644
--- a/test/embedding/goldens/helptext.txt
+++ b/test/embedding/goldens/helptext.txt
@@ -39,7 +39,8 @@
[E] downgrade Downgrade the current package's dependencies to oldest versions.
[E] get Get the current package's dependencies.
[E] global Work with global packages.
-[E] logout Log out of pub.dartlang.org.
+[E] login Log into pub.dev.
+[E] logout Log out of pub.dev.
[E] outdated Analyze your dependencies to find which ones can be upgraded.
[E] publish Publish the current package to pub.dartlang.org.
[E] remove Removes a dependency from the current package.
@@ -64,7 +65,8 @@
downgrade Downgrade the current package's dependencies to oldest versions.
get Get the current package's dependencies.
global Work with global packages.
- logout Log out of pub.dartlang.org.
+ login Log into pub.dev.
+ logout Log out of pub.dev.
outdated Analyze your dependencies to find which ones can be upgraded.
publish Publish the current package to pub.dartlang.org.
remove Removes a dependency from the current package.
diff --git a/test/pub_test.dart b/test/pub_test.dart
index 3e52f94..167a260 100644
--- a/test/pub_test.dart
+++ b/test/pub_test.dart
@@ -35,7 +35,8 @@
downgrade Downgrade the current package's dependencies to oldest versions.
get Get the current package's dependencies.
global Work with global packages.
- logout Log out of pub.dartlang.org.
+ login Log into pub.dev.
+ logout Log out of pub.dev.
outdated Analyze your dependencies to find which ones can be upgraded.
publish Publish the current package to pub.dartlang.org.
remove Removes a dependency from the current package.