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 +7 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/lib/ember_simple_auth/rails.rb +8 -0
- data/lib/ember_simple_auth/rails/version.rb +5 -0
- data/vendor/assets/javascripts/ember-simple-auth.js +1749 -0
- metadata +91 -0
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,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);
|