示例#1
0
class AnzECASClient(AnzCASClient):
    ''' Anz eCAS client extends anz.casclient to support European Council CAS'''

    implements( IAnzCASClient )

    meta_type = 'Anz eCAS Client'

    casServerValidationUrl = ''

    security = ClassSecurityInfo()

    # Session variable use to save assertion
    CAS_ASSERTION = '__ecas_assertion'

    _properties = AnzCASClient._properties + (
        {
            'id': 'casServerValidationUrl',
            'label': 'eCAS Server Validation URL',
            'type': 'string',
            'mode': 'w'
        },
    )

    def __init__( self, id, title ):
        super(AnzECASClient, self).__init__(id, title)
        self._ecas_id = PersistentMapping()

    def getEcasUserId(self, username):
        userdb = getattr(self, '_ecas_id', None)
        if userdb:
            for ecas_id, user in self._ecas_id.iteritems():
                if isEmail(username):
                    if user.email and user.email.lower() == username.lower():
                        return ecas_id
                else:
                    if user.username == username:
                        return ecas_id

    def getEcasIDUser(self, ecas_id):
        """Return internal user mapping for the ecas_id.
        """
        userdb = getattr(self, '_ecas_id', {})
        return userdb.get(ecas_id)

    def getEcasIDEmail(self, ecas_id):
        """Return ecas user's email."""
        ecas_user = self.getEcasIDUser(ecas_id)
        if ecas_user:
            return ecas_user.email

    def getEcasIDUsername(self, ecas_id):
        """Return ecas user's username."""
        ecas_user = self.getEcasIDUser(ecas_id)
        if ecas_user:
            return ecas_user.username

    security.declarePrivate( 'challenge' )
    def challenge( self, request, response, **kw ):
        if request['QUERY_STRING']:
            url = request['ACTUAL_URL'] + "?" + request['QUERY_STRING']
        else:
            url = request['ACTUAL_URL']
        came_from = urllib2.quote(url)
        response.setCookie('challenged', True, path='/')
        response.redirect( '/Login/unauthorized?came_from=%s' % came_from, lock=1 )
        return 1

    def validateServiceTicket(self, service, ticket):
        if self.ticketValidationSpecification == 'CAS 1.0':
            validator = Cas10TicketValidator(
            self.casServerUrlPrefix, self.renew )
        else:
            if self.acceptAnyProxy or self.allowedProxyChains:
                validator = Cas20ProxyTicketValidator(
                    self.casServerUrlPrefix,
                    self._pgtStorage,
                    acceptAnyProxy=self.acceptAnyProxy,
                    allowedProxyChains=self.allowedProxyChains,
                    renew=self.renew )
            else:
                validator = ECas20ServiceTicketValidator(
                    self.casServerUrlPrefix, self.casServerValidationUrl, self._pgtStorage, self.renew )
        return validator.validate(ticket, service, self.getProxyCallbackUrl() )

    security.declarePrivate( 'authenticateCredentials' )
    def authenticateCredentials( self, credentials ):
        user_and_info = super(AnzECASClient, self).authenticateCredentials(credentials)
        if not user_and_info:
            return None
        user, info = user_and_info
        """
        # this code should not be here, but in an assignLocalRolesPlugin
        # make sure the code following will not start a transaction without committing this one
        # else we shall loose the session stored by casclient.py:extractCredentials
        # and the next auth plugin will try to validate the ticket himself and fail
        # because this one was provided by a different sso service than what the next plugin is bound to
        try:
            engine = self.unrestrictedTraverse('/ReportekEngine')
            authMiddleware = engine.authMiddlewareApi
            if authMiddleware:
                authMiddleware.updateLocalRoles(user)
            #from Products.Reportek.BdrAuthorizationMiddleware import updateLocalRoles2
            #updateLocalRoles2(user)
        # make sure any relavant exception are caught before this point.
        # We wouldn't know what to do with them here...
        except:
            LOG.warning("Error while contacting Satelite Registry for authorization info. "
                        "Using the know roles assignments")
        """
        return user, info

    def invalidateOlderMapping(self, c_ecas_id, username):
        """Invalidate older mapping."""
        userdb = getattr(self, '_ecas_id', None)
        res = []
        if userdb:
            for ecas_id, user in self._ecas_id.iteritems():
                if ecas_id != c_ecas_id:
                    if isEmail(username):
                        if user.email and user.email.lower() == username.lower():
                            user._email = None
                            res.append(ecas_id)
                    else:
                        if user.username == username:
                            user._username = None
                            res.append(ecas_id)
        return res

    def mapUser(self, ecas, ecas_id, username):
        ecas_user = ecas._ecas_id.get(ecas_id)
        if not ecas_user:
            ecas_user = EcasClient(ecas_id, username)
            ecas._ecas_id[ecas_id] = ecas_user
            res = self.invalidateOlderMapping(ecas_id, username)
            if res:
                LOG.debug("Invalidated data for ecas id: {}".format(res))
        elif not ecas_user.email and isEmail(username):
            ecas_user._email = username
        elif isEmail(username) and ecas_user.email != username:
            ecas_user._email = username
        elif not ecas_user.username and not isEmail(username):
            ecas_user._username = username
        else:
            LOG.debug("User %s already mapped in %s app" % (username, ECAS_ID))

    def extractCredentials(self, request):
        creds = super(AnzECASClient, self).extractCredentials(request)
        sdm = getattr( self, 'session_data_manager', None )
        assert sdm is not None, 'No session data manager found!'
        session = sdm.getSessionData( create=0 )
        assertion = self.getAssertion( session )
        if assertion:
            try:
                ecas = self.unrestrictedTraverse('/'+ENGINE_ID+'/acl_users/'+ECAS_ID)
                username = assertion.principal.id
                ecas_id = assertion.principal.ecas_id

                if not hasattr(ecas, '_ecas_id'):
                    ecas._ecas_id = PersistentMapping()
                    old_mapping = getattr(ecas, '_user2ecas_id', None)
                    if old_mapping:
                        for user, ecas_user_id in old_mapping.iteritems():
                            self.mapUser(ecas, ecas_user_id, user)
                        del ecas._user2ecas_id

                self.mapUser(ecas, ecas_id, username)

            except Exception as e:
                LOG.warning("Error getting username: {}".format(str(e)))
        return creds