21 |
21 |
22 __docformat__ = "restructuredtext en" |
22 __docformat__ = "restructuredtext en" |
23 |
23 |
24 from logilab.common.registry import objectify_predicate |
24 from logilab.common.registry import objectify_predicate |
25 |
25 |
|
26 from yams import buildobjs |
|
27 |
26 from cubicweb import Unauthorized |
28 from cubicweb import Unauthorized |
27 from cubicweb.server import BEFORE_ADD_RELATIONS, ON_COMMIT_ADD_RELATIONS, hook |
29 from cubicweb.server import BEFORE_ADD_RELATIONS, ON_COMMIT_ADD_RELATIONS, hook |
28 |
30 |
29 |
31 |
|
32 _DEFAULT_UPDATE_ATTRPERM = buildobjs.DEFAULT_ATTRPERMS['update'] |
30 def check_entity_attributes(session, entity, editedattrs=None, creation=False): |
33 def check_entity_attributes(session, entity, editedattrs=None, creation=False): |
31 eid = entity.eid |
34 eid = entity.eid |
32 eschema = entity.e_schema |
35 eschema = entity.e_schema |
33 # ._cw_skip_security_attributes is there to bypass security for attributes |
36 # ._cw_skip_security_attributes is there to bypass security for attributes |
34 # set by hooks by modifying the entity's dictionary |
37 # set by hooks by modifying the entity's dictionary |
37 dontcheck = editedattrs.skip_security |
40 dontcheck = editedattrs.skip_security |
38 for attr in editedattrs: |
41 for attr in editedattrs: |
39 if attr in dontcheck: |
42 if attr in dontcheck: |
40 continue |
43 continue |
41 rdef = eschema.rdef(attr) |
44 rdef = eschema.rdef(attr) |
42 if rdef.final: # non final relation are checked by other hooks |
45 if rdef.final: # non final relation are checked by standard hooks |
43 # add/delete should be equivalent (XXX: unify them into 'update' ?) |
46 # attributes only have a specific 'update' permission |
44 if creation and not rdef.permissions.get('update'): |
47 updateperm = rdef.permissions.get('update') |
|
48 # comparison below works because the default update perm is: |
|
49 # |
|
50 # ('managers', ERQLExpression(Any X WHERE U has_update_permission X, X eid %(x)s, U eid %(u)s)) |
|
51 # |
|
52 # is deserialized in this order (groups first), and ERQLExpression |
|
53 # implements comparison by expression. |
|
54 if updateperm == _DEFAULT_UPDATE_ATTRPERM: |
|
55 # The default update permission is to delegate to the entity |
|
56 # update permission. This is an historical artefact but it is |
|
57 # costly (in general). Hence we take this permission object as a |
|
58 # marker saying "no specific" update permissions for this |
|
59 # attribute. Thus we just do nothing. |
|
60 continue |
|
61 if creation and updateperm == (): |
|
62 # That actually means an immutable attribute. We make an |
|
63 # _exception_ to the `check attr update perms at entity create & |
|
64 # update time` rule for this case. |
45 continue |
65 continue |
46 rdef.check_perm(session, 'update', eid=eid) |
66 rdef.check_perm(session, 'update', eid=eid) |
47 |
67 |
48 |
68 |
49 class CheckEntityPermissionOp(hook.DataOperationMixIn, hook.LateOperation): |
69 class CheckEntityPermissionOp(hook.DataOperationMixIn, hook.LateOperation): |