
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.
139 lines
4.5 KiB
CoffeeScript
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')
|