Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: sdk/lib/_internal/pub_generated/lib/src/oauth2.dart

Issue 557563002: Store the async-await compiled pub code directly in the repo. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 library pub.oauth2; 1 library pub.oauth2;
6
7 import 'dart:async'; 2 import 'dart:async';
8 import 'dart:io'; 3 import 'dart:io';
9
10 import 'package:oauth2/oauth2.dart'; 4 import 'package:oauth2/oauth2.dart';
11 import 'package:path/path.dart' as path; 5 import 'package:path/path.dart' as path;
12 import 'package:shelf/shelf.dart' as shelf; 6 import 'package:shelf/shelf.dart' as shelf;
13 import 'package:shelf/shelf_io.dart' as shelf_io; 7 import 'package:shelf/shelf_io.dart' as shelf_io;
14
15 import 'http.dart'; 8 import 'http.dart';
16 import 'io.dart'; 9 import 'io.dart';
17 import 'log.dart' as log; 10 import 'log.dart' as log;
18 import 'system_cache.dart'; 11 import 'system_cache.dart';
19 import 'utils.dart'; 12 import 'utils.dart';
20
21 export 'package:oauth2/oauth2.dart'; 13 export 'package:oauth2/oauth2.dart';
22 14 final _identifier =
23 /// The pub client's OAuth2 identifier. 15 '818368855108-8grd2eg9tj9f38os6f1urbcvsq399u8n.apps.' 'googleusercontent.com ';
24 final _identifier = '818368855108-8grd2eg9tj9f38os6f1urbcvsq399u8n.apps.'
25 'googleusercontent.com';
26
27 /// The pub client's OAuth2 secret.
28 ///
29 /// This isn't actually meant to be kept a secret.
30 final _secret = 'SWeqj8seoJW0w7_CpEPFLX0K'; 16 final _secret = 'SWeqj8seoJW0w7_CpEPFLX0K';
31
32 /// The URL to which the user will be directed to authorize the pub client to
33 /// get an OAuth2 access token.
34 ///
35 /// `access_type=offline` and `approval_prompt=force` ensures that we always get
36 /// a refresh token from the server. See the [Google OAuth2 documentation][].
37 ///
38 /// [Google OAuth2 documentation]: https://developers.google.com/accounts/docs/O Auth2WebServer#offline
39 final authorizationEndpoint = Uri.parse( 17 final authorizationEndpoint = Uri.parse(
40 'https://accounts.google.com/o/oauth2/auth?access_type=offline' 18 'https://accounts.google.com/o/oauth2/auth?access_type=offline'
41 '&approval_prompt=force'); 19 '&approval_prompt=force');
42
43 /// The URL from which the pub client will request an access token once it's
44 /// been authorized by the user.
45 ///
46 /// This can be controlled externally by setting the `_PUB_TEST_TOKEN_ENDPOINT`
47 /// environment variable.
48 Uri get tokenEndpoint { 20 Uri get tokenEndpoint {
49 var tokenEndpoint = Platform.environment['_PUB_TEST_TOKEN_ENDPOINT']; 21 var tokenEndpoint = Platform.environment['_PUB_TEST_TOKEN_ENDPOINT'];
50 if (tokenEndpoint != null) { 22 if (tokenEndpoint != null) {
51 return Uri.parse(tokenEndpoint); 23 return Uri.parse(tokenEndpoint);
52 } else { 24 } else {
53 return _tokenEndpoint; 25 return _tokenEndpoint;
54 } 26 }
55 } 27 }
56
57 final _tokenEndpoint = Uri.parse('https://accounts.google.com/o/oauth2/token'); 28 final _tokenEndpoint = Uri.parse('https://accounts.google.com/o/oauth2/token');
58
59 /// The OAuth2 scopes that the pub client needs.
60 ///
61 /// Currently the client only needs the user's email so that the server can
62 /// verify their identity.
63 final _scopes = ['https://www.googleapis.com/auth/userinfo.email']; 29 final _scopes = ['https://www.googleapis.com/auth/userinfo.email'];
64
65 /// An in-memory cache of the user's OAuth2 credentials.
66 ///
67 /// This should always be the same as the credentials file stored in the system
68 /// cache.
69 Credentials _credentials; 30 Credentials _credentials;
70
71 /// Delete the cached credentials, if they exist.
72 void clearCredentials(SystemCache cache) { 31 void clearCredentials(SystemCache cache) {
73 _credentials = null; 32 _credentials = null;
74 var credentialsFile = _credentialsFile(cache); 33 var credentialsFile = _credentialsFile(cache);
75 if (entryExists(credentialsFile)) deleteEntry(credentialsFile); 34 if (entryExists(credentialsFile)) deleteEntry(credentialsFile);
76 } 35 }
77
78 /// Asynchronously passes an OAuth2 [Client] to [fn], and closes the client when
79 /// the [Future] returned by [fn] completes.
80 ///
81 /// This takes care of loading and saving the client's credentials, as well as
82 /// prompting the user for their authorization. It will also re-authorize and
83 /// re-run [fn] if a recoverable authorization error is detected.
84 Future withClient(SystemCache cache, Future fn(Client client)) { 36 Future withClient(SystemCache cache, Future fn(Client client)) {
85 return _getClient(cache).then((client) { 37 return _getClient(cache).then((client) {
86 var completer = new Completer(); 38 var completer = new Completer();
87 return fn(client).whenComplete(() { 39 return fn(client).whenComplete(() {
88 client.close(); 40 client.close();
89 // Be sure to save the credentials even when an error happens.
90 _saveCredentials(cache, client.credentials); 41 _saveCredentials(cache, client.credentials);
91 }); 42 });
92 }).catchError((error) { 43 }).catchError((error) {
93 if (error is ExpirationException) { 44 if (error is ExpirationException) {
94 log.error("Pub's authorization to upload packages has expired and " 45 log.error(
95 "can't be automatically refreshed."); 46 "Pub's authorization to upload packages has expired and "
47 "can't be automatically refreshed.");
96 return withClient(cache, fn); 48 return withClient(cache, fn);
97 } else if (error is AuthorizationException) { 49 } else if (error is AuthorizationException) {
98 var message = "OAuth2 authorization failed"; 50 var message = "OAuth2 authorization failed";
99 if (error.description != null) { 51 if (error.description != null) {
100 message = "$message (${error.description})"; 52 message = "$message (${error.description})";
101 } 53 }
102 log.error("$message."); 54 log.error("$message.");
103 clearCredentials(cache); 55 clearCredentials(cache);
104 return withClient(cache, fn); 56 return withClient(cache, fn);
105 } else { 57 } else {
106 throw error; 58 throw error;
107 } 59 }
108 }); 60 });
109 } 61 }
110
111 /// Gets a new OAuth2 client.
112 ///
113 /// If saved credentials are available, those are used; otherwise, the user is
114 /// prompted to authorize the pub client.
115 Future<Client> _getClient(SystemCache cache) { 62 Future<Client> _getClient(SystemCache cache) {
116 return new Future.sync(() { 63 return new Future.sync(() {
117 var credentials = _loadCredentials(cache); 64 var credentials = _loadCredentials(cache);
118 if (credentials == null) return _authorize(); 65 if (credentials == null) return _authorize();
119 66 var client =
120 var client = new Client(_identifier, _secret, credentials, 67 new Client(_identifier, _secret, credentials, httpClient: httpClient);
121 httpClient: httpClient);
122 _saveCredentials(cache, client.credentials); 68 _saveCredentials(cache, client.credentials);
123 return client; 69 return client;
124 }); 70 });
125 } 71 }
126
127 /// Loads the user's OAuth2 credentials from the in-memory cache or the
128 /// filesystem if possible.
129 ///
130 /// If the credentials can't be loaded for any reason, the returned [Future]
131 /// completes to `null`.
132 Credentials _loadCredentials(SystemCache cache) { 72 Credentials _loadCredentials(SystemCache cache) {
133 log.fine('Loading OAuth2 credentials.'); 73 log.fine('Loading OAuth2 credentials.');
134
135 try { 74 try {
136 if (_credentials != null) return _credentials; 75 if (_credentials != null) return _credentials;
137
138 var path = _credentialsFile(cache); 76 var path = _credentialsFile(cache);
139 if (!fileExists(path)) return null; 77 if (!fileExists(path)) return null;
140
141 var credentials = new Credentials.fromJson(readTextFile(path)); 78 var credentials = new Credentials.fromJson(readTextFile(path));
142 if (credentials.isExpired && !credentials.canRefresh) { 79 if (credentials.isExpired && !credentials.canRefresh) {
143 log.error("Pub's authorization to upload packages has expired and " 80 log.error(
144 "can't be automatically refreshed."); 81 "Pub's authorization to upload packages has expired and "
145 return null; // null means re-authorize. 82 "can't be automatically refreshed.");
83 return null;
146 } 84 }
147
148 return credentials; 85 return credentials;
149 } catch (e) { 86 } catch (e) {
150 log.error('Warning: could not load the saved OAuth2 credentials: $e\n' 87 log.error(
151 'Obtaining new credentials...'); 88 'Warning: could not load the saved OAuth2 credentials: $e\n'
152 return null; // null means re-authorize. 89 'Obtaining new credentials...');
90 return null;
153 } 91 }
154 } 92 }
155
156 /// Save the user's OAuth2 credentials to the in-memory cache and the
157 /// filesystem.
158 void _saveCredentials(SystemCache cache, Credentials credentials) { 93 void _saveCredentials(SystemCache cache, Credentials credentials) {
159 log.fine('Saving OAuth2 credentials.'); 94 log.fine('Saving OAuth2 credentials.');
160 _credentials = credentials; 95 _credentials = credentials;
161 var credentialsPath = _credentialsFile(cache); 96 var credentialsPath = _credentialsFile(cache);
162 ensureDir(path.dirname(credentialsPath)); 97 ensureDir(path.dirname(credentialsPath));
163 writeTextFile(credentialsPath, credentials.toJson(), dontLogContents: true); 98 writeTextFile(credentialsPath, credentials.toJson(), dontLogContents: true);
164 } 99 }
165
166 /// The path to the file in which the user's OAuth2 credentials are stored.
167 String _credentialsFile(SystemCache cache) => 100 String _credentialsFile(SystemCache cache) =>
168 path.join(cache.rootDir, 'credentials.json'); 101 path.join(cache.rootDir, 'credentials.json');
169
170 /// Gets the user to authorize pub as a client of pub.dartlang.org via oauth2.
171 ///
172 /// Returns a Future that completes to a fully-authorized [Client].
173 Future<Client> _authorize() { 102 Future<Client> _authorize() {
174 var grant = new AuthorizationCodeGrant( 103 var grant = new AuthorizationCodeGrant(
175 _identifier, 104 _identifier,
176 _secret, 105 _secret,
177 authorizationEndpoint, 106 authorizationEndpoint,
178 tokenEndpoint, 107 tokenEndpoint,
179 httpClient: httpClient); 108 httpClient: httpClient);
180
181 // Spin up a one-shot HTTP server to receive the authorization code from the
182 // Google OAuth2 server via redirect. This server will close itself as soon as
183 // the code is received.
184 var completer = new Completer(); 109 var completer = new Completer();
185 bindServer('localhost', 0).then((server) { 110 bindServer('localhost', 0).then((server) {
186 shelf_io.serveRequests(server, (request) { 111 shelf_io.serveRequests(server, (request) {
187 if (request.url.path != "/") { 112 if (request.url.path != "/") {
188 return new shelf.Response.notFound('Invalid URI.'); 113 return new shelf.Response.notFound('Invalid URI.');
189 } 114 }
190
191 log.message('Authorization received, processing...'); 115 log.message('Authorization received, processing...');
192 var queryString = request.url.query; 116 var queryString = request.url.query;
193 if (queryString == null) queryString = ''; 117 if (queryString == null) queryString = '';
194
195 // Closing the server here is safe, since it will wait until the response
196 // is sent to actually shut down.
197 server.close(); 118 server.close();
198 chainToCompleter(grant.handleAuthorizationResponse(queryToMap(queryString) ), 119 chainToCompleter(
120 grant.handleAuthorizationResponse(queryToMap(queryString)),
199 completer); 121 completer);
200
201 return new shelf.Response.found('http://pub.dartlang.org/authorized'); 122 return new shelf.Response.found('http://pub.dartlang.org/authorized');
202 }); 123 });
203
204 var authUrl = grant.getAuthorizationUrl( 124 var authUrl = grant.getAuthorizationUrl(
205 Uri.parse('http://localhost:${server.port}'), scopes: _scopes); 125 Uri.parse('http://localhost:${server.port}'),
206 126 scopes: _scopes);
207 log.message( 127 log.message(
208 'Pub needs your authorization to upload packages on your behalf.\n' 128 'Pub needs your authorization to upload packages on your behalf.\n'
209 'In a web browser, go to $authUrl\n' 129 'In a web browser, go to $authUrl\n' 'Then click "Allow access".\n\n '
210 'Then click "Allow access".\n\n' 130 'Waiting for your authorization...');
211 'Waiting for your authorization...');
212 }); 131 });
213
214 return completer.future.then((client) { 132 return completer.future.then((client) {
215 log.message('Successfully authorized.\n'); 133 log.message('Successfully authorized.\n');
216 return client; 134 return client;
217 }); 135 });
218 } 136 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698