setUserId, query principal: fall back to virtual principal possibly provided by oidc

This commit is contained in:
Helmut Merz 2025-05-04 22:40:44 +02:00
parent 77fedaaeaa
commit 80c83d5c9f
5 changed files with 30 additions and 15 deletions

View file

@ -15,9 +15,10 @@ from cybertools.organize.interfaces import IPerson as IBasePerson
from cybertools.organize.interfaces import ITask from cybertools.organize.interfaces import ITask
from loops.interfaces import ILoopsAdapter, IConceptSchema, IRelationAdapter from loops.interfaces import ILoopsAdapter, IConceptSchema, IRelationAdapter
from loops.interfaces import HtmlText from loops.interfaces import HtmlText
from loops.organize.util import getPrincipalFolder from loops.organize.util import getPrincipalFolder, getPrincipalForUserId
from loops import util from loops import util
from loops.util import _ from loops.util import _
from scopes.web.auth import oidc
ANNOTATION_KEY = 'loops.organize.person' ANNOTATION_KEY = 'loops.organize.person'
@ -38,20 +39,23 @@ class UserId(schema.TextLine):
""" """
def _validate(self, userId): def _validate(self, userId):
from loops.organize.party import getPersonForUser
if not userId: if not userId:
return return
from loops.organize.party import getPersonForUser
context = removeSecurityProxy(self.context).context context = removeSecurityProxy(self.context).context
auth = component.getUtility(IAuthentication, context=context) principal = getPrincipalForUserId(userId, context)
try: #auth = component.getUtility(IAuthentication, context=context)
principal = auth.getPrincipal(userId) #try:
except PrincipalLookupError: #principal = auth.getPrincipal(userId)
raiseValidationError(_(u'User $userId does not exist', #except PrincipalLookupError:
#principal = oidc.Principal(userId, dict(name=userId))
if principal is None:
raiseValidationError(_('User $userId does not exist',
mapping={'userId': userId})) mapping={'userId': userId}))
person = getPersonForUser(context, principal=principal) person = getPersonForUser(context, principal=principal)
if person is not None and person != context: if person is not None and person != context:
raiseValidationError( raiseValidationError(
_(u'There is alread a person ($person) assigned to user $userId.', _('There is already a person ($person) assigned to user $userId.',
mapping=dict(person=getName(person), mapping=dict(person=getName(person),
userId=userId))) userId=userId)))

View file

@ -24,6 +24,7 @@ from loops.concept import Concept
from loops.interfaces import IConcept from loops.interfaces import IConcept
from loops.organize.interfaces import IAddress, IPerson, IHasRole from loops.organize.interfaces import IAddress, IPerson, IHasRole
from loops.organize.interfaces import ANNOTATION_KEY from loops.organize.interfaces import ANNOTATION_KEY
from loops.organize.util import getPrincipalForUserId
from loops.predicate import RelationAdapter from loops.predicate import RelationAdapter
from loops.predicate import PredicateInterfaceSourceList from loops.predicate import PredicateInterfaceSourceList
from loops.security.common import assignOwner, removeOwner, allowEditingForOwner from loops.security.common import assignOwner, removeOwner, allowEditingForOwner
@ -32,6 +33,7 @@ from loops.security.common import getCurrentPrincipal
from loops.security.interfaces import ISecuritySetter from loops.security.interfaces import ISecuritySetter
from loops.type import TypeInterfaceSourceList from loops.type import TypeInterfaceSourceList
from loops import util from loops import util
from scopes.web.auth import oidc
# register type interfaces - (TODO: use a function for this) # register type interfaces - (TODO: use a function for this)
@ -85,6 +87,7 @@ class Person(AdapterBase, BasePerson):
setter = ISecuritySetter(self) setter = ISecuritySetter(self)
if userId: if userId:
principal = self.getPrincipalForUserId(userId) principal = self.getPrincipalForUserId(userId)
print('***', userId, principal)
if principal is None: if principal is None:
return return
person = getPersonForUser(self.context, principal=principal) person = getPersonForUser(self.context, principal=principal)
@ -140,13 +143,15 @@ class Person(AdapterBase, BasePerson):
def getPrincipalForUserId(self, userId=None): def getPrincipalForUserId(self, userId=None):
userId = userId or self.userId userId = userId or self.userId
return getPrincipalForUserId(userId, self.context, self.authentication)
if not userId: if not userId:
return None return None
auth = self.authentication auth = self.authentication
try: try:
return auth.getPrincipal(userId) return auth.getPrincipal(userId)
except PrincipalLookupError: except PrincipalLookupError:
return None return oidc.Principal(userId, dict(name=userId))
#return None
def getAuthenticationUtility(context): def getAuthenticationUtility(context):

View file

@ -15,6 +15,7 @@ from zope.traversing.api import getParents
from loops.common import adapted from loops.common import adapted
from loops.security.common import getCurrentPrincipal from loops.security.common import getCurrentPrincipal
from loops.type import getOptionsDict from loops.type import getOptionsDict
from scopes.web.auth import oidc
defaultAuthPluginId = 'loops' defaultAuthPluginId = 'loops'
@ -85,12 +86,15 @@ def getInternalPrincipal(id, context=None, pau=None):
def getPrincipalForUserId(id, context=None, auth=None): def getPrincipalForUserId(id, context=None, auth=None):
if not id:
return None
if auth is None: if auth is None:
auth = component.getUtility(IAuthentication, context=context) auth = component.getUtility(IAuthentication, context=context)
try: try:
return auth.getPrincipal(id) return auth.getPrincipal(id)
except PrincipalLookupError: except PrincipalLookupError:
return None return oidc.Principal(id, dict(name=id))
#return None
def getRolesForPrincipal(id, context): def getRolesForPrincipal(id, context):

View file

@ -3,7 +3,7 @@
# provide (register) authentication utility # provide (register) authentication utility
# and other authentication and authorization stuff. # and other authentication and authorization stuff.
from scopes.server import auth from scopes.web.auth import oidc
from zope.authentication.interfaces import IAuthentication from zope.authentication.interfaces import IAuthentication
from zope.component import provideAdapter, getUtility, provideUtility from zope.component import provideAdapter, getUtility, provideUtility
from zope.interface import implementer, Interface from zope.interface import implementer, Interface
@ -14,18 +14,18 @@ from zope.security.proxy import removeSecurityProxy
def registerAuthUtility(config): def registerAuthUtility(config):
baseAuth = getUtility(IAuthentication) baseAuth = getUtility(IAuthentication)
print('*** registerAuthUtility, baseAuth:', baseAuth) print('*** registerAuthUtility, baseAuth:', baseAuth)
provideUtility(auth.OidcAuthentication(baseAuth)) provideUtility(oidc.OidcAuthentication(baseAuth))
class LoginView: class LoginView:
def __call__(self): def __call__(self):
auth.Authenticator(self.request).login() oidc.Authenticator(self.request).login()
return '' return ''
class CallbackView: class CallbackView:
def __call__(self): def __call__(self):
auth.Authenticator(self.request).callback() oidc.Authenticator(self.request).callback()
return '' return ''

View file

@ -10,12 +10,14 @@ from zope.securitypolicy import securitymap
sys.modules['zope.app.securitypolicy.securitymap'] = securitymap sys.modules['zope.app.securitypolicy.securitymap'] = securitymap
from loops.server import auth from loops.server import auth
from scopes.web.auth import oidc
import waitress import waitress
from zope.app.wsgi import config, getWSGIApplication from zope.app.wsgi import config, getWSGIApplication
def run(app, config): def run(app, config):
oidc.startup()
port = int(config.server_port) port = int(config.server_port)
#print(f'Serving on port {port}.') print(f'Serving on port {port}.')
waitress.serve(app, port=port) waitress.serve(app, port=port)
def main(): def main():