travis-web/assets/scripts/app/auth.coffee
Piotr Sarnacki 0d12176239 Don't error out if router is not yet setup
When router is not set up yet sending events to it will fail. If that's
the case, we can just swallow the error, because afterSignIn will take
effect only if we are already in some state in the router.
2013-06-05 12:43:27 +02:00

120 lines
4.2 KiB
CoffeeScript

@Travis.Auth = Ember.Object.extend
state: "signed-out"
receivingEnd: "#{location.protocol}//#{location.host}"
init: ->
window.addEventListener('message', (e) => @receiveMessage(e))
signOut: ->
Travis.storage.removeItem('travis.locale')
Travis.storage.removeItem('travis.user')
Travis.storage.removeItem('travis.token')
Travis.sessionStorage.clear()
Travis.setLocale Travis.default_locale
@set('state', 'signed-out')
@set('user', undefined)
if user = Travis.__container__.lookup('controller:currentUser').get('content')
if user.get('stateManager.currentPath') == 'rootState.loaded.updated.uncommitted'
user.send('rollback')
user.unloadRecord()
Travis.__container__.lookup('controller:currentUser').set('content', null)
if router = Travis.__container__.lookup('router:main')
router.send('afterSignOut')
signIn: (data) ->
if data
@autoSignIn(data)
else
@set('state', 'signing-in')
url = "#{@endpoint}/auth/post_message?origin=#{@receivingEnd}"
$('<iframe id="auth-frame" />').hide().appendTo('body').attr('src', url)
autoSignIn: (data) ->
data ||= @userDataFrom(Travis.sessionStorage) || @userDataFrom(Travis.storage)
@setData(data) if data
userDataFrom: (storage) ->
userJSON = storage.getItem('travis.user')
user = JSON.parse userJSON if userJSON?
user = user.user if user?.user
token = storage.getItem('travis.token')
if user && token && @validateUser(user)
{ user: user, token: token }
else
# console.log('dropping user, no token') if token?
storage.removeItem('travis.user')
storage.removeItem('travis.token')
null
validateUser: (user) ->
@validateHas('id', user) && @validateHas('login', user) && @validateHas('token', user) && @validateHas('correct_scopes', user) && user.correct_scopes
validateHas: (field, user) ->
if user[field]
true
else
# console.log("discarding user data, lacks #{field}")
false
setData: (data) ->
@storeData(data, Travis.sessionStorage)
@storeData(data, Travis.storage) unless @userDataFrom(Travis.storage)
user = @loadUser(data.user)
# TODO: we should not use __container__ directly, how to do it better?
# A good answer seems to do auth in context of controller.
Travis.__container__.lookup('controller:currentUser').set('content', user)
@set('state', 'signed-in')
Travis.setLocale(data.user.locale || Travis.default_locale)
Travis.trigger('user:signed_in', data.user)
if router = Travis.__container__.lookup('router:main')
path = @readAfterSignInPath()
Ember.run.next =>
try
router.send('afterSignIn', path)
catch e
throw e unless e =~ /There are no active handlers/
@refreshUserData(data.user)
refreshUserData: (user) ->
Travis.ajax.get "/users/#{user.id}", (data) =>
Travis.store.loadIncomplete(Travis.User, data.user)
# if user is still signed in, update saved data
if @signedIn()
data.user.token = user.token
@storeData(data, Travis.sessionStorage)
@storeData(data, Travis.storage)
signedIn: ->
@get('state') == 'signed-in'
storeData: (data, storage) ->
storage.setItem('travis.token', data.token) if data.token
storage.setItem('travis.user', JSON.stringify(data.user))
loadUser: (user) ->
store = @app.store
store.load(Travis.User, user.id, user)
user = store.find(Travis.User, user.id)
user.get('permissions')
user
storeAfterSignInPath: (path) ->
Travis.sessionStorage.setItem('travis.after_signin_path', path)
readAfterSignInPath: ->
path = Travis.sessionStorage.getItem('travis.after_signin_path')
Travis.sessionStorage.removeItem('travis.after_signin_path')
path
receiveMessage: (event) ->
if event.origin == @expectedOrigin()
if event.data == 'redirect'
window.location = "#{@endpoint}/auth/handshake?redirect_uri=#{location}"
else if event.data.user?
event.data.user.token = event.data.travis_token if event.data.travis_token
@setData(event.data)
expectedOrigin: ->
if @endpoint[0] == '/' then @receivingEnd else @endpoint