travis-web/app/utils/auth.coffee
2015-07-15 14:02:16 +02:00

163 lines
5.0 KiB
CoffeeScript

`import config from 'travis/config/environment'`
`import Ajax from 'travis/utils/ajax'`
Auth = Ember.Object.extend
state: "signed-out"
receivingEnd: "#{location.protocol}//#{location.host}"
init: ->
window.addEventListener('message', (e) => @receiveMessage(e))
token: ->
Travis.sessionStorage.getItem('travis.token')
endpoint: (->
config.apiEndpoint
).property(),
signOut: ->
@storage.removeItem('travis.user')
@storage.removeItem('travis.token')
@sessionStorage.clear()
@set('state', 'signed-out')
@set('user', undefined)
if user = @get('currentUser')
@store.unloadAll('user')
@set('currentUser', null)
@sendToApp('afterSignOut')
Travis.trigger('user:signed_out')
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(@sessionStorage) || @userDataFrom(@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']
isTravisBecome = sessionStorage.getItem('travis.become')
unless isTravisBecome
fieldsToValidate.push 'correct_scopes'
if config.pro
fieldsToValidate.push 'channels'
fieldsToValidate.every( (field) => @validateHas(field, user) ) && (isTravisBecome || user.correct_scopes)
validateHas: (field, user) ->
if user[field]
true
else
# console.log("discarding user data, lacks #{field}")
false
setData: (data) ->
@storeData(data, @sessionStorage)
@storeData(data, @storage) unless @userDataFrom(@storage)
user = @loadUser(data.user)
@set('currentUser', user)
@set('state', 'signed-in')
Travis.trigger('user:signed_in', data.user)
@sendToApp('afterSignIn')
refreshUserData: (user) ->
unless user
if data = @userDataFrom(@sessionStorage) || @userDataFrom(@storage)
user = data.user
if user
Ajax.get "/users/#{user.id}", (data) =>
if data.user.correct_scopes
userRecord = @loadUser(data.user)
userRecord.get('permissions')
# if user is still signed in, update saved data
if @get('signedIn')
data.user.token = user.token
@storeData(data, @sessionStorage)
@storeData(data, @storage)
Travis.trigger('user:refreshed', data.user)
else
@signOut()
, (status, xhr) =>
@signOut() if status == 403 || status == 404
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) ->
@store.pushPayload(users: [user])
@store.recordForId('user', user.id)
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).
router = @container.lookup('router:main')
try
router.send(name)
catch error
unless error.message =~ /Can't trigger action/
throw error
userName: (->
@get('currentUser.name') || @get('currentUser.login')
).property('currentUser.login', 'currentUser.name')
gravatarUrl: (->
"#{location.protocol}//www.gravatar.com/avatar/#{@get('currentUser.gravatarId')}?s=48&d=mm"
).property('currentUser.gravatarId')
permissions: Ember.computed.alias('currentUser.permissions')
`export default Auth`