143 lines
4.6 KiB
CoffeeScript
143 lines
4.6 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) ->
|
|
fieldsToValidate = ['id', 'login', 'token', 'correct_scopes']
|
|
if Travis.config.pro
|
|
fieldsToValidate.push 'channels'
|
|
|
|
fieldsToValidate.every( (field) => @validateHas(field, 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.match(/^https?:\/\/[^\/]*/)[0]
|
|
|
|
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')
|