ember_simple_auth-rails 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a46609437e0589bf826fe15f379e8c31320b16aa
4
+ data.tar.gz: 6b019c17a72b3efa41bf43bf33ace31ef4c4fd8a
5
+ SHA512:
6
+ metadata.gz: 8404a68ae21dec8776ad28e4ad133002ba0dfbfc9506403fa1fb93147dcc7e2e00325aa6957268e4b119ea3c89a09066ed85b4f6a2c84b1202cd4211cb5a6064
7
+ data.tar.gz: 110100e3fd7b7198eed7ae6f875f3bf4d55173111ff686e8348d446d6e4cf5e3e944740eee9980e98a8f363c468b94a9ed47240cba746625b2595a59e968bf59
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 doodzik
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,29 @@
1
+ # EmberSimpleAuth::Rails
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'ember_simple_auth-rails'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install ember_simple_auth-rails
18
+
19
+ ## Usage
20
+
21
+ TODO: Write usage instructions here
22
+
23
+ ## Contributing
24
+
25
+ 1. Fork it ( http://github.com/<my-github-username>/ember_simple_auth-rails/fork )
26
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
27
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
28
+ 4. Push to the branch (`git push origin my-new-feature`)
29
+ 5. Create new Pull Request
@@ -0,0 +1,8 @@
1
+ require "ember_simple_auth/rails/version"
2
+
3
+ module EmberSimpleAuth
4
+ module Rails
5
+ class Engine < ::Rails::Engine
6
+ end
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ module EmberSimpleAuth
2
+ module Rails
3
+ VERSION = "0.2.0"
4
+ end
5
+ end
@@ -0,0 +1,1749 @@
1
+ (function(global) {
2
+
3
+ var define, requireModule;
4
+
5
+ (function() {
6
+ var registry = {}, seen = {};
7
+
8
+ define = function(name, deps, callback) {
9
+ registry[name] = { deps: deps, callback: callback };
10
+ };
11
+
12
+ requireModule = function(name) {
13
+ if (seen.hasOwnProperty(name)) { return seen[name]; }
14
+ seen[name] = {};
15
+
16
+ if (!registry[name]) {
17
+ throw new Error("Could not find module " + name);
18
+ }
19
+
20
+ var mod = registry[name],
21
+ deps = mod.deps,
22
+ callback = mod.callback,
23
+ reified = [],
24
+ exports;
25
+
26
+ for (var i=0, l=deps.length; i<l; i++) {
27
+ if (deps[i] === 'exports') {
28
+ reified.push(exports = {});
29
+ } else {
30
+ reified.push(requireModule(resolve(deps[i])));
31
+ }
32
+ }
33
+
34
+ var value = callback.apply(this, reified);
35
+ return seen[name] = exports || value;
36
+
37
+ function resolve(child) {
38
+ if (child.charAt(0) !== '.') { return child; }
39
+ var parts = child.split("/");
40
+ var parentBase = name.split("/").slice(0, -1);
41
+
42
+ for (var i=0, l=parts.length; i<l; i++) {
43
+ var part = parts[i];
44
+
45
+ if (part === '..') { parentBase.pop(); }
46
+ else if (part === '.') { continue; }
47
+ else { parentBase.push(part); }
48
+ }
49
+
50
+ return parentBase.join("/");
51
+ }
52
+ };
53
+
54
+ requireModule.registry = registry;
55
+ })();
56
+
57
+ define("ember-simple-auth",
58
+ ["./ember-simple-auth/core","./ember-simple-auth/session","./ember-simple-auth/authenticators","./ember-simple-auth/authorizers","./ember-simple-auth/stores","./ember-simple-auth/mixins/application_route_mixin","./ember-simple-auth/mixins/authenticated_route_mixin","./ember-simple-auth/mixins/authentication_controller_mixin","./ember-simple-auth/mixins/login_controller_mixin","exports"],
59
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __dependency5__, __dependency6__, __dependency7__, __dependency8__, __dependency9__, __exports__) {
60
+ "use strict";
61
+ var setup = __dependency1__.setup;
62
+ var Configuration = __dependency1__.Configuration;
63
+ var Session = __dependency2__.Session;
64
+ var Authenticators = __dependency3__.Authenticators;
65
+ var Authorizers = __dependency4__.Authorizers;
66
+ var Stores = __dependency5__.Stores;
67
+ var ApplicationRouteMixin = __dependency6__.ApplicationRouteMixin;
68
+ var AuthenticatedRouteMixin = __dependency7__.AuthenticatedRouteMixin;
69
+ var AuthenticationControllerMixin = __dependency8__.AuthenticationControllerMixin;
70
+ var LoginControllerMixin = __dependency9__.LoginControllerMixin;
71
+
72
+ /**
73
+ Ember.SimpleAuth's main module.
74
+
75
+ @module Ember.SimpleAuth
76
+ */
77
+
78
+ __exports__.setup = setup;
79
+ __exports__.Configuration = Configuration;
80
+ __exports__.Session = Session;
81
+ __exports__.Authenticators = Authenticators;
82
+ __exports__.Authorizers = Authorizers;
83
+ __exports__.Stores = Stores;
84
+ __exports__.ApplicationRouteMixin = ApplicationRouteMixin;
85
+ __exports__.AuthenticatedRouteMixin = AuthenticatedRouteMixin;
86
+ __exports__.AuthenticationControllerMixin = AuthenticationControllerMixin;
87
+ __exports__.LoginControllerMixin = LoginControllerMixin;
88
+ });
89
+ define("ember-simple-auth/authenticators",
90
+ ["./authenticators/base","./authenticators/oauth2","exports"],
91
+ function(__dependency1__, __dependency2__, __exports__) {
92
+ "use strict";
93
+ var global = (typeof window !== 'undefined') ? window : {},
94
+ Ember = global.Ember;
95
+
96
+ var Base = __dependency1__.Base;
97
+ var OAuth2 = __dependency2__.OAuth2;
98
+
99
+ var Authenticators = Ember.Namespace.create({
100
+ Base: Base,
101
+ OAuth2: OAuth2
102
+ });
103
+
104
+ __exports__.Authenticators = Authenticators;
105
+ });
106
+ define("ember-simple-auth/authenticators/base",
107
+ ["exports"],
108
+ function(__exports__) {
109
+ "use strict";
110
+ var global = (typeof window !== 'undefined') ? window : {},
111
+ Ember = global.Ember;
112
+
113
+ /**
114
+ The base for all authenticators. __This serves as a starting point for
115
+ implementing custom authenticators and must not be used directly.__
116
+
117
+ The authenticator acquires all data that makes up the session. The actual
118
+ mechanism used to do this might e.g. be posting a set of credentials to a
119
+ server and in exchange retrieving an access token, initiating authentication
120
+ against an external provider like Facebook etc. and depends on the specific
121
+ authenticator. Any data that the authenticator receives upon successful
122
+ authentication and resolves with grom the
123
+ [Ember.SimpleAuth.Authenticators.Base#authenticate](#Ember-SimpleAuth-Authenticators-Base-authenticate)
124
+ method is stored in the session and can then be used by the authorizer (see
125
+ [Ember.SimpleAuth.Authorizers.Base](#Ember-SimpleAuth-Authorizers-Base)).
126
+
127
+ Authenticators may trigger the `'ember-simple-auth:session-updated'` event
128
+ when any of the session properties change. The session listens to that event
129
+ and will handle the changes accordingly.
130
+
131
+ __Custom authenticators have to be registered with Ember's dependency
132
+ injection container__ so that the session can retrieve an instance, e.g.:
133
+
134
+ ```javascript
135
+ var CustomAuthenticator = Ember.SimpleAuth.Authenticators.Base.extend({
136
+ ...
137
+ });
138
+ Ember.Application.initializer({
139
+ name: 'authentication',
140
+ initialize: function(container, application) {
141
+ container.register('app:authenticators:custom', CustomAuthenticator);
142
+ Ember.SimpleAuth.setup(container, application);
143
+ }
144
+ });
145
+ ```
146
+
147
+ @class Base
148
+ @namespace Authenticators
149
+ @extends Ember.Object
150
+ @uses Ember.Evented
151
+ */
152
+ var Base = Ember.Object.extend(Ember.Evented, {
153
+ /**
154
+ Restores the session from a set of properties. __This method is invoked by
155
+ the session either after the applciation starts up and session data was
156
+ restored from the store__ or when properties in the store have changed due
157
+ to external events (e.g. in another tab).
158
+
159
+ __This method returns a promise. A resolving promise will result in the
160
+ session being authenticated.__ Any properties the promise resolves with
161
+ will be saved by and accessible via the session. In most cases the
162
+ `properties` argument will simply be forwarded through the promise. A
163
+ rejecting promise indicates that authentication failed and the session
164
+ will remain unchanged.
165
+
166
+ `Ember.SimpleAuth.Authenticators.Base`'s always rejects as there's no
167
+ reasonable default implementation.
168
+
169
+ @method restore
170
+ @param {Object} data The data to restore the session from
171
+ @return {Ember.RSVP.Promise} A promise that when it resolves results in the session being authenticated
172
+ */
173
+ restore: function(data) {
174
+ return new Ember.RSVP.reject();
175
+ },
176
+
177
+ /**
178
+ Authenticates the session with the specified `options`. These options vary
179
+ depending on the actual authentication mechanism the authenticator
180
+ implements (e.g. a set of credentials or a Facebook account id etc.). __The
181
+ session will invoke this method when an action in the appliaction triggers
182
+ authentication__ (see
183
+ [Ember.SimpleAuth.AuthenticationControllerMixin.actions#authenticate](#Ember-SimpleAuth-AuthenticationControllerMixin-authenticate)).
184
+
185
+ __This method returns a promise. A resolving promise will result in the
186
+ session being authenticated.__ Any properties the promise resolves with
187
+ will be saved by and accessible via the session. A rejecting promise
188
+ indicates that authentication failed and the session will remain unchanged.
189
+
190
+ `Ember.SimpleAuth.Authenticators.Base`'s implementation always returns a
191
+ rejecting promise and thus never authenticates the session as there's no
192
+ reasonable default behavior (for Ember.SimpleAuth's default authenticator
193
+ see
194
+ [Ember.SimpleAuth.Authenticators.OAuth2](#Ember-SimpleAuth-Authenticators-OAuth2)).
195
+
196
+ @method authenticate
197
+ @param {Object} options The options to authenticate the session with
198
+ @return {Ember.RSVP.Promise} A promise that when it resolves results in the session being authenticated
199
+ */
200
+ authenticate: function(options) {
201
+ return new Ember.RSVP.reject();
202
+ },
203
+
204
+ /**
205
+ Invalidation callback that is invoked when the session is invalidated.
206
+ While the session will invalidate itself and clear all session properties,
207
+ it might be necessary for some authenticators to perform additional tasks
208
+ (e.g. invalidating an access token on the server), which should be done in
209
+ this method.
210
+
211
+ __This method returns a promise. A resolving promise will result in the
212
+ session being invalidated.__ A rejecting promise will result in the session
213
+ invalidation being intercepted and the session being left authenticated.
214
+
215
+ `Ember.SimpleAuth.Authenticators.Base`'s implementation always returns a
216
+ resolving promise and thus never intercepts session invalidation.
217
+
218
+ @method invalidate
219
+ @return {Ember.RSVP.Promise} A promise that when it resolves results in the session being invalidated
220
+ */
221
+ invalidate: function() {
222
+ return new Ember.RSVP.resolve();
223
+ }
224
+ });
225
+
226
+ __exports__.Base = Base;
227
+ });
228
+ define("ember-simple-auth/authenticators/oauth2",
229
+ ["./base","../utils/is_secure_url","exports"],
230
+ function(__dependency1__, __dependency2__, __exports__) {
231
+ "use strict";
232
+ var global = (typeof window !== 'undefined') ? window : {},
233
+ Ember = global.Ember;
234
+
235
+ var Base = __dependency1__.Base;
236
+ var isSecureUrl = __dependency2__.isSecureUrl;
237
+
238
+ /**
239
+ Authenticator that conforms to OAuth 2
240
+ ([RFC 6749](http://tools.ietf.org/html/rfc6749)), specifically the _"Resource
241
+ Owner Password Credentials Grant Type"_.
242
+
243
+ This authenticator supports refreshing the access token automatically and
244
+ will trigger the `'ember-simple-auth:session-updated'` event each time the
245
+ token was refreshed.
246
+
247
+ @class OAuth2
248
+ @namespace Authenticators
249
+ @extends Authenticators.Base
250
+ */
251
+ var OAuth2 = Base.extend({
252
+ /**
253
+ The endpoint on the server the authenticator acquires the access token
254
+ from.
255
+
256
+ @property serverTokenEndpoint
257
+ @type String
258
+ @default '/token'
259
+ */
260
+ serverTokenEndpoint: '/token',
261
+ /**
262
+ Sets whether the authenticator automatically refreshes access tokens.
263
+
264
+ @property refreshAccessTokens
265
+ @type Boolean
266
+ @default true
267
+ */
268
+ refreshAccessTokens: true,
269
+ /**
270
+ @property _refreshTokenTimeout
271
+ @private
272
+ */
273
+ _refreshTokenTimeout: null,
274
+
275
+ /**
276
+ Restores the session from a set of session properties; __will return a
277
+ resolving promise when there's a non-empty `access_token` in the `data`__
278
+ and a rejecting promise otherwise.
279
+
280
+ This method also schedules automatic token refreshing when there are values
281
+ for `refresh_token` and `expires_in` in the `data` and automatic token
282
+ refreshing is not disabled (see
283
+ [Ember.SimpleAuth.Authenticators.OAuth2#refreshAccessTokens](#Ember-SimpleAuth-Authenticators-OAuth2-refreshAccessTokens)).
284
+
285
+ @method restore
286
+ @param {Object} data The data to restore the session from
287
+ @return {Ember.RSVP.Promise} A promise that when it resolves results in the session being authenticated
288
+ */
289
+ restore: function(data) {
290
+ var _this = this;
291
+ return new Ember.RSVP.Promise(function(resolve, reject) {
292
+ if (!Ember.isEmpty(data.access_token)) {
293
+ var now = (new Date()).getTime();
294
+ if (!Ember.isEmpty(data.expires_at) && data.expires_at < now) {
295
+ reject();
296
+ } else {
297
+ _this.scheduleAccessTokenRefresh(data.expires_in, data.expires_at, data.refresh_token);
298
+ resolve(data);
299
+ }
300
+ } else {
301
+ reject();
302
+ }
303
+ });
304
+ },
305
+
306
+ /**
307
+ Authenticates the session with the specified `credentials`; the credentials
308
+ are `POST`ed to the `serverTokenEndpoint` and if they are valid the server
309
+ returns an access token in response (see
310
+ http://tools.ietf.org/html/rfc6749#section-4.3). __If the credentials are
311
+ valid and authentication succeeds, a promise that resolves with the
312
+ server's response is returned__, otherwise a promise that rejects with the
313
+ error is returned.
314
+
315
+ This method also schedules automatic token refreshing when there are values
316
+ for `refresh_token` and `expires_in` in the server response and automatic
317
+ token refreshing is not disabled (see
318
+ [Ember.SimpleAuth.Authenticators.OAuth2#refreshAccessTokens](#Ember-SimpleAuth-Authenticators-OAuth2-refreshAccessTokens)).
319
+
320
+ @method authenticate
321
+ @param {Object} credentials The credentials to authenticate the session with
322
+ @return {Ember.RSVP.Promise} A promise that resolves when an access token is successfully acquired from the server and rejects otherwise
323
+ */
324
+ authenticate: function(credentials) {
325
+ var _this = this;
326
+ return new Ember.RSVP.Promise(function(resolve, reject) {
327
+ var data = { grant_type: 'password', username: credentials.identification, password: credentials.password };
328
+ _this.makeRequest(data).then(function(response) {
329
+ Ember.run(function() {
330
+ var expiresAt = _this.absolutizeExpirationTime(response.expires_in);
331
+ _this.scheduleAccessTokenRefresh(response.expires_in, expiresAt, response.refresh_token);
332
+ resolve(Ember.$.extend(response, { expires_at: expiresAt }));
333
+ });
334
+ }, function(xhr, status, error) {
335
+ Ember.run(function() {
336
+ reject(xhr.responseJSON || xhr.responseText);
337
+ });
338
+ });
339
+ });
340
+ },
341
+
342
+ /**
343
+ Cancels any outstanding automatic token refreshes.
344
+
345
+ @method invalidate
346
+ @return {Ember.RSVP.Promise} A resolving promise
347
+ */
348
+ invalidate: function() {
349
+ Ember.run.cancel(this._refreshTokenTimeout);
350
+ delete this._refreshTokenTimeout;
351
+ return new Ember.RSVP.resolve();
352
+ },
353
+
354
+ /**
355
+ Sends an `AJAX` request to the `serverTokenEndpoint`. This will always be a
356
+ _"POST_" request with content type _"application/x-www-form-urlencoded"_ as
357
+ specified in [RFC 6749](http://tools.ietf.org/html/rfc6749).
358
+
359
+ This method is not meant to be used directly but serves as an extension
360
+ point to e.g. add _"Client Credentials"_ (see
361
+ [RFC 6749, section 2.3](http://tools.ietf.org/html/rfc6749#section-2.3)).
362
+
363
+ @method makeRequest
364
+ @param {Object} data The data to send with the request, e.g. username and password or the refresh token
365
+ @return {Deferred object} A Deferred object (see [the jQuery docs](http://api.jquery.com/category/deferred-object/)) that is compatible to Ember.RSVP.Promise; will resolve if the request succeeds, reject otherwise
366
+ @protected
367
+ */
368
+ makeRequest: function(data) {
369
+ if (!isSecureUrl(this.serverTokenEndpoint)) {
370
+ Ember.Logger.warn('Credentials are transmitted via an insecure connection - use HTTPS to keep them secure.');
371
+ }
372
+ return Ember.$.ajax({
373
+ url: this.serverTokenEndpoint,
374
+ type: 'POST',
375
+ data: data,
376
+ dataType: 'json',
377
+ contentType: 'application/x-www-form-urlencoded'
378
+ });
379
+ },
380
+
381
+ /**
382
+ @method scheduleAccessTokenRefresh
383
+ @private
384
+ */
385
+ scheduleAccessTokenRefresh: function(expiresIn, expiresAt, refreshToken) {
386
+ var _this = this;
387
+ if (this.refreshAccessTokens) {
388
+ var now = (new Date()).getTime();
389
+ if (Ember.isEmpty(expiresAt) && !Ember.isEmpty(expiresIn)) {
390
+ expiresAt = new Date(now + (expiresIn - 5) * 1000).getTime();
391
+ }
392
+ if (!Ember.isEmpty(refreshToken) && !Ember.isEmpty(expiresAt) && expiresAt > now) {
393
+ Ember.run.cancel(this._refreshTokenTimeout);
394
+ delete this._refreshTokenTimeout;
395
+ this._refreshTokenTimeout = Ember.run.later(this, this.refreshAccessToken, expiresIn, refreshToken, expiresAt - now);
396
+ }
397
+ }
398
+ },
399
+
400
+ /**
401
+ @method refreshAccessToken
402
+ @private
403
+ */
404
+ refreshAccessToken: function(expiresIn, refreshToken) {
405
+ var _this = this;
406
+ var data = { grant_type: 'refresh_token', refresh_token: refreshToken };
407
+ this.makeRequest(data).then(function(response) {
408
+ Ember.run(function() {
409
+ expiresIn = response.expires_in || expiresIn;
410
+ refreshToken = response.refresh_token || refreshToken;
411
+ var expiresAt = _this.absolutizeExpirationTime(expiresIn);
412
+ _this.scheduleAccessTokenRefresh(expiresIn, null, refreshToken);
413
+ _this.trigger('ember-simple-auth:session-updated', Ember.$.extend(response, { expires_in: expiresIn, expires_at: expiresAt, refresh_token: refreshToken }));
414
+ });
415
+ }, function(xhr, status, error) {
416
+ Ember.Logger.warn('Access token could not be refreshed - server responded with ' + error + '.');
417
+ });
418
+ },
419
+
420
+ /**
421
+ @method absolutizeExpirationTime
422
+ @private
423
+ */
424
+ absolutizeExpirationTime: function(expiresIn) {
425
+ if (!Ember.isEmpty(expiresIn)) {
426
+ return new Date((new Date().getTime()) + (expiresIn - 5) * 1000).getTime();
427
+ }
428
+ }
429
+ });
430
+
431
+ __exports__.OAuth2 = OAuth2;
432
+ });
433
+ define("ember-simple-auth/authorizers",
434
+ ["./authorizers/base","./authorizers/oauth2","exports"],
435
+ function(__dependency1__, __dependency2__, __exports__) {
436
+ "use strict";
437
+ var global = (typeof window !== 'undefined') ? window : {},
438
+ Ember = global.Ember;
439
+
440
+ var Base = __dependency1__.Base;
441
+ var OAuth2 = __dependency2__.OAuth2;
442
+
443
+ var Authorizers = Ember.Namespace.create({
444
+ Base: Base,
445
+ OAuth2: OAuth2
446
+ });
447
+
448
+ __exports__.Authorizers = Authorizers;
449
+ });
450
+ define("ember-simple-auth/authorizers/base",
451
+ ["exports"],
452
+ function(__exports__) {
453
+ "use strict";
454
+ var global = (typeof window !== 'undefined') ? window : {},
455
+ Ember = global.Ember;
456
+
457
+ /**
458
+ The base for all authorizers. __This serves as a starting point for
459
+ implementing custom authorizers and must not be used directly.__
460
+
461
+ __The authorizer preprocesses all XHR requests__ (expect ones to 3rd party
462
+ origins, see [Ember.SimpleAuth.setup](#Ember-SimpleAuth-setup)) and makes
463
+ sure they have the required data attached that allows the server to identify
464
+ the user making the request. This data might be a specific header, data in
465
+ the query part of the URL, cookies etc. __The authorizer has to fit the
466
+ authenticator__ (see
467
+ [Ember.SimpleAuth.Authenticators.Base](#Ember-SimpleAuth-Authenticators-Base))
468
+ as it usually relies on data that the authenticator retrieves during
469
+ authentication and that it makes available through the session.
470
+
471
+ @class Base
472
+ @namespace Authorizers
473
+ @extends Ember.Object
474
+ */
475
+ var Base = Ember.Object.extend({
476
+ /**
477
+ The session the authorizer gets the data it needs to authorize requests
478
+ from (see [Ember.SimpleAuth.Session](#Ember-SimpleAuth-Session)).
479
+
480
+ @property session
481
+ @readOnly
482
+ @type Ember.SimpleAuth.Session
483
+ @default the session instance that is created during the Ember.js application's intialization
484
+ */
485
+ session: null,
486
+
487
+ /**
488
+ Authorizes an XHR request by adding some sort of secret information that
489
+ allows the server to identify the user making the request (e.g. a token in
490
+ the `Authorization` header or some other secret in the query string etc.).
491
+
492
+ `Ember.SimpleAuth.Authorizers.Base`'s implementation does nothing as
493
+ there's no reasonable default behavior (for Ember.SimpleAuth's default
494
+ authorizer see
495
+ [Ember.SimpleAuth.Authorizers.OAuth2](#Ember-SimpleAuth-Authorizers-OAuth2)).
496
+
497
+ @method authorize
498
+ @param {jqXHR} jqXHR The XHR request to authorize (see http://api.jquery.com/jQuery.ajax/#jqXHR)
499
+ @param {Object} requestOptions The options as provided to the `$.ajax` method (see http://api.jquery.com/jQuery.ajaxPrefilter/)
500
+ */
501
+ authorize: function(jqXHR, requestOptions) {
502
+ }
503
+ });
504
+
505
+ __exports__.Base = Base;
506
+ });
507
+ define("ember-simple-auth/authorizers/oauth2",
508
+ ["./base","../utils/is_secure_url","exports"],
509
+ function(__dependency1__, __dependency2__, __exports__) {
510
+ "use strict";
511
+ var global = (typeof window !== 'undefined') ? window : {},
512
+ Ember = global.Ember;
513
+
514
+ var Base = __dependency1__.Base;
515
+ var isSecureUrl = __dependency2__.isSecureUrl;
516
+
517
+ /**
518
+ Authorizer that conforms to OAuth 2
519
+ ([RFC 6749](http://tools.ietf.org/html/rfc6749)) by sending a bearer token
520
+ ([RFC 6749](http://tools.ietf.org/html/rfc6750)) in the request's
521
+ `Authorization` header.
522
+
523
+ @class OAuth2
524
+ @namespace Authorizers
525
+ @extends Authorizers.Base
526
+ */
527
+ var OAuth2 = Base.extend({
528
+ /**
529
+ Authorizes an XHR request by sending the `access_token` property from the
530
+ session as a bearer token in the `Authorization` header:
531
+
532
+ ```
533
+ Authorization: Bearer <access_token>
534
+ ```
535
+
536
+ @method authorize
537
+ @param {jqXHR} jqXHR The XHR request to authorize (see http://api.jquery.com/jQuery.ajax/#jqXHR)
538
+ @param {Object} requestOptions The options as provided to the `$.ajax` method (see http://api.jquery.com/jQuery.ajaxPrefilter/)
539
+ */
540
+ authorize: function(jqXHR, requestOptions) {
541
+ if (this.get('session.isAuthenticated') && !Ember.isEmpty(this.get('session.access_token'))) {
542
+ if (!isSecureUrl(requestOptions.url)) {
543
+ Ember.Logger.warn('Credentials are transmitted via an insecure connection - use HTTPS to keep them secure.');
544
+ }
545
+ jqXHR.setRequestHeader('Authorization', 'Bearer ' + this.get('session.access_token'));
546
+ }
547
+ }
548
+ });
549
+
550
+ __exports__.OAuth2 = OAuth2;
551
+ });
552
+ define("ember-simple-auth/core",
553
+ ["./session","./authenticators","./authorizers","./stores","exports"],
554
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
555
+ "use strict";
556
+ var Session = __dependency1__.Session;
557
+ var Authenticators = __dependency2__.Authenticators;
558
+ var Authorizers = __dependency3__.Authorizers;
559
+ var Stores = __dependency4__.Stores;
560
+
561
+ function extractLocationOrigin(location) {
562
+ if (Ember.typeOf(location) === 'string') {
563
+ var link = document.createElement('a');
564
+ link.href = location;
565
+ //IE requires the following line when url is relative.
566
+ //First assignment of relative url to link.href results in absolute url on link.href but link.hostname and other properties are not set
567
+ //Second assignment of absolute url to link.href results in link.hostname and other properties being set as expected
568
+ link.href = link.href;
569
+ location = link;
570
+ }
571
+ var port = location.port;
572
+ if (Ember.isEmpty(port)) {
573
+ //need to include the port whether its actually present or not as some versions of IE will always set it
574
+ port = location.protocol === 'http:' ? '80' : (location.protocol === 'https:' ? '443' : '');
575
+ }
576
+ return location.protocol + '//' + location.hostname + (port !== '' ? ':' + port : '');
577
+ }
578
+
579
+ var urlOrigins = {};
580
+ var documentOrigin = extractLocationOrigin(window.location);
581
+ var crossOriginWhitelist;
582
+ function shouldAuthorizeRequest(url) {
583
+ var urlOrigin = urlOrigins[url] = urlOrigins[url] || extractLocationOrigin(url);
584
+ return crossOriginWhitelist.indexOf(urlOrigin) > -1 || urlOrigin === documentOrigin;
585
+ }
586
+
587
+ /**
588
+ Ember.SimpleAuth's configuration object.
589
+
590
+ @class Configuration
591
+ @namespace $mainModule
592
+ */
593
+ var Configuration = Ember.Namespace.create({
594
+ /**
595
+ The route to transition to for authentication; should be set through
596
+ [Ember.SimpleAuth.setup](#Ember-SimpleAuth-setup).
597
+
598
+ @property authenticationRoute
599
+ @readOnly
600
+ @static
601
+ @type String
602
+ @default 'login'
603
+ */
604
+ authenticationRoute: 'login',
605
+
606
+ /**
607
+ The route to transition to after successful authentication; should be set
608
+ through [Ember.SimpleAuth.setup](#Ember-SimpleAuth-setup).
609
+
610
+ @property routeAfterAuthentication
611
+ @readOnly
612
+ @static
613
+ @type String
614
+ @default 'index'
615
+ */
616
+ routeAfterAuthentication: 'index',
617
+
618
+ /**
619
+ @property applicationRootUrl
620
+ @static
621
+ @private
622
+ @type String
623
+ */
624
+ applicationRootUrl: null,
625
+ });
626
+
627
+ /**
628
+ Sets up Ember.SimpleAuth for the application; this method __should be invoked
629
+ in a custom initializer__ like this:
630
+
631
+ ```javascript
632
+ Ember.Application.initializer({
633
+ name: 'authentication',
634
+ initialize: function(container, application) {
635
+ Ember.SimpleAuth.setup(container, application);
636
+ }
637
+ });
638
+ ```
639
+
640
+ @method setup
641
+ @namespace $mainModule
642
+ @static
643
+ @param {Container} container The Ember.js application's dependency injection container
644
+ @param {Ember.Application} application The Ember.js application instance
645
+ @param {Object} [options]
646
+ @param {String} [options.authenticationRoute] route to transition to for authentication - defaults to `'login'`
647
+ @param {String} [options.routeAfterAuthentication] route to transition to after successful authentication - defaults to `'index'`
648
+ @param {Array[String]} [options.crossOriginWhitelist] Ember.SimpleAuth will never authorize requests going to a different origin than the one the Ember.js application was loaded from; to explicitely enable authorization for additional origins, whitelist those origins - defaults to `[]` _(beware that origins consist of protocol, host and port (port can be left out when it is 80 for HTTP or 443 for HTTPS))_
649
+ @param {Object} [options.authorizer] The authorizer _class_ to use; must extend `Ember.SimpleAuth.Authorizers.Base` - defaults to `Ember.SimpleAuth.Authorizers.OAuth2`
650
+ @param {Object} [options.store] The store _class_ to use; must extend `Ember.SimpleAuth.Stores.Base` - defaults to `Ember.SimpleAuth.Stores.LocalStorage`
651
+ **/
652
+ var setup = function(container, application, options) {
653
+ options = options || {};
654
+ Configuration.routeAfterAuthentication = options.routeAfterAuthentication || Configuration.routeAfterAuthentication;
655
+ Configuration.authenticationRoute = options.authenticationRoute || Configuration.authenticationRoute;
656
+ Configuration.applicationRootUrl = container.lookup('router:main').get('rootURL') || '/';
657
+ crossOriginWhitelist = Ember.A(options.crossOriginWhitelist || []).map(function(origin) {
658
+ return extractLocationOrigin(origin);
659
+ });
660
+
661
+ container.register('ember-simple-auth:authenticators:oauth2', Authenticators.OAuth2);
662
+
663
+ var store = (options.store || Stores.LocalStorage).create();
664
+ var session = Session.create({ store: store, container: container });
665
+ var authorizer = (options.authorizer || Authorizers.OAuth2).create({ session: session });
666
+
667
+ container.register('ember-simple-auth:session:current', session, { instantiate: false });
668
+ Ember.A(['model', 'controller', 'view', 'route']).forEach(function(component) {
669
+ container.injection(component, 'session', 'ember-simple-auth:session:current');
670
+ });
671
+
672
+ Ember.$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
673
+ if (shouldAuthorizeRequest(options.url)) {
674
+ authorizer.authorize(jqXHR, options);
675
+ }
676
+ });
677
+ };
678
+
679
+ __exports__.setup = setup;
680
+ __exports__.Configuration = Configuration;
681
+ });
682
+ define("ember-simple-auth/mixins/application_route_mixin",
683
+ ["./../core","exports"],
684
+ function(__dependency1__, __exports__) {
685
+ "use strict";
686
+ var global = (typeof window !== 'undefined') ? window : {},
687
+ Ember = global.Ember;
688
+
689
+ var Configuration = __dependency1__.Configuration;
690
+
691
+ /**
692
+ The mixin for the application route. This defines actions to authenticate the
693
+ session as well as to invalidate it. These actions can be used in all
694
+ templates like this:
695
+
696
+ ```handlebars
697
+ {{#if session.isAuthenticated}}
698
+ <a {{ action 'invalidateSession' }}>Logout</a>
699
+ {{else}}
700
+ <a {{ action 'authenticateSession' }}>Login</a>
701
+ {{/if}}
702
+ ```
703
+
704
+ While this code works it is __preferrable to use the regular `link-to` helper
705
+ for the _'login'_ link__ as that will add the `'active'` class to the link.
706
+ For the _'logout'_ actions of course there is no route.
707
+
708
+ ```handlebars
709
+ {{#if session.isAuthenticated}}
710
+ <a {{ action 'invalidateSession' }}>Logout</a>
711
+ {{else}}
712
+ {{#link-to 'login'}}Login{{/link-to}}
713
+ {{/if}}
714
+ ```
715
+
716
+ This mixin also defines actions that are triggered whenever the session is
717
+ successfully authenticated or invalidated and whenever authentication or
718
+ invalidation fails.
719
+
720
+ @class ApplicationRouteMixin
721
+ @namespace $mainModule
722
+ @extends Ember.Mixin
723
+ @static
724
+ */
725
+ var ApplicationRouteMixin = Ember.Mixin.create({
726
+ activate: function() {
727
+ var _this = this;
728
+ this._super();
729
+ this.get('session').on('ember-simple-auth:session-authentication-succeeded', function() {
730
+ _this.send('sessionAuthenticationSucceeded');
731
+ });
732
+ this.get('session').on('ember-simple-auth:session-authentication-failed', function(error) {
733
+ _this.send('sessionAuthenticationFailed', error);
734
+ });
735
+ this.get('session').on('ember-simple-auth:session-invalidation-succeeded', function() {
736
+ _this.send('sessionInvalidationSucceeded');
737
+ });
738
+ this.get('session').on('ember-simple-auth:session-invalidation-failed', function(error) {
739
+ _this.send('sessionInvalidationFailed', error);
740
+ });
741
+ },
742
+
743
+ actions: {
744
+ /**
745
+ This action triggers transition to the `authenticationRoute` specified in
746
+ [Ember.SimpleAuth.setup](#Ember-SimpleAuth-setup). It can be used in
747
+ templates as shown above. It is also triggered automatically by
748
+ [Ember.SimpleAuth.AuthenticatedRouteMixin](#Ember-SimpleAuth-AuthenticatedRouteMixin)
749
+ whenever a route that requries authentication is accessed but the session
750
+ is not currently authenticated.
751
+
752
+ __For an application that works without an authentication route (e.g.
753
+ because it opens a new window to handle authentication there), this is
754
+ the method to override, e.g.:__
755
+
756
+ ```javascript
757
+ App.ApplicationRoute = Ember.Route.extend(Ember.SimpleAuth.ApplicationRouteMixin, {
758
+ actions: {
759
+ authenticateSession: function() {
760
+ this.get('session').authenticate('app:authenticators:custom', {});
761
+ }
762
+ }
763
+ });
764
+ ```
765
+
766
+ @method actions.authenticateSession
767
+ */
768
+ authenticateSession: function() {
769
+ this.transitionTo(Configuration.authenticationRoute);
770
+ },
771
+
772
+ /**
773
+ This action is triggered whenever the session is successfully
774
+ authenticated. If there is a transition that was previously intercepted
775
+ by
776
+ [AuthenticatedRouteMixin#beforeModel](#Ember-SimpleAuth-AuthenticatedRouteMixin-beforeModel)
777
+ it will retry that. If there is no such transition, this action
778
+ transitions to the `routeAfterAuthentication` specified in
779
+ [Ember.SimpleAuth.setup](#Ember-SimpleAuth-setup).
780
+
781
+ @method actions.sessionAuthenticationSucceeded
782
+ */
783
+ sessionAuthenticationSucceeded: function() {
784
+ var attemptedTransition = this.get('session.attemptedTransition');
785
+ if (attemptedTransition) {
786
+ attemptedTransition.retry();
787
+ this.set('session.attemptedTransition', null);
788
+ } else {
789
+ this.transitionTo(Configuration.routeAfterAuthentication);
790
+ }
791
+ },
792
+
793
+ /**
794
+ This action is triggered whenever session authentication fails. The
795
+ `error` argument is the error object that the promise the authenticator
796
+ returns rejects with. (see
797
+ [Ember.SimpleAuth.Authenticators.Base#authenticate](#Ember-SimpleAuth-Authenticators-Base-authenticate)).
798
+
799
+ It can be overridden to display error messages etc.:
800
+
801
+ ```javascript
802
+ App.ApplicationRoute = Ember.Route.extend(Ember.SimpleAuth.ApplicationRouteMixin, {
803
+ actions: {
804
+ sessionAuthenticationFailed: function(error) {
805
+ this.controllerFor('application').set('loginErrorMessage', error.message);
806
+ }
807
+ }
808
+ });
809
+ ```
810
+
811
+ @method actions.sessionAuthenticationFailed
812
+ @param {any} error The error the promise returned by the authenticator rejects with, see [Ember.SimpleAuth.Authenticators.Base#authenticate](#Ember-SimpleAuth-Authenticators-Base-authenticate)
813
+ */
814
+ sessionAuthenticationFailed: function(error) {
815
+ },
816
+
817
+ /**
818
+ This action invalidates the session (see
819
+ [Ember.SimpleAuth.Session#invalidate](#Ember-SimpleAuth-Session-invalidate)).
820
+ If invalidation succeeds, it reloads the application (see
821
+ [Ember.SimpleAuth.ApplicationRouteMixin.sessionInvalidationSucceeded](#Ember-SimpleAuth-ApplicationRouteMixin-sessionInvalidationSucceeded)).
822
+
823
+ @method actions.invalidateSession
824
+ */
825
+ invalidateSession: function() {
826
+ this.get('session').invalidate();
827
+ },
828
+
829
+ /**
830
+ This action is invoked whenever the session is successfully invalidated.
831
+ It reloads the Ember.js application by redirecting the browser to the
832
+ application's root URL so that all in-memory data (such as Ember Data
833
+ stores etc.) is cleared. The root URL is automatically retrieved from the
834
+ Ember.js application's router (see
835
+ http://emberjs.com/guides/routing/#toc_specifying-a-root-url).
836
+
837
+ @method actions.sessionInvalidationSucceeded
838
+ */
839
+ sessionInvalidationSucceeded: function() {
840
+ window.location.replace(Configuration.applicationRootUrl);
841
+ },
842
+
843
+ /**
844
+ This action is invoked whenever session invalidation fails. This mainly
845
+ serves as an extension point to add custom behavior and does nothing by
846
+ default.
847
+
848
+ @method actions.sessionInvalidationFailed
849
+ */
850
+ sessionInvalidationFailed: function(error) {
851
+ },
852
+
853
+ /**
854
+ This action is invoked when an authorization error occurs (which is
855
+ usually __when a server responds with HTTP status 401__). It invalidates
856
+ the session and reloads the application (see
857
+ [Ember.SimpleAuth.ApplicationRouteMixin.sessionInvalidationSucceeded](#Ember-SimpleAuth-ApplicationRouteMixin-sessionInvalidationSucceeded)).
858
+
859
+ @method actions.authorizationFailed
860
+ */
861
+ authorizationFailed: function() {
862
+ this.get('session').invalidate();
863
+ },
864
+
865
+ /**
866
+ @method actions.error
867
+ @private
868
+ */
869
+ error: function(reason) {
870
+ if (reason.status === 401) {
871
+ this.send('authorizationFailed');
872
+ }
873
+ return true;
874
+ }
875
+ }
876
+ });
877
+
878
+ __exports__.ApplicationRouteMixin = ApplicationRouteMixin;
879
+ });
880
+ define("ember-simple-auth/mixins/authenticated_route_mixin",
881
+ ["exports"],
882
+ function(__exports__) {
883
+ "use strict";
884
+ var global = (typeof window !== 'undefined') ? window : {},
885
+ Ember = global.Ember;
886
+
887
+ /**
888
+ The mixin for routes that require the session to be authenticated in order to
889
+ be accessible. Including this mixin in a route automatically adds hooks that
890
+ enforce the session to be authenticated and redirect to the
891
+ `authenticationRoute` specified in
892
+ [Ember.SimpleAuth.setup](#Ember-SimpleAuth-setup) if it is not.
893
+
894
+ `Ember.SimpleAuth.AuthenticatedRouteMixin` performs the redirect in the
895
+ `beforeModel` method so that in all methods executed after that the session
896
+ is guaranteed to be authenticated. __If `beforeModel` is overridden, ensure
897
+ that the custom implementation calls `this._super(transition)`__ so that the
898
+ session enforcement code is actually executed.
899
+
900
+ @class AuthenticatedRouteMixin
901
+ @extends Ember.Mixin
902
+ @static
903
+ */
904
+ var AuthenticatedRouteMixin = Ember.Mixin.create({
905
+ /**
906
+ This method implements the enforcement of the session being authenticated.
907
+ If the session is not authenticated, the current transition will be aborted
908
+ and a redirect will be triggered to the `authenticationRoute` specified in
909
+ [Ember.SimpleAuth.setup](#Ember-SimpleAuth-setup). The method also saves
910
+ the intercepted transition so that it can be retried after the session has
911
+ been authenticated (see
912
+ [Ember.SimpleAuth.ApplicationRouteMixin#sessionAuthenticationSucceeded](#Ember-SimpleAuth-ApplicationRouteMixin-sessionAuthenticationSucceeded)).
913
+
914
+ @method beforeModel
915
+ @param {Transition} transition The transition that lead to this route
916
+ */
917
+ beforeModel: function(transition) {
918
+ if (!this.get('session.isAuthenticated')) {
919
+ transition.abort();
920
+ this.set('session.attemptedTransition', transition);
921
+ transition.send('authenticateSession');
922
+ }
923
+ }
924
+ });
925
+
926
+ __exports__.AuthenticatedRouteMixin = AuthenticatedRouteMixin;
927
+ });
928
+ define("ember-simple-auth/mixins/authentication_controller_mixin",
929
+ ["exports"],
930
+ function(__exports__) {
931
+ "use strict";
932
+ var global = (typeof window !== 'undefined') ? window : {},
933
+ Ember = global.Ember;
934
+
935
+ /**
936
+ The mixin for the controller that handles the `authenticationRoute` specified
937
+ in [Ember.SimpleAuth.setup](#Ember-SimpleAuth-setup)). It provides the
938
+ `authenticate` action that will authenticate the session with the configured
939
+ [Ember.SimpleAuth.AuthenticationControllerMixin#authenticatorFactory](#Ember-SimpleAuth-AuthenticationControllerMixin-authenticatorFactory)
940
+ when invoked.
941
+
942
+ @class AuthenticationControllerMixin
943
+ @extends Ember.Mixin
944
+ */
945
+ var AuthenticationControllerMixin = Ember.Mixin.create({
946
+ /**
947
+ The authenticator factory used to authenticate the session.
948
+
949
+ @property authenticatorFactory
950
+ @type String
951
+ @default null
952
+ */
953
+ authenticatorFactory: null,
954
+
955
+ actions: {
956
+ /**
957
+ This action will authenticate the session with the configured
958
+ [Ember.SimpleAuth.AuthenticationControllerMixin#authenticatorFactory](#Ember-SimpleAuth-AuthenticationControllerMixin-authenticatorFactory)
959
+ (see
960
+ Ember.SimpleAuth.Session#authenticate](#Ember-SimpleAuth-Session-authenticate)).
961
+
962
+ If authentication succeeds, this method triggers the
963
+ `sessionAuthenticationSucceeded` action (see
964
+ [Ember.SimpleAuth.ApplicationRouteMixin#sessionAuthenticationSucceeded](#Ember-SimpleAuth-ApplicationRouteMixin-sessionAuthenticationSucceeded)).
965
+ If authentication fails it triggers the `sessionAuthenticationFailed`
966
+ action (see
967
+ [Ember.SimpleAuth.ApplicationRouteMixin#sessionAuthenticationFailed](#Ember-SimpleAuth-ApplicationRouteMixin-sessionAuthenticationFailed)).
968
+
969
+ @method actions.authenticate
970
+ @param {Object} options Any options the auhtenticator needs to authenticate the session
971
+ */
972
+ authenticate: function(options) {
973
+ var _this = this;
974
+ this.get('session').authenticate(this.get('authenticatorFactory'), options);
975
+ }
976
+ }
977
+ });
978
+
979
+ __exports__.AuthenticationControllerMixin = AuthenticationControllerMixin;
980
+ });
981
+ define("ember-simple-auth/mixins/login_controller_mixin",
982
+ ["./authentication_controller_mixin","../authenticators/oauth2","exports"],
983
+ function(__dependency1__, __dependency2__, __exports__) {
984
+ "use strict";
985
+ var global = (typeof window !== 'undefined') ? window : {},
986
+ Ember = global.Ember;
987
+
988
+ var AuthenticationControllerMixin = __dependency1__.AuthenticationControllerMixin;
989
+ var OAuth2 = __dependency2__.OAuth2;
990
+
991
+ /**
992
+ A mixin to use with the controller that handles the `authenticationRoute`
993
+ specified in
994
+ [Ember.SimpleAuth.setup](#Ember-SimpleAuth-setup) if the used authentication
995
+ mechanism works with a login form that asks for user credentials. It provides
996
+ the `authenticate` action that will authenticate the session with the
997
+ configured authenticator factory when invoked. __This is a
998
+ specialization of
999
+ [Ember.SimpleAuth.AuthenticationControllerMixin](#Ember-SimpleAuth-AuthenticationControllerMixin).__
1000
+
1001
+ Accompanying the controller that this mixin is mixed in the application needs
1002
+ to have a `login` template with the fields `identification` and `password` as
1003
+ well as an actionable button or link that triggers the `authenticate` action,
1004
+ e.g.:
1005
+
1006
+ ```handlebars
1007
+ <form {{action 'authenticate' on='submit'}}>
1008
+ <label for="identification">Login</label>
1009
+ {{input id='identification' placeholder='Enter Login' value=identification}}
1010
+ <label for="password">Password</label>
1011
+ {{input id='password' placeholder='Enter Password' type='password' value=password}}
1012
+ <button type="submit">Login</button>
1013
+ </form>
1014
+ ```
1015
+
1016
+ @class LoginControllerMixin
1017
+ @extends Ember.SimpleAuth.AuthenticationControllerMixin
1018
+ */
1019
+ var LoginControllerMixin = Ember.Mixin.create(AuthenticationControllerMixin, {
1020
+ /**
1021
+ The authenticator factory used to authenticate the session.
1022
+
1023
+ @property authenticatorFactory
1024
+ @type String
1025
+ @default 'ember-simple-auth:authenticators:oauth2'
1026
+ */
1027
+ authenticatorFactory: 'ember-simple-auth:authenticators:oauth2',
1028
+
1029
+ actions: {
1030
+ /**
1031
+ This action will authenticate the session with the configured
1032
+ [Ember.SimpleAuth.LoginControllerMixin#authenticatorFactory](#Ember-SimpleAuth-LoginControllerMixin-authenticatorFactory)
1033
+ if both `identification` and `password` are non-empty. It passes both
1034
+ values to the authenticator.
1035
+
1036
+ _The action also resets the `password` property so sensitive data does not
1037
+ stay in memory for longer than necessary._
1038
+
1039
+ @method actions.authenticate
1040
+ */
1041
+ authenticate: function() {
1042
+ var data = this.getProperties('identification', 'password');
1043
+ if (!Ember.isEmpty(data.identification) && !Ember.isEmpty(data.password)) {
1044
+ this.set('password', null);
1045
+ this._super(data);
1046
+ }
1047
+ }
1048
+ }
1049
+ });
1050
+
1051
+ __exports__.LoginControllerMixin = LoginControllerMixin;
1052
+ });
1053
+ define("ember-simple-auth/session",
1054
+ ["./utils/flat_objects_are_equal","exports"],
1055
+ function(__dependency1__, __exports__) {
1056
+ "use strict";
1057
+ var global = (typeof window !== 'undefined') ? window : {},
1058
+ Ember = global.Ember;
1059
+
1060
+ var flatObjectsAreEqual = __dependency1__.flatObjectsAreEqual;
1061
+
1062
+ /**
1063
+ __The session provides access to the current authentication state as well as
1064
+ any data resolved by the authenticator__ (see
1065
+ [Ember.SimpleAuth.Authenticators.Base#authenticate](#Ember-SimpleAuth-Authenticators-Base-authenticate)).
1066
+ It is created when Ember.SimpleAuth is set up (see
1067
+ [Ember.SimpleAuth.setup](#Ember-SimpleAuth-setup)) and __injected into all
1068
+ models, controllers, routes and views so that all parts of the application
1069
+ can always access the current authentication state and other data__,
1070
+ depending on the used authenticator (see
1071
+ [Ember.SimpleAuth.Authenticators.Base](#Ember-SimpleAuth-Authenticators-Base))).
1072
+
1073
+ The session also provides methods to authenticate the user and to invalidate
1074
+ itself (see
1075
+ [Ember.SimpleAuth.Session#authenticate](#Ember-SimpleAuth-Session-authenticate),
1076
+ [Ember.SimpleAuth.Session#invaldiate](#Ember-SimpleAuth-Session-invaldiate)
1077
+ These methods are usually invoked through actions from routes or controllers.
1078
+
1079
+ @class Session
1080
+ @extends Ember.ObjectProxy
1081
+ @uses Ember.Evented
1082
+ */
1083
+ var Session = Ember.ObjectProxy.extend(Ember.Evented, {
1084
+ /**
1085
+ The authenticator factory used to authenticate the session. This is only
1086
+ set when the session is currently authenticated.
1087
+
1088
+ @property authenticatorFactory
1089
+ @type String
1090
+ @readOnly
1091
+ @default null
1092
+ */
1093
+ authenticatorFactory: null,
1094
+ /**
1095
+ The store used to persist session properties. This is assigned during
1096
+ Ember.SimpleAuth's setup and can be specified there
1097
+ (see [Ember.SimpleAuth.setup](#Ember-SimpleAuth-setup)).
1098
+
1099
+ @property store
1100
+ @type Ember.SimpleAuth.Stores.Base
1101
+ @readOnly
1102
+ @default null
1103
+ */
1104
+ store: null,
1105
+ /**
1106
+ Returns whether the session is currently authenticated.
1107
+
1108
+ @property isAuthenticated
1109
+ @type Boolean
1110
+ @readOnly
1111
+ @default false
1112
+ */
1113
+ isAuthenticated: false,
1114
+ /**
1115
+ @property attemptedTransition
1116
+ @private
1117
+ */
1118
+ attemptedTransition: null,
1119
+ /**
1120
+ @property content
1121
+ @private
1122
+ */
1123
+ content: {},
1124
+
1125
+ /**
1126
+ @method init
1127
+ @private
1128
+ */
1129
+ init: function() {
1130
+ var _this = this;
1131
+ this.bindToStoreEvents();
1132
+ var restoredContent = this.store.restore();
1133
+ var authenticatorFactory = restoredContent.authenticatorFactory;
1134
+ if (!!authenticatorFactory) {
1135
+ delete restoredContent.authenticatorFactory;
1136
+ this.container.lookup(authenticatorFactory).restore(restoredContent).then(function(content) {
1137
+ _this.setup(authenticatorFactory, content);
1138
+ }, function() {
1139
+ _this.store.clear();
1140
+ });
1141
+ } else {
1142
+ this.store.clear();
1143
+ }
1144
+ },
1145
+
1146
+ /**
1147
+ Authentices the session with an `authenticator` and appropriate `options`.
1148
+ __This delegates the actual authentication work to the `authenticator`__
1149
+ and handles the returned promise accordingly (see
1150
+ [Ember.SimpleAuth.Authenticators.Base#authenticate](#Ember-SimpleAuth-Authenticators-Base-authenticate)).
1151
+
1152
+ __This method returns a promise itself. A resolving promise indicates that
1153
+ the session was successfully authenticated__ while a rejecting promise
1154
+ indicates that authentication failed and the session remains
1155
+ unauthenticated.
1156
+
1157
+ @method authenticate
1158
+ @param {String} authenticatorFactory The authenticator factory to use as it is registered with Ember's container, see [Ember's API docs](http://emberjs.com/api/classes/Ember.Application.html#method_register)
1159
+ @param {Object} options The options to pass to the authenticator; depending on the type of authenticator these might be a set of credentials, a Facebook OAuth Token, etc.
1160
+ @return {Ember.RSVP.Promise} A promise that resolves when the session was authenticated successfully
1161
+ */
1162
+ authenticate: function(authenticatorFactory, options) {
1163
+ var _this = this;
1164
+ return new Ember.RSVP.Promise(function(resolve, reject) {
1165
+ _this.container.lookup(authenticatorFactory).authenticate(options).then(function(content) {
1166
+ _this.setup(authenticatorFactory, content, true);
1167
+ resolve();
1168
+ }, function(error) {
1169
+ _this.clear();
1170
+ _this.trigger('ember-simple-auth:session-authentication-failed', error);
1171
+ reject(error);
1172
+ });
1173
+ });
1174
+ },
1175
+
1176
+ /**
1177
+ Invalidates the session with the authenticator it is currently
1178
+ authenticated with (see
1179
+ [Ember.SimpleAuth.Session#authenticatorFactory](#Ember-SimpleAuth-Session-authenticatorFactory)).
1180
+ __This invokes the authenticator's `invalidate` method and handles the
1181
+ returned promise accordingly__ (see
1182
+ [Ember.SimpleAuth.Authenticators.Base#invalidate](#Ember-SimpleAuth-Authenticators-Base-invalidate)).
1183
+
1184
+ __This method returns a promise itself. A resolving promise indicates that
1185
+ the session was successfully invalidated__ while a rejecting promise
1186
+ indicates that the promise returned by the `authenticator` rejected and
1187
+ thus invalidation was cancelled. In that case the session remains
1188
+ authenticated.
1189
+
1190
+ @method invalidate
1191
+ @return {Ember.RSVP.Promise} A promise that resolves when the session was invalidated successfully
1192
+ */
1193
+ invalidate: function() {
1194
+ var _this = this;
1195
+ return new Ember.RSVP.Promise(function(resolve, reject) {
1196
+ var authenticator = _this.container.lookup(_this.authenticatorFactory);
1197
+ authenticator.invalidate(_this.content).then(function() {
1198
+ authenticator.off('ember-simple-auth:session-updated');
1199
+ _this.clear(true);
1200
+ resolve();
1201
+ }, function(error) {
1202
+ _this.trigger('ember-simple-auth:session-invalidation-failed', error);
1203
+ reject(error);
1204
+ });
1205
+ });
1206
+ },
1207
+
1208
+ /**
1209
+ @method setup
1210
+ @private
1211
+ */
1212
+ setup: function(authenticatorFactory, content, trigger) {
1213
+ trigger = !!trigger && !this.get('isAuthenticated');
1214
+ this.setProperties({
1215
+ isAuthenticated: true,
1216
+ authenticatorFactory: authenticatorFactory,
1217
+ content: content
1218
+ });
1219
+ this.bindToAuthenticatorEvents();
1220
+ var data = Ember.$.extend({ authenticatorFactory: authenticatorFactory }, this.content);
1221
+ if (!flatObjectsAreEqual(data, this.store.restore())) {
1222
+ this.store.clear();
1223
+ this.store.persist(data);
1224
+ }
1225
+ if (trigger) {
1226
+ this.trigger('ember-simple-auth:session-authentication-succeeded');
1227
+ }
1228
+ },
1229
+
1230
+ /**
1231
+ @method clear
1232
+ @private
1233
+ */
1234
+ clear: function(trigger) {
1235
+ trigger = !!trigger && this.get('isAuthenticated');
1236
+ this.setProperties({
1237
+ isAuthenticated: false,
1238
+ authenticatorFactory: null,
1239
+ content: {}
1240
+ });
1241
+ this.store.clear();
1242
+ if (trigger) {
1243
+ this.trigger('ember-simple-auth:session-invalidation-succeeded');
1244
+ }
1245
+ },
1246
+
1247
+ /**
1248
+ @method bindToAuthenticatorEvents
1249
+ @private
1250
+ */
1251
+ bindToAuthenticatorEvents: function() {
1252
+ var _this = this;
1253
+ var authenticator = this.container.lookup(this.authenticatorFactory);
1254
+ authenticator.off('ember-simple-auth:session-updated');
1255
+ authenticator.on('ember-simple-auth:session-updated', function(content) {
1256
+ _this.setup(_this.authenticatorFactory, content);
1257
+ });
1258
+ },
1259
+
1260
+ /**
1261
+ @method bindToStoreEvents
1262
+ @private
1263
+ */
1264
+ bindToStoreEvents: function() {
1265
+ var _this = this;
1266
+ this.store.on('ember-simple-auth:session-updated', function(content) {
1267
+ var authenticatorFactory = content.authenticatorFactory;
1268
+ if (!!authenticatorFactory) {
1269
+ delete content.authenticatorFactory;
1270
+ _this.container.lookup(authenticatorFactory).restore(content).then(function(content) {
1271
+ _this.setup(authenticatorFactory, content, true);
1272
+ }, function() {
1273
+ _this.clear(true);
1274
+ });
1275
+ } else {
1276
+ _this.clear(true);
1277
+ }
1278
+ });
1279
+ }
1280
+ });
1281
+
1282
+ __exports__.Session = Session;
1283
+ });
1284
+ define("ember-simple-auth/stores",
1285
+ ["./stores/base","./stores/cookie","./stores/local_storage","./stores/ephemeral","exports"],
1286
+ function(__dependency1__, __dependency2__, __dependency3__, __dependency4__, __exports__) {
1287
+ "use strict";
1288
+ var global = (typeof window !== 'undefined') ? window : {},
1289
+ Ember = global.Ember;
1290
+
1291
+ var Base = __dependency1__.Base;
1292
+ var Cookie = __dependency2__.Cookie;
1293
+ var LocalStorage = __dependency3__.LocalStorage;
1294
+ var Ephemeral = __dependency4__.Ephemeral;
1295
+
1296
+ var Stores = Ember.Namespace.create({
1297
+ Base: Base,
1298
+ Cookie: Cookie,
1299
+ LocalStorage: LocalStorage,
1300
+ Ephemeral: Ephemeral
1301
+ });
1302
+
1303
+ __exports__.Stores = Stores;
1304
+ });
1305
+ define("ember-simple-auth/stores/base",
1306
+ ["exports"],
1307
+ function(__exports__) {
1308
+ "use strict";
1309
+ var global = (typeof window !== 'undefined') ? window : {},
1310
+ Ember = global.Ember;
1311
+
1312
+ /**
1313
+ The base for all store types. __This serves as a starting point for
1314
+ implementing custom stores and must not be used directly.__
1315
+
1316
+ Stores may trigger the `'ember-simple-auth:session-updated'` event when
1317
+ any of the stored values change due to external actions (e.g. from another
1318
+ tab). The session listens to that event and will handle the changes
1319
+ accordingly. Whenever the event is triggered by the store, the session will
1320
+ forward all values as one object to its authenticator which might then
1321
+ invalidate the session (see
1322
+ [Ember.SimpleAuth.Authenticators.Base#restore](#Ember-SimpleAuth-Authenticators-Base-restore)).
1323
+
1324
+ @class Base
1325
+ @namespace Stores
1326
+ @extends Ember.Object
1327
+ @uses Ember.Evented
1328
+ */
1329
+ var Base = Ember.Object.extend(Ember.Evented, {
1330
+ /**
1331
+ Persists the `data` in the store.
1332
+
1333
+ `Ember.SimpleAuth.Stores.Base`'s implementation does nothing.
1334
+
1335
+ @method persist
1336
+ @param {Object} data The data to persist
1337
+ */
1338
+ persist: function(data) {
1339
+ },
1340
+
1341
+ /**
1342
+ Restores all data currently saved in the store as one plain object.
1343
+
1344
+ `Ember.SimpleAuth.Stores.Base`'s implementation always returns an empty
1345
+ plain Object.
1346
+
1347
+ @method restore
1348
+ @return {Object} The data currently persisted in the store.
1349
+ */
1350
+ restore: function() {
1351
+ return {};
1352
+ },
1353
+
1354
+ /**
1355
+ Clears the store.
1356
+
1357
+ `Ember.SimpleAuth.Stores.Base`'s implementation does nothing.
1358
+
1359
+ @method clear
1360
+ */
1361
+ clear: function() {
1362
+ }
1363
+ });
1364
+
1365
+ __exports__.Base = Base;
1366
+ });
1367
+ define("ember-simple-auth/stores/cookie",
1368
+ ["./base","../utils/flat_objects_are_equal","exports"],
1369
+ function(__dependency1__, __dependency2__, __exports__) {
1370
+ "use strict";
1371
+ var global = (typeof window !== 'undefined') ? window : {},
1372
+ Ember = global.Ember;
1373
+
1374
+ var Base = __dependency1__.Base;
1375
+ var flatObjectsAreEqual = __dependency2__.flatObjectsAreEqual;
1376
+
1377
+ /**
1378
+ Store that saves its data in session cookies.
1379
+
1380
+ __In order to keep multiple tabs/windows of your application in sync, this
1381
+ store has to periodically (every 500ms) check the cookies__ for changes as
1382
+ there are no events that notify of changes in cookies. The recommended
1383
+ alternative is
1384
+ [Ember.SimpleAuth.Stores.LocalStorage](#Ember-SimpleAuth-Stores-LocalStorage)
1385
+ that also persistently stores data but instead of cookies relies on the
1386
+ `localStorage` API and does not need to poll for external changes.
1387
+
1388
+ This store will trigger the `'ember-simple-auth:session-updated'` event when
1389
+ any of its cookies is changed from another tab or window.
1390
+
1391
+ @class Cookie
1392
+ @namespace Stores
1393
+ @extends Stores.Base
1394
+ */
1395
+ var Cookie = Base.extend({
1396
+ /**
1397
+ The prefix to use for the store's cookie names so they can be distinguished
1398
+ from other cookies.
1399
+
1400
+ @property cookieNamePrefix
1401
+ @type String
1402
+ @default 'ember_simple_auth:'
1403
+ */
1404
+ cookieNamePrefix: 'ember_simple_auth:',
1405
+ /**
1406
+ @property _secureCookies
1407
+ @private
1408
+ */
1409
+ _secureCookies: window.location.protocol === 'https:',
1410
+ /**
1411
+ @property _syncDataTimeout
1412
+ @private
1413
+ */
1414
+ _syncDataTimeout: null,
1415
+
1416
+ /**
1417
+ @method init
1418
+ @private
1419
+ */
1420
+ init: function() {
1421
+ this.syncData();
1422
+ },
1423
+
1424
+ /**
1425
+ Persists the `data` in session cookies.
1426
+
1427
+ @method persist
1428
+ @param {Object} data The data to persist
1429
+ */
1430
+ persist: function(data) {
1431
+ for (var property in data) {
1432
+ this.write(property, data[property], null);
1433
+ }
1434
+ this._lastData = this.restore();
1435
+ },
1436
+
1437
+ /**
1438
+ Restores all data currently saved in the session cookies identified by the
1439
+ `cookieNamePrefix` as one plain object.
1440
+
1441
+ @method restore
1442
+ @return {Object} All data currently persisted in the session cookies
1443
+ */
1444
+ restore: function() {
1445
+ var _this = this;
1446
+ var data = {};
1447
+ this.knownCookies().forEach(function(cookie) {
1448
+ data[cookie] = _this.read(cookie);
1449
+ });
1450
+ return data;
1451
+ },
1452
+
1453
+ /**
1454
+ Clears the store by deleting all session cookies prefixed with the
1455
+ `cookieNamePrefix`.
1456
+
1457
+ @method clear
1458
+ */
1459
+ clear: function() {
1460
+ var _this = this;
1461
+ this.knownCookies().forEach(function(cookie) {
1462
+ _this.write(cookie, null, (new Date(0)).toGMTString());
1463
+ });
1464
+ this._lastData = null;
1465
+ },
1466
+
1467
+ /**
1468
+ @method read
1469
+ @private
1470
+ */
1471
+ read: function(name) {
1472
+ var value = document.cookie.match(new RegExp(this.cookieNamePrefix + name + '=([^;]+)')) || [];
1473
+ return decodeURIComponent(value[1] || '');
1474
+ },
1475
+
1476
+ /**
1477
+ @method write
1478
+ @private
1479
+ */
1480
+ write: function(name, value, expiration) {
1481
+ var expires = Ember.isEmpty(expiration) ? '' : '; expires=' + expiration;
1482
+ var secure = !!this._secureCookies ? ';secure' : '';
1483
+ document.cookie = this.cookieNamePrefix + name + '=' + encodeURIComponent(value) + expires + secure;
1484
+ },
1485
+
1486
+ /**
1487
+ @method knownCookies
1488
+ @private
1489
+ */
1490
+ knownCookies: function() {
1491
+ var _this = this;
1492
+ return Ember.A(document.cookie.split(/[=;\s]+/)).filter(function(element) {
1493
+ return new RegExp('^' + _this.cookieNamePrefix).test(element);
1494
+ }).map(function(cookie) {
1495
+ return cookie.replace(_this.cookieNamePrefix, '');
1496
+ });
1497
+ },
1498
+
1499
+ /**
1500
+ @method syncData
1501
+ @private
1502
+ */
1503
+ syncData: function() {
1504
+ var data = this.restore();
1505
+ if (!flatObjectsAreEqual(data, this._lastData)) {
1506
+ this._lastData = data;
1507
+ this.trigger('ember-simple-auth:session-updated', data);
1508
+ }
1509
+ if (!Ember.testing) {
1510
+ Ember.run.cancel(this._syncDataTimeout);
1511
+ this._syncDataTimeout = Ember.run.later(this, this.syncData, 500);
1512
+ }
1513
+ }
1514
+ });
1515
+
1516
+ __exports__.Cookie = Cookie;
1517
+ });
1518
+ define("ember-simple-auth/stores/ephemeral",
1519
+ ["./base","exports"],
1520
+ function(__dependency1__, __exports__) {
1521
+ "use strict";
1522
+ var global = (typeof window !== 'undefined') ? window : {},
1523
+ Ember = global.Ember;
1524
+
1525
+ var Base = __dependency1__.Base;
1526
+
1527
+ /**
1528
+ Store that saves its data in memory and thus __is not actually persistent__.
1529
+ This store is mainly useful for testing.
1530
+
1531
+ @class Ephemeral
1532
+ @namespace Stores
1533
+ @extends Stores.Base
1534
+ */
1535
+ var Ephemeral = Base.extend({
1536
+ /**
1537
+ @method init
1538
+ @private
1539
+ */
1540
+ init: function() {
1541
+ this.clear();
1542
+ },
1543
+
1544
+ /**
1545
+ Persists the `data`.
1546
+
1547
+ @method persist
1548
+ @param {Object} data The data to persist
1549
+ */
1550
+ persist: function(data) {
1551
+ this._data = Ember.$.extend(data, this._data);
1552
+ },
1553
+
1554
+ /**
1555
+ Restores all data currently saved as one plain object.
1556
+
1557
+ @method restore
1558
+ @return {Object} All data currently persisted
1559
+ */
1560
+ restore: function() {
1561
+ return Ember.$.extend({}, this._data);
1562
+ },
1563
+
1564
+ /**
1565
+ Clears the store.
1566
+
1567
+ @method clear
1568
+ */
1569
+ clear: function() {
1570
+ delete this._data;
1571
+ this._data = {};
1572
+ }
1573
+ });
1574
+
1575
+ __exports__.Ephemeral = Ephemeral;
1576
+ });
1577
+ define("ember-simple-auth/stores/local_storage",
1578
+ ["./base","../utils/flat_objects_are_equal","exports"],
1579
+ function(__dependency1__, __dependency2__, __exports__) {
1580
+ "use strict";
1581
+ var global = (typeof window !== 'undefined') ? window : {},
1582
+ Ember = global.Ember;
1583
+
1584
+ var Base = __dependency1__.Base;
1585
+ var flatObjectsAreEqual = __dependency2__.flatObjectsAreEqual;
1586
+
1587
+ /**
1588
+ Store that saves its data in the browser's `localStorage`.
1589
+
1590
+ This store will trigger the `'ember-simple-auth:session-updated'` event when
1591
+ any of the keys it manages is changed from another tab or window.
1592
+
1593
+ @class LocalStorage
1594
+ @namespace Stores
1595
+ @extends Stores.Base
1596
+ */
1597
+ var LocalStorage = Base.extend({
1598
+ /**
1599
+ The prefix to use for the store's keys so they can be distinguished from
1600
+ others.
1601
+
1602
+ @property keyPrefix
1603
+ @type String
1604
+ @default 'ember_simple_auth:'
1605
+ */
1606
+ keyPrefix: 'ember_simple_auth:',
1607
+
1608
+ /**
1609
+ @property _triggerChangeEventTimeout
1610
+ @private
1611
+ */
1612
+ _triggerChangeEventTimeout: null,
1613
+
1614
+ /**
1615
+ @method init
1616
+ @private
1617
+ */
1618
+ init: function() {
1619
+ this.bindToStorageEvents();
1620
+ },
1621
+
1622
+ /**
1623
+ Persists the `data` in the `localStorage`.
1624
+
1625
+ @method persist
1626
+ @param {Object} data The data to persist
1627
+ */
1628
+ persist: function(data) {
1629
+ for (var property in data) {
1630
+ var key = this.buildStorageKey(property);
1631
+ localStorage.setItem(key, data[property]);
1632
+ }
1633
+ this._lastData = this.restore();
1634
+ },
1635
+
1636
+ /**
1637
+ Restores all data currently saved in the `localStorage` identified by the
1638
+ `keyPrefix` as one plain object.
1639
+
1640
+ @method restore
1641
+ @return {Object} All data currently persisted in the `localStorage`
1642
+ */
1643
+ restore: function() {
1644
+ var _this = this;
1645
+ var data = {};
1646
+ this.knownKeys().forEach(function(key) {
1647
+ var originalKey = key.replace(_this.keyPrefix, '');
1648
+ data[originalKey] = localStorage.getItem(key);
1649
+ });
1650
+ return data;
1651
+ },
1652
+
1653
+ /**
1654
+ Clears the store by deleting all `localStorage` keys prefixed with the
1655
+ `keyPrefix`.
1656
+
1657
+ @method clear
1658
+ */
1659
+ clear: function() {
1660
+ this.knownKeys().forEach(function(key) {
1661
+ localStorage.removeItem(key);
1662
+ });
1663
+ this._lastData = null;
1664
+ },
1665
+
1666
+ /**
1667
+ @method buildStorageKey
1668
+ @private
1669
+ */
1670
+ buildStorageKey: function(property) {
1671
+ return this.keyPrefix + property;
1672
+ },
1673
+
1674
+ /**
1675
+ @method knownKeys
1676
+ @private
1677
+ */
1678
+ knownKeys: function(callback) {
1679
+ var keys = Ember.A([]);
1680
+ for (var i = 0, l = localStorage.length; i < l; i++) {
1681
+ var key = localStorage.key(i);
1682
+ if (key.indexOf(this.keyPrefix) === 0) {
1683
+ keys.push(key);
1684
+ }
1685
+ }
1686
+ return keys;
1687
+ },
1688
+
1689
+ /**
1690
+ @method bindToStorageEvents
1691
+ @private
1692
+ */
1693
+ bindToStorageEvents: function() {
1694
+ var _this = this;
1695
+ Ember.$(window).bind('storage', function(e) {
1696
+ var data = _this.restore();
1697
+ if (!flatObjectsAreEqual(data, _this._lastData)) {
1698
+ _this._lastData = data;
1699
+ Ember.run.cancel(_this._triggerChangeEventTimeout);
1700
+ _this._triggerChangeEventTimeout = Ember.run.next(_this, function() {
1701
+ this.trigger('ember-simple-auth:session-updated', data);
1702
+ });
1703
+ }
1704
+ });
1705
+ }
1706
+ });
1707
+
1708
+ __exports__.LocalStorage = LocalStorage;
1709
+ });
1710
+ define("ember-simple-auth/utils/flat_objects_are_equal",
1711
+ ["exports"],
1712
+ function(__exports__) {
1713
+ "use strict";
1714
+ var flatObjectsAreEqual = function(a, b) {
1715
+ function sortObject(object) {
1716
+ var array = [];
1717
+ for (var property in object) {
1718
+ array.push([property, object[property]]);
1719
+ }
1720
+ return array.sort(function(a, b) {
1721
+ if (a[0] < b[0]) {
1722
+ return -1;
1723
+ } else if (a[0] > b[0]) {
1724
+ return 1;
1725
+ } else {
1726
+ return 0;
1727
+ }
1728
+ });
1729
+ }
1730
+ return JSON.stringify(sortObject(a)) === JSON.stringify(sortObject(b));
1731
+ };
1732
+
1733
+ __exports__.flatObjectsAreEqual = flatObjectsAreEqual;
1734
+ });
1735
+ define("ember-simple-auth/utils/is_secure_url",
1736
+ ["exports"],
1737
+ function(__exports__) {
1738
+ "use strict";
1739
+ var isSecureUrl = function(url) {
1740
+ var link = document.createElement('a');
1741
+ link.href = location;
1742
+ link.href = link.href;
1743
+ return link.protocol == 'https:';
1744
+ };
1745
+
1746
+ __exports__.isSecureUrl = isSecureUrl;
1747
+ });
1748
+ global.Ember.SimpleAuth = requireModule('ember-simple-auth');
1749
+ })((typeof global !== 'undefined') ? global : window);