travis-web/assets/scripts/app/auth.coffee
Piotr Sarnacki 1238caf318 Fix signing out on failed try to update user data
A while ago I introduced a change to auth code which signs out user on
failed try to get user data. The problem with it was it signed out on
all kind of errors, like network error. I changed the code to log out on
401 status, but I haven't tested it properly, we actually return 403 on
unauthenticated queries for user data.
2014-06-23 15:15:40 +02:00

139 lines
4.5 KiB
CoffeeScript

window.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(data.user)
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)
, (status, xhr) =>
@signOut() if status == 403
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')