ducky/web
2015-07-07
Parent:13d27b50d79e
ducky/web/src/models/me.js
Implement subscriptions. Create a Subscription model and a Subscriptions collection, and attach them to the app context. Add a helper to our Profile model to retrieve the Subscription of that model. Still not sure this should be on the Profile--wouldn't it be better on the Me model? Isn't that generally where we would need it?
1 import Model from 'ampersand-model'
2 import Sync from 'ampersand-sync'
3 import qs from 'qs'
4 import config from '../config'
5 import isObject from 'lodash.isobject'
6 import jwtDecode from 'jwt-decode'
7 import debounce from 'lodash.debounce'
9 export default Model.extend({
10 url: config.urlBase + '/auth/token',
11 ajaxConfig: {
12 headers: {
13 'Content-Type': 'application/x-www-form-urlencoded',
14 'Authorization': 'Basic ' + btoa(config.clientID + ':' + config.clientSecret),
15 }
16 },
18 props: {
19 access_token: 'string',
20 refresh_token: 'string',
21 expires_in: 'int',
22 token_created: 'date',
23 profileID: 'string',
24 email: 'string',
25 },
27 profile() {
28 return new Promise((resolve, reject) => {
29 app.profiles.getOrFetch(this.profileID, (err, model) => {
30 if (err) {
31 reject(err)
32 } else {
33 resolve(model)
34 }
35 })
36 })
37 },
39 derived: {
40 loggedIn () {
41 return !!this.access_token
42 },
43 tokenExpires () {
44 let d = this.token_created
45 d.setSeconds(d.getSeconds() + this.expires_in)
46 return d
47 },
48 needsRefresh () {
49 return !!this.refresh_token && (new Date() >= this.tokenExpires)
50 },
51 },
53 initialize() {
54 this.debouncedWriteToCache = debounce(this.writeToCache, 250)
55 },
57 login (email, password) {
58 let options = {
59 data: qs.stringify({
60 'username': email,
61 'password': password,
62 'grant_type': 'password',
63 'scope': 'subscriptions',
64 }),
65 }
66 let moc = this
67 options.success = function(resp) {
68 if (!resp.access_token) {
69 return false
70 }
71 let serverAttrs = moc.parse(resp, options)
72 serverAttrs.token_created = new Date()
73 if (options.wait) serverAttrs = assign({}, serverAttrs)
74 if (isObject(serverAttrs) && !moc.set(serverAttrs, options)) {
75 return false
76 }
77 const token = jwtDecode(moc.access_token)
78 moc.profileID = token.sub
79 moc.email = email
80 moc.trigger('sync', moc, resp, options)
81 }
82 options.error = function(resp) {
83 moc.trigger('error', moc, resp, options)
84 }
85 let sync = Sync('create', moc, options)
86 },
88 writeToCache () {
89 const data = JSON.stringify(this)
90 localStorage.setItem('me', data)
91 },
93 load () {
94 let moc = this
95 const resp = localStorage.getItem('me')
96 if (resp) {
97 const loaded = this.parse(JSON.parse(resp))
98 moc.set(loaded, {silent: true})
99 }
100 return this
101 },
103 logout () {
104 localStorage.removeItem('me')
105 },
107 })