OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 library oauth2; | 5 library oauth2; |
6 | 6 |
7 import 'dart:io'; | 7 import 'dart:io'; |
8 import 'dart:uri'; | 8 import 'dart:uri'; |
9 | 9 |
10 // TODO(nweiz): Make this a "package:" URL, or something nicer than this. | 10 // TODO(nweiz): Make this a "package:" URL, or something nicer than this. |
11 import '../../pkg/oauth2/lib/oauth2.dart'; | 11 import '../../pkg/oauth2/lib/oauth2.dart'; |
12 import 'io.dart'; | 12 import 'io.dart'; |
| 13 import 'log.dart' as log; |
13 import 'system_cache.dart'; | 14 import 'system_cache.dart'; |
14 import 'utils.dart'; | 15 import 'utils.dart'; |
15 | 16 |
16 export '../../pkg/oauth2/lib/oauth2.dart'; | 17 export '../../pkg/oauth2/lib/oauth2.dart'; |
17 | 18 |
18 /// The pub client's OAuth2 identifier. | 19 /// The pub client's OAuth2 identifier. |
19 final _identifier = '818368855108-8grd2eg9tj9f38os6f1urbcvsq399u8n.apps.' | 20 final _identifier = '818368855108-8grd2eg9tj9f38os6f1urbcvsq399u8n.apps.' |
20 'googleusercontent.com'; | 21 'googleusercontent.com'; |
21 | 22 |
22 /// The pub client's OAuth2 secret. This isn't actually meant to be kept a | 23 /// The pub client's OAuth2 secret. This isn't actually meant to be kept a |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
93 _identifier, _secret, credentials, httpClient: curlClient)); | 94 _identifier, _secret, credentials, httpClient: curlClient)); |
94 }).chain((client) { | 95 }).chain((client) { |
95 return _saveCredentials(cache, client.credentials).transform((_) => client); | 96 return _saveCredentials(cache, client.credentials).transform((_) => client); |
96 }); | 97 }); |
97 } | 98 } |
98 | 99 |
99 /// Loads the user's OAuth2 credentials from the in-memory cache or the | 100 /// Loads the user's OAuth2 credentials from the in-memory cache or the |
100 /// filesystem if possible. If the credentials can't be loaded for any reason, | 101 /// filesystem if possible. If the credentials can't be loaded for any reason, |
101 /// the returned [Future] will complete to null. | 102 /// the returned [Future] will complete to null. |
102 Future<Credentials> _loadCredentials(SystemCache cache) { | 103 Future<Credentials> _loadCredentials(SystemCache cache) { |
103 if (_credentials != null) return new Future.immediate(_credentials); | 104 log.fine('Loading OAuth2 credentials.'); |
104 return fileExists(_credentialsFile(cache)).chain((credentialsExist) { | 105 |
105 if (!credentialsExist) return new Future.immediate(null); | 106 if (_credentials != null) { |
| 107 log.fine('Using already-loaded credentials.'); |
| 108 return new Future.immediate(_credentials); |
| 109 } |
| 110 |
| 111 var path = _credentialsFile(cache); |
| 112 return fileExists(path).chain((credentialsExist) { |
| 113 if (!credentialsExist) { |
| 114 log.fine('No credentials found at $path.'); |
| 115 return new Future.immediate(null); |
| 116 } |
106 | 117 |
107 return readTextFile(_credentialsFile(cache)).transform((credentialsJson) { | 118 return readTextFile(_credentialsFile(cache)).transform((credentialsJson) { |
108 var credentials = new Credentials.fromJson(credentialsJson); | 119 var credentials = new Credentials.fromJson(credentialsJson); |
109 if (credentials.isExpired && !credentials.canRefresh) { | 120 if (credentials.isExpired && !credentials.canRefresh) { |
110 printError("Pub's authorization to upload packages has expired and " | 121 log.error("Pub's authorization to upload packages has expired and " |
111 "can't be automatically refreshed."); | 122 "can't be automatically refreshed."); |
112 return null; // null means re-authorize | 123 return null; // null means re-authorize |
113 } | 124 } |
114 | 125 |
115 return credentials; | 126 return credentials; |
116 }); | 127 }); |
117 }).transformException((e) { | 128 }).transformException((e) { |
118 printError('Warning: could not load the saved OAuth2 credentials:' | 129 log.error('Warning: could not load the saved OAuth2 credentials: $e\n' |
119 ' $e\n' | |
120 'Obtaining new credentials...'); | 130 'Obtaining new credentials...'); |
121 return null; // null means re-authorize | 131 return null; // null means re-authorize |
122 }); | 132 }); |
123 } | 133 } |
124 | 134 |
125 /// Save the user's OAuth2 credentials to the in-memory cache and the | 135 /// Save the user's OAuth2 credentials to the in-memory cache and the |
126 /// filesystem. | 136 /// filesystem. |
127 Future _saveCredentials(SystemCache cache, Credentials credentials) { | 137 Future _saveCredentials(SystemCache cache, Credentials credentials) { |
| 138 log.fine('Saving OAuth2 credentials.'); |
128 _credentials = credentials; | 139 _credentials = credentials; |
129 var credentialsFile = _credentialsFile(cache); | 140 var path = _credentialsFile(cache); |
130 return ensureDir(dirname(credentialsFile)).chain((_) => | 141 return ensureDir(dirname(path)).chain((_) => |
131 writeTextFile(credentialsFile, credentials.toJson())); | 142 writeTextFile(path, credentials.toJson())); |
132 } | 143 } |
133 | 144 |
134 /// The path to the file in which the user's OAuth2 credentials are stored. | 145 /// The path to the file in which the user's OAuth2 credentials are stored. |
135 String _credentialsFile(SystemCache cache) => | 146 String _credentialsFile(SystemCache cache) => |
136 join(cache.rootDir, 'credentials.json'); | 147 join(cache.rootDir, 'credentials.json'); |
137 | 148 |
138 /// Gets the user to authorize pub as a client of pub.dartlang.org via oauth2. | 149 /// Gets the user to authorize pub as a client of pub.dartlang.org via oauth2. |
139 /// Returns a Future that will complete to a fully-authorized [Client]. | 150 /// Returns a Future that will complete to a fully-authorized [Client]. |
140 Future<Client> _authorize() { | 151 Future<Client> _authorize() { |
141 // Allow the tests to inject their own token endpoint URL. | 152 // Allow the tests to inject their own token endpoint URL. |
(...skipping 12 matching lines...) Expand all Loading... |
154 httpClient: curlClient); | 165 httpClient: curlClient); |
155 | 166 |
156 // Spin up a one-shot HTTP server to receive the authorization code from the | 167 // Spin up a one-shot HTTP server to receive the authorization code from the |
157 // Google OAuth2 server via redirect. This server will close itself as soon as | 168 // Google OAuth2 server via redirect. This server will close itself as soon as |
158 // the code is received. | 169 // the code is received. |
159 var completer = new Completer(); | 170 var completer = new Completer(); |
160 var server = new HttpServer(); | 171 var server = new HttpServer(); |
161 server.addRequestHandler((request) => request.path == "/", | 172 server.addRequestHandler((request) => request.path == "/", |
162 (request, response) { | 173 (request, response) { |
163 chainToCompleter(new Future.immediate(null).chain((_) { | 174 chainToCompleter(new Future.immediate(null).chain((_) { |
164 print('Authorization received, processing...'); | 175 log.message('Authorization received, processing...'); |
165 var queryString = request.queryString; | 176 var queryString = request.queryString; |
166 if (queryString == null) queryString = ''; | 177 if (queryString == null) queryString = ''; |
167 response.statusCode = 302; | 178 response.statusCode = 302; |
168 response.headers.set('location', 'http://pub.dartlang.org/authorized'); | 179 response.headers.set('location', 'http://pub.dartlang.org/authorized'); |
169 return Futures.wait([ | 180 return Futures.wait([ |
170 closeHttpResponse(request, response), | 181 closeHttpResponse(request, response), |
171 grant.handleAuthorizationResponse(queryToMap(queryString)) | 182 grant.handleAuthorizationResponse(queryToMap(queryString)) |
172 ]); | 183 ]); |
173 }).transform((results) { | 184 }).transform((results) { |
174 server.close(); | 185 server.close(); |
175 return results[1]; | 186 return results[1]; |
176 }), completer); | 187 }), completer); |
177 }); | 188 }); |
178 server.listen('127.0.0.1', 0); | 189 server.listen('127.0.0.1', 0); |
179 | 190 |
180 var authUrl = grant.getAuthorizationUrl( | 191 var authUrl = grant.getAuthorizationUrl( |
181 new Uri.fromString('http://localhost:${server.port}'), scopes: _scopes); | 192 new Uri.fromString('http://localhost:${server.port}'), scopes: _scopes); |
182 | 193 |
183 print('Pub needs your authorization to upload packages on your behalf.\n' | 194 log.message( |
184 'In a web browser, go to $authUrl\n' | 195 'Pub needs your authorization to upload packages on your behalf.\n' |
185 'Then click "Allow access".\n\n' | 196 'In a web browser, go to $authUrl\n' |
186 'Waiting for your authorization...'); | 197 'Then click "Allow access".\n\n' |
| 198 'Waiting for your authorization...'); |
187 | 199 |
188 return completer.future.transform((client) { | 200 return completer.future.transform((client) { |
189 print('Successfully authorized.\n'); | 201 log.message('Successfully authorized.\n'); |
190 return client; | 202 return client; |
191 }); | 203 }); |
192 } | 204 } |
OLD | NEW |