Commit c07ea769 authored by Randall Leeds's avatar Randall Leeds

Switch to BrowserID "Goldilocks" API

Rather than support the fiddly matrix of possiblities when a user
may not have a session with the application but has a session with
the identity provider, borrow the newer "Goldilocks" API design from
upstream where the application is responsible for its own session
and the BrowserId implementation is less stateful.
parent 30d2c5dd
......@@ -14,12 +14,11 @@ configure = [
identityProvider.checkAuthentication = [
'$q', 'session',
($q, session) ->
(authCheck = $q.defer())
.promise.then do ->
(authCheck = $q.defer()).promise.then do ->
session.load().$promise.then (data) ->
authCheck.resolve
certificate: data.csrf
userid: data.userid
if data.userid then authCheck.resolve data.csrf
else authCheck.reject 'no session'
, -> authCheck.reject 'request failure'
]
identityProvider.forgetAuthentication = [
......@@ -31,16 +30,10 @@ configure = [
identityProvider.requestAuthentication = [
'$q', '$rootScope',
($q, $rootScope) ->
if authCheck then authCheck.reject()
(authCheck = $q.defer())
.promise.finally do ->
(authCheck = $q.defer()).promise.finally do ->
$rootScope.$on 'auth', (event, err, data) ->
if err
authCheck.reject(err)
else
authCheck.resolve
certificate: data.csrf
userid: data.userid
if err then authCheck.reject err
else authCheck.resolve data.csrf
]
]
......
......@@ -27,25 +27,16 @@ authorizeAction = (action, annotation, user) ->
class AppController
this.$inject = [
'$location', '$q', '$route', '$scope', '$timeout',
'annotator', 'flash', 'identity', 'socket', 'streamfilter',
'annotator', 'flash', 'identity', 'session', 'socket', 'streamfilter',
'documentHelpers', 'drafts'
]
constructor: (
$location, $q, $route, $scope, $timeout
annotator, flash, identity, socket, streamfilter,
annotator, flash, identity, session, socket, streamfilter,
documentHelpers, drafts
) ->
{plugins, host, providers} = annotator
# Verified user id.
# Undefined means we don't track the session, but the identity module will
# tell us the state of the session. A null value means that the session
# has been checked and it was found that there is no user logged in.
loggedInUser = undefined
# Resolved once the API service has been discovered.
storeReady = $q.defer()
applyUpdates = (action, data) ->
"""Update the application with new data from the websocket."""
return unless data?.length
......@@ -62,30 +53,6 @@ class AppController
plugins.Store?.unregisterAnnotation(annotation)
annotator.deleteAnnotation(annotation)
initIdentity = (persona) ->
"""Initialize identity callbacks."""
# Store the argument as the claimed user id.
claimedUser = persona
# Convert it to the format used by persona.
if claimedUser then claimedUser = claimedUser.replace(/^acct:/, '')
if claimedUser is loggedInUser
if loggedInUser is undefined
# This is the first execution.
# Configure the identity callbacks and the initial user id claim.
identity.watch
loggedInUser: claimedUser
onlogin: (assertion) ->
onlogin(assertion)
onlogout: ->
onlogout()
else if drafts.discard()
if claimedUser
identity.request()
else
identity.logout()
initStore = ->
"""Initialize the storage component."""
Store = plugins.Store
......@@ -198,9 +165,6 @@ class AppController
_dfdSock.promise
oncancel = ->
loggedInuser = null
onlogin = (assertion) ->
# Configure the Auth plugin with the issued assertion as refresh token.
annotator.addPlugin 'Auth',
......@@ -217,7 +181,7 @@ class AppController
update: [token.userId]
delete: [token.userId]
admin: [token.userId]
loggedInUser = token.userId.replace /^acct:/, ''
$scope.persona = token.userId
reset()
onlogout = ->
......@@ -231,9 +195,18 @@ class AppController
plugins.Permissions?.destroy()
delete plugins.Permissions
loggedInUser = null
$scope.persona = null
reset()
onready = ->
$scope.$evalAsync ->
$scope.persona ?= null
oncancel = ->
$scope.$evalAsync ->
flash 'info', 'Sign in canceled.'
$scope.dialog.visible = false
reset = ->
# Do not rely on the identity service to invoke callbacks within an
# angular digest cycle.
......@@ -244,14 +217,6 @@ class AppController
for draft in drafts.all()
annotator.publish 'beforeAnnotationCreated', draft
# Convert the verified user id to the format used by the API.
persona = loggedInUser
if persona then persona = "acct:#{persona}"
# Ensure it is synchronized on the scope.
# Without this, failed identity changes will remain on the scope.
$scope.persona = persona
# Reload services
storeReady.promise.then -> initStore()
initUpdater()
......@@ -261,7 +226,7 @@ class AppController
angular.extend annotator.options.Store, options
storeReady.resolve()
$scope.$watch 'persona', initIdentity
identity.watch {onlogin, onlogout, onready}
$scope.$watch 'socialView.name', (newValue, oldValue) ->
return if newValue is oldValue
......
......@@ -57,42 +57,8 @@ identityProvider = ->
'$injector', '$q',
($injector, $q) ->
provider = this
loggedInUser = undefined
oncancel = null
onlogin = null
onlogout = null
onmatch = null
onready = null
invokeCallbacks = (grant={}) ->
{userid, certificate} = grant
userid or= null
# Fire callbacks as appropriate.
# Consult the state matrix in the `navigator.id.watch` documentation.
# https://developer.mozilla.org/en-US/docs/Web/API/navigator.id.watch
if loggedInUser is null
if userid
loggedInUser = userid
onlogin?(certificate)
else
onmatch?()
else if loggedInUser
if userid
if loggedInUser is userid
onmatch?()
else
loggedInUser = userid
onlogin?(certificate)
else
loggedInUser = null
onlogout?()
else
if userid
loggedInUser = userid
onlogin?(certificate)
else
loggedInUser = null
onlogout?()
###*
# @ngdoc method
......@@ -102,7 +68,7 @@ identityProvider = ->
###
logout: ->
result = $injector.invoke(provider.forgetAuthentication, provider)
$q.when(result).finally(invokeCallbacks)
$q.when(result).finally(onlogout)
###*
# @ngdoc method
......@@ -113,7 +79,7 @@ identityProvider = ->
request: (options={}) ->
{oncancel} = options
result = $injector.invoke(provider.requestAuthentication, provider)
$q.when(result).then(invokeCallbacks, oncancel)
$q.when(result).then(onlogin, oncancel)
###*
# @ngdoc method
......@@ -122,9 +88,9 @@ identityProvider = ->
# https://developer.mozilla.org/en-US/docs/Web/API/navigator.id.watch
###
watch: (options) ->
{loggedInUser, onlogin, onlogout, onmatch, onready} = options
{loggedInUser, onlogin, onlogout, onready} = options
result = $injector.invoke(provider.checkAuthentication, provider)
$q.when(result).then(invokeCallbacks, null, onready)
$q.when(result).then(onlogin).finally(-> onready?())
]
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment