travis-web/assets/scripts/app/auth.coffee
Piotr Sarnacki 3b1cd4f5c4 Bring back afterSignIn and afterSignIn as actions sent to controller
It seems that there is more use cases to cover with this behaviour, for
example when someone enters /auth directly and logs in from there.
2014-05-28 10:22:48 +02:00

138 lines
4.5 KiB
CoffeeScript

Auth = Ember.Object.extend
state: "signed-out"
receivingEnd: "#{location.protocol}//#{location.host}"
init: ->
window.addEventListener('message', (e) => @receiveMessage(e))
endpoint: (->
@container.lookup('application:main').config.api_endpoint
).property(),
signOut: ->
Travis.storage.removeItem('travis.user')
Travis.storage.removeItem('travis.token')
Travis.sessionStorage.clear()
@set('state', 'signed-out')
@set('user', undefined)
if user = @get('currentUser')
user.unload()
@set('currentUser', null)
@sendToApp('afterSignOut')
signIn: (data) ->
if data
@autoSignIn(data)
else
@set('state', 'signing-in')
url = "#{@get('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)
@set('currentUser', user)
@set('state', 'signed-in')
Travis.trigger('user:signed_in', data.user)
@sendToApp('afterSignIn')
refreshUserData: (user) ->
Travis.ajax.get "/users/#{user.id}", (data) =>
Travis.loadOrMerge(Travis.User, data.user)
# if user is still signed in, update saved data
if @get('signedIn')
data.user.token = user.token
@storeData(data, Travis.sessionStorage)
@storeData(data, Travis.storage)
, (data, status, xhr) =>
@signOut() if xhr.status == 401
signedIn: (->
@get('state') == 'signed-in'
).property('state')
signedOut: (->
@get('state') == 'signed-out'
).property('state')
signingIn: (->
@get('state') == 'signing-in'
).property('state')
storeData: (data, storage) ->
storage.setItem('travis.token', data.token) if data.token
storage.setItem('travis.user', JSON.stringify(data.user))
loadUser: (user) ->
Travis.loadOrMerge(Travis.User, user)
user = Travis.User.find(user.id)
user.get('permissions')
user
receiveMessage: (event) ->
if event.origin == @expectedOrigin()
if event.data == 'redirect'
window.location = "#{@get('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: ->
endpoint = @get('endpoint')
if endpoint[0] == '/' then @receivingEnd else endpoint
sendToApp: (name) ->
# TODO: this is an ugly solution, we need to do one of 2 things:
# * find a way to check if we can already send an event to remove try/catch
# * remove afterSignIn and afterSignOut events by replacing them in a more
# straightforward code - we can do what's needed on a routes/controller level
# as a direct response to either manual sign in or autoSignIn (right now
# we treat both cases behave the same in terms of sent events which I think
# makes it more complicated than it should be).
controller = @container.lookup('controller:auth')
try
controller.send(name)
catch error
unless error.message =~ /Can't trigger action/
throw error
Ember.onLoad 'Ember.Application', (Application) ->
Application.initializer
name: "auth",
initialize: (container, application) ->
application.register 'auth:main', Auth
application.inject('route', 'auth', 'auth:main')
application.inject('controller', 'auth', 'auth:main')
application.inject('application', 'auth', 'auth:main')