new role loops.Person for Person object and its children, with zope.View default permission; + security propagation fixes
This commit is contained in:
parent
6fad66ea34
commit
2cee73672b
9 changed files with 67 additions and 36 deletions
|
@ -42,7 +42,7 @@ TypeInterfaceSourceList.typeInterfaces += (ISimpleBlogPost, IBlogPost,)
|
||||||
|
|
||||||
class SimpleBlogPost(Compound):
|
class SimpleBlogPost(Compound):
|
||||||
|
|
||||||
implements(IBlogPost)
|
implements(ISimpleBlogPost)
|
||||||
|
|
||||||
textContentType = 'text/html'
|
textContentType = 'text/html'
|
||||||
|
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
loops - Linked Objects for Organization and Processing Services
|
loops - Linked Objects for Organization and Processing Services
|
||||||
===============================================================
|
===============================================================
|
||||||
|
|
||||||
($Id$)
|
|
||||||
|
|
||||||
Note: This packages depends on cybertools.organize.
|
Note: This packages depends on cybertools.organize.
|
||||||
|
|
||||||
Let's do some basic setup
|
Let's do some basic setup
|
||||||
|
@ -267,9 +265,9 @@ Person objects that have a user assigned to them receive this user
|
||||||
|
|
||||||
>>> from zope.app.securitypolicy.interfaces import IPrincipalRoleMap
|
>>> from zope.app.securitypolicy.interfaces import IPrincipalRoleMap
|
||||||
>>> IPrincipalRoleMap(concepts['john']).getPrincipalsAndRoles()
|
>>> IPrincipalRoleMap(concepts['john']).getPrincipalsAndRoles()
|
||||||
[('loops.Owner', 'users.john', PermissionSetting: Allow)]
|
[('loops.Person', 'users.john', PermissionSetting: Allow)]
|
||||||
>>> IPrincipalRoleMap(concepts['person.newuser']).getPrincipalsAndRoles()
|
>>> IPrincipalRoleMap(concepts['person.newuser']).getPrincipalsAndRoles()
|
||||||
[('loops.Owner', u'loops.newuser', PermissionSetting: Allow)]
|
[('loops.Person', u'loops.newuser', PermissionSetting: Allow)]
|
||||||
|
|
||||||
The person ``martha`` hasn't got a user id, so there is no role assigned
|
The person ``martha`` hasn't got a user id, so there is no role assigned
|
||||||
to it.
|
to it.
|
||||||
|
@ -307,9 +305,12 @@ Now we are ready to look for the real stuff - what John is allowed to do.
|
||||||
True
|
True
|
||||||
|
|
||||||
Person objects that have an owner may be modified by this owner.
|
Person objects that have an owner may be modified by this owner.
|
||||||
|
(Changed in 2013-01-14: Owner not set automatically)
|
||||||
|
|
||||||
>>> canWrite(john, 'title')
|
>>> canWrite(john, 'title')
|
||||||
True
|
False
|
||||||
|
|
||||||
|
was: True
|
||||||
|
|
||||||
So let's try with another user with another role setting.
|
So let's try with another user with another role setting.
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2011 Helmut Merz helmutm@cy55.de
|
# Copyright (c) 2013 Helmut Merz helmutm@cy55.de
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# This program is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -18,8 +18,6 @@
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Adapters for IConcept providing interfaces from the cybertools.organize package.
|
Adapters for IConcept providing interfaces from the cybertools.organize package.
|
||||||
|
|
||||||
$Id$
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from persistent.mapping import PersistentMapping
|
from persistent.mapping import PersistentMapping
|
||||||
|
@ -43,9 +41,11 @@ 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.predicate import RelationAdapter
|
from loops.predicate import RelationAdapter
|
||||||
from loops.security.common import assignOwner, removeOwner, allowEditingForOwner
|
|
||||||
from loops.type import TypeInterfaceSourceList
|
|
||||||
from loops.predicate import PredicateInterfaceSourceList
|
from loops.predicate import PredicateInterfaceSourceList
|
||||||
|
from loops.security.common import assignOwner, removeOwner, allowEditingForOwner
|
||||||
|
from loops.security.common import assignPersonRole, removePersonRole
|
||||||
|
from loops.security.interfaces import ISecuritySetter
|
||||||
|
from loops.type import TypeInterfaceSourceList
|
||||||
from loops import util
|
from loops import util
|
||||||
|
|
||||||
|
|
||||||
|
@ -84,6 +84,7 @@ class Person(AdapterBase, BasePerson):
|
||||||
def getUserId(self):
|
def getUserId(self):
|
||||||
return getattr(self.context, '_userId', None)
|
return getattr(self.context, '_userId', None)
|
||||||
def setUserId(self, userId):
|
def setUserId(self, userId):
|
||||||
|
setter = ISecuritySetter(self)
|
||||||
if userId:
|
if userId:
|
||||||
principal = self.getPrincipalForUserId(userId)
|
principal = self.getPrincipalForUserId(userId)
|
||||||
if principal is None:
|
if principal is None:
|
||||||
|
@ -99,13 +100,16 @@ class Person(AdapterBase, BasePerson):
|
||||||
if ann is None: # or not isinstance(ann, PersistentMapping):
|
if ann is None: # or not isinstance(ann, PersistentMapping):
|
||||||
ann = pa[ANNOTATION_KEY] = PersistentMapping()
|
ann = pa[ANNOTATION_KEY] = PersistentMapping()
|
||||||
ann[loopsId] = self.context
|
ann[loopsId] = self.context
|
||||||
assignOwner(self.context, userId)
|
#assignOwner(self.context, userId)
|
||||||
|
assignPersonRole(self.context, userId)
|
||||||
oldUserId = self.userId
|
oldUserId = self.userId
|
||||||
if oldUserId and oldUserId != userId:
|
if oldUserId and oldUserId != userId:
|
||||||
self.removeReferenceFromPrincipal(oldUserId)
|
self.removeReferenceFromPrincipal(oldUserId)
|
||||||
removeOwner(self.context, oldUserId)
|
removeOwner(self.context, oldUserId)
|
||||||
|
removePersonRole(self.context, oldUserId)
|
||||||
self.context._userId = userId
|
self.context._userId = userId
|
||||||
allowEditingForOwner(self.context, revert=not userId)
|
setter.propagateSecurity()
|
||||||
|
allowEditingForOwner(self.context, revert=not userId) # why this?
|
||||||
userId = property(getUserId, setUserId)
|
userId = property(getUserId, setUserId)
|
||||||
|
|
||||||
def removeReferenceFromPrincipal(self, userId):
|
def removeReferenceFromPrincipal(self, userId):
|
||||||
|
|
|
@ -2,8 +2,6 @@
|
||||||
loops - Linked Objects for Organization and Processing Services
|
loops - Linked Objects for Organization and Processing Services
|
||||||
===============================================================
|
===============================================================
|
||||||
|
|
||||||
($Id$)
|
|
||||||
|
|
||||||
>>> from zope import component
|
>>> from zope import component
|
||||||
>>> from zope.traversing.api import getName
|
>>> from zope.traversing.api import getName
|
||||||
|
|
||||||
|
@ -183,6 +181,12 @@ Querying objects by state
|
||||||
[<...>]
|
[<...>]
|
||||||
|
|
||||||
|
|
||||||
|
Task States
|
||||||
|
===========
|
||||||
|
|
||||||
|
>>> from loops.organize.stateful.task import taskStates, publishableTask
|
||||||
|
|
||||||
|
|
||||||
Fin de partie
|
Fin de partie
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
|
|
@ -69,37 +69,51 @@ def publishableTask():
|
||||||
color='yellow',
|
color='yellow',
|
||||||
setSecurity=setPermissionsForRoles({
|
setSecurity=setPermissionsForRoles({
|
||||||
('zope.View', 'zope.Member'): Deny,
|
('zope.View', 'zope.Member'): Deny,
|
||||||
('zope.View', 'loops.Member'): Deny,})),
|
('zope.View', 'loops.Member'): Deny,
|
||||||
|
('zope.View', 'loops.Person'): Deny,
|
||||||
|
('zope.View', 'loops.Staff'): Deny,})),
|
||||||
State('active', 'active', ('retract', 'finish', 'publish', 'cancel',),
|
State('active', 'active', ('retract', 'finish', 'publish', 'cancel',),
|
||||||
color='lightblue',
|
color='lightblue',
|
||||||
setSecurity=setPermissionsForRoles({
|
setSecurity=setPermissionsForRoles({
|
||||||
('zope.View', 'zope.Member'): Deny,
|
('zope.View', 'zope.Member'): Deny,
|
||||||
('zope.View', 'loops.Member'): Allow,})),
|
('zope.View', 'loops.Member'): Deny,
|
||||||
|
('zope.View', 'loops.Person'): Allow,
|
||||||
|
('zope.View', 'loops.Staff'): Deny,})),
|
||||||
State('active_published', 'active (published)',
|
State('active_published', 'active (published)',
|
||||||
('retract', 'finish_published', 'retract', 'cancel',), color='blue',
|
('retract', 'finish_published', 'retract', 'cancel',), color='blue',
|
||||||
setSecurity=setPermissionsForRoles({
|
setSecurity=setPermissionsForRoles({
|
||||||
('zope.View', 'zope.Member'): Allow,
|
('zope.View', 'zope.Member'): Allow,
|
||||||
('zope.View', 'loops.Member'): Allow,})),
|
('zope.View', 'loops.Member'): Allow,
|
||||||
|
('zope.View', 'loops.Person'): Allow,
|
||||||
|
('zope.View', 'loops.Staff'): Allow,})),
|
||||||
State('finished', 'finished', ('reopen', 'archive',),
|
State('finished', 'finished', ('reopen', 'archive',),
|
||||||
color='lightgreen',
|
color='lightgreen',
|
||||||
setSecurity=setPermissionsForRoles({
|
setSecurity=setPermissionsForRoles({
|
||||||
('zope.View', 'zope.Member'): Deny,
|
('zope.View', 'zope.Member'): Deny,
|
||||||
('zope.View', 'loops.Member'): Allow,})),
|
('zope.View', 'loops.Member'): Deny,
|
||||||
|
('zope.View', 'loops.Person'): Allow,
|
||||||
|
('zope.View', 'loops.Staff'): Deny,})),
|
||||||
State('finished_published', 'finished (published)', ('reopen', 'archive',),
|
State('finished_published', 'finished (published)', ('reopen', 'archive',),
|
||||||
color='green',
|
color='green',
|
||||||
setSecurity=setPermissionsForRoles({
|
setSecurity=setPermissionsForRoles({
|
||||||
('zope.View', 'zope.Member'): Allow,
|
('zope.View', 'zope.Member'): Allow,
|
||||||
('zope.View', 'loops.Member'): Allow,})),
|
('zope.View', 'loops.Member'): Allow,
|
||||||
|
('zope.View', 'loops.Person'): Allow,
|
||||||
|
('zope.View', 'loops.Staff'): Allow,})),
|
||||||
State('cancelled', 'cancelled', ('reopen',),
|
State('cancelled', 'cancelled', ('reopen',),
|
||||||
color='x',
|
color='x',
|
||||||
setSecurity=setPermissionsForRoles({
|
setSecurity=setPermissionsForRoles({
|
||||||
('zope.View', 'zope.Member'): Deny,
|
('zope.View', 'zope.Member'): Deny,
|
||||||
('zope.View', 'loops.Member'): Deny,})),
|
('zope.View', 'loops.Member'): Deny,
|
||||||
|
('zope.View', 'loops.Person'): Deny,
|
||||||
|
('zope.View', 'loops.Staff'): Deny,})),
|
||||||
State('archived', 'archived', ('reopen',),
|
State('archived', 'archived', ('reopen',),
|
||||||
color='grey',
|
color='grey',
|
||||||
setSecurity=setPermissionsForRoles({
|
setSecurity=setPermissionsForRoles({
|
||||||
('zope.View', 'zope.Member'): Deny,
|
('zope.View', 'zope.Member'): Deny,
|
||||||
('zope.View', 'loops.Member'): Deny,})),
|
('zope.View', 'loops.Member'): Deny,
|
||||||
|
('zope.View', 'loops.Person'): Deny,
|
||||||
|
('zope.View', 'loops.Staff'): Deny,})),
|
||||||
Transition('release', 'release', 'active'),
|
Transition('release', 'release', 'active'),
|
||||||
Transition('release_publish', 'release, publish', 'active_published'),
|
Transition('release_publish', 'release, publish', 'active_published'),
|
||||||
Transition('publish', 'publish', 'active_published'),
|
Transition('publish', 'publish', 'active_published'),
|
||||||
|
|
|
@ -79,6 +79,11 @@
|
||||||
<grant role="loops.Owner" permission="loops.ViewRestricted" />
|
<grant role="loops.Owner" permission="loops.ViewRestricted" />
|
||||||
<grant role="loops.Owner" permission="zope.View" />
|
<grant role="loops.Owner" permission="zope.View" />
|
||||||
|
|
||||||
|
<role id="loops.Person"
|
||||||
|
title="[loops-person-role] Person" />
|
||||||
|
<grant role="loops.Person" permission="zope.View" />
|
||||||
|
<grant role="loops.Person" permission="loops.ViewRestricted" />
|
||||||
|
|
||||||
<!-- moved to etc/securitypolicy.zcml: -->
|
<!-- moved to etc/securitypolicy.zcml: -->
|
||||||
<!--<grant role="zope.ContentManager" permission="loops.AssignAsParent" />-->
|
<!--<grant role="zope.ContentManager" permission="loops.AssignAsParent" />-->
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2010 Helmut Merz helmutm@cy55.de
|
# Copyright (c) 2013 Helmut Merz helmutm@cy55.de
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# This program is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -18,8 +18,6 @@
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Security-related views.
|
Security-related views.
|
||||||
|
|
||||||
$Id$
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from zope.app.authentication.groupfolder import GroupInformation
|
from zope.app.authentication.groupfolder import GroupInformation
|
||||||
|
@ -145,7 +143,7 @@ class PermissionView(object):
|
||||||
for e in entry:
|
for e in entry:
|
||||||
value = SettingAsBoolean[e[1]]
|
value = SettingAsBoolean[e[1]]
|
||||||
value = (value is False and '-') or (value and '+') or ''
|
value = (value is False and '-') or (value and '+') or ''
|
||||||
result.append(value + e[0])
|
result.append(value + (e[0] or ''))
|
||||||
return ', '.join(result)
|
return ', '.join(result)
|
||||||
|
|
||||||
def getPrincipalPermissions(self):
|
def getPrincipalPermissions(self):
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2011 Helmut Merz helmutm@cy55.de
|
# Copyright (c) 2013 Helmut Merz helmutm@cy55.de
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# This program is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -18,8 +18,6 @@
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Common functions and other stuff for working with permissions and roles.
|
Common functions and other stuff for working with permissions and roles.
|
||||||
|
|
||||||
$Id$
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from persistent import Persistent
|
from persistent import Persistent
|
||||||
|
@ -49,12 +47,12 @@ allRolesExceptOwner = (
|
||||||
'zope.Anonymous', 'zope.Member', 'zope.ContentManager', 'loops.Staff',
|
'zope.Anonymous', 'zope.Member', 'zope.ContentManager', 'loops.Staff',
|
||||||
'loops.xmlrpc.ConceptManager', # relevant for local security?
|
'loops.xmlrpc.ConceptManager', # relevant for local security?
|
||||||
#'loops.SiteManager',
|
#'loops.SiteManager',
|
||||||
'loops.Member', 'loops.Master',)
|
'loops.Person', 'loops.Member', 'loops.Master')
|
||||||
allRolesExceptOwnerAndMaster = tuple(allRolesExceptOwner[:-1])
|
allRolesExceptOwnerAndMaster = tuple(allRolesExceptOwner[:-1])
|
||||||
minorPrivilegedRoles = ('zope.Anonymous', 'zope.Member',)
|
minorPrivilegedRoles = ('zope.Anonymous', 'zope.Member',)
|
||||||
localRoles = ('zope.Anonymous', 'zope.Member', 'zope.ContentManager',
|
localRoles = ('zope.Anonymous', 'zope.Member', 'zope.ContentManager',
|
||||||
'loops.SiteManager', 'loops.Staff', 'loops.Member', 'loops.Master',
|
'loops.SiteManager', 'loops.Staff', 'loops.Member', 'loops.Master',
|
||||||
'loops.Owner')
|
'loops.Owner', 'loops.Person')
|
||||||
|
|
||||||
localPermissions = ('zope.ManageContent', 'zope.View', 'loops.ManageWorkspaces',
|
localPermissions = ('zope.ManageContent', 'zope.View', 'loops.ManageWorkspaces',
|
||||||
'loops.ViewRestricted', 'loops.EditRestricted', 'loops.AssignAsParent',)
|
'loops.ViewRestricted', 'loops.EditRestricted', 'loops.AssignAsParent',)
|
||||||
|
@ -127,7 +125,15 @@ def assignOwner(obj, principalId):
|
||||||
|
|
||||||
def removeOwner(obj, principalId):
|
def removeOwner(obj, principalId):
|
||||||
prm = IPrincipalRoleManager(obj)
|
prm = IPrincipalRoleManager(obj)
|
||||||
prm.removeRoleFromPrincipal('loops.Owner', principalId)
|
prm.unsetRoleForPrincipal('loops.Owner', principalId)
|
||||||
|
|
||||||
|
def assignPersonRole(obj, principalId):
|
||||||
|
prm = IPrincipalRoleManager(obj)
|
||||||
|
prm.assignRoleToPrincipal('loops.Person', principalId)
|
||||||
|
|
||||||
|
def removePersonRole(obj, principalId):
|
||||||
|
prm = IPrincipalRoleManager(obj)
|
||||||
|
prm.unsetRoleForPrincipal('loops.Person', principalId)
|
||||||
|
|
||||||
|
|
||||||
def allowEditingForOwner(obj, deny=allRolesExceptOwner, revert=False):
|
def allowEditingForOwner(obj, deny=allRolesExceptOwner, revert=False):
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
#
|
#
|
||||||
# Copyright (c) 2011 Helmut Merz helmutm@cy55.de
|
# Copyright (c) 2013 Helmut Merz helmutm@cy55.de
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# This program is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
@ -19,8 +19,6 @@
|
||||||
"""
|
"""
|
||||||
Base classes for security setters, i.e. adapters that provide standardized
|
Base classes for security setters, i.e. adapters that provide standardized
|
||||||
methods for setting role permissions and other security-related stuff.
|
methods for setting role permissions and other security-related stuff.
|
||||||
|
|
||||||
$Id$
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from zope.app.security.settings import Allow, Deny, Unset
|
from zope.app.security.settings import Allow, Deny, Unset
|
||||||
|
@ -136,7 +134,7 @@ class LoopsObjectSecuritySetter(BaseSecuritySetter):
|
||||||
def copyPrincipalRoles(self, source, revert=False):
|
def copyPrincipalRoles(self, source, revert=False):
|
||||||
prm = IPrincipalRoleMap(baseObject(source.context))
|
prm = IPrincipalRoleMap(baseObject(source.context))
|
||||||
for r, p, s in prm.getPrincipalsAndRoles():
|
for r, p, s in prm.getPrincipalsAndRoles():
|
||||||
if p in self.workspacePrincipals:
|
#if p in self.workspacePrincipals:
|
||||||
if revert:
|
if revert:
|
||||||
setPrincipalRole(self.principalRoleManager, r, p, Unset)
|
setPrincipalRole(self.principalRoleManager, r, p, Unset)
|
||||||
else:
|
else:
|
||||||
|
@ -155,6 +153,7 @@ class ConceptSecuritySetter(LoopsObjectSecuritySetter):
|
||||||
setter = ISecuritySetter(adapted(relation.second))
|
setter = ISecuritySetter(adapted(relation.second))
|
||||||
setter.setDefaultRolePermissions()
|
setter.setDefaultRolePermissions()
|
||||||
setter.acquireRolePermissions()
|
setter.acquireRolePermissions()
|
||||||
|
# TODO: use setter.acquirePrincipalRoles() instead of copyPrincipalRoles()
|
||||||
wi = baseObject(self.context).workspaceInformation
|
wi = baseObject(self.context).workspaceInformation
|
||||||
if wi and not wi.propagateParentSecurity:
|
if wi and not wi.propagateParentSecurity:
|
||||||
return
|
return
|
||||||
|
|
Loading…
Add table
Reference in a new issue