
Sign out should occur in the route after the request is performed. Additionally, the error from refreshUserData needs to be handled in route in order to not propagate to parent routes.
163 lines
5.1 KiB
CoffeeScript
163 lines
5.1 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}").then (data) =>
|
|
if data.user.correct_scopes && false
|
|
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
|
|
return Ember.RSVP.Promise.reject()
|
|
else
|
|
return Ember.RSVP.Promise.resolve()
|
|
|
|
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`
|