30 from six.moves import range |
30 from six.moves import range |
31 |
31 |
32 from logilab.common import tempattr |
32 from logilab.common import tempattr |
33 from logilab.common.decorators import cached, clear_cache, monkeypatch, cachedproperty |
33 from logilab.common.decorators import cached, clear_cache, monkeypatch, cachedproperty |
34 from logilab.common.logging_ext import set_log_methods |
34 from logilab.common.logging_ext import set_log_methods |
35 from logilab.common.deprecation import deprecated, class_moved, moved |
35 from logilab.common.deprecation import deprecated |
36 from logilab.common.textutils import splitstrip |
36 from logilab.common.textutils import splitstrip |
37 from logilab.common.graph import get_cycles |
37 from logilab.common.graph import get_cycles |
38 |
38 |
39 import yams |
39 import yams |
40 from yams import BadSchemaDefinition, buildobjs as ybo |
40 from yams import BadSchemaDefinition, buildobjs as ybo |
41 from yams.schema import Schema, ERSchema, EntitySchema, RelationSchema, \ |
41 from yams.schema import Schema, ERSchema, EntitySchema, RelationSchema, \ |
42 RelationDefinitionSchema, PermissionMixIn, role_name |
42 RelationDefinitionSchema, PermissionMixIn, role_name |
43 from yams.constraints import (BaseConstraint, FormatConstraint, BoundaryConstraint, |
43 from yams.constraints import (BaseConstraint, FormatConstraint, |
44 IntervalBoundConstraint, StaticVocabularyConstraint, |
|
45 cstr_json_dumps, cstr_json_loads) |
44 cstr_json_dumps, cstr_json_loads) |
46 from yams.reader import (CONSTRAINTS, PyFileReader, SchemaLoader, |
45 from yams.reader import (CONSTRAINTS, PyFileReader, SchemaLoader, |
47 cleanup_sys_modules, fill_schema_from_namespace) |
46 cleanup_sys_modules, fill_schema_from_namespace) |
48 |
47 |
49 from rql import parse, nodes, RQLSyntaxError, TypeResolverException |
48 from rql import parse, nodes, RQLSyntaxError, TypeResolverException |
66 |
65 |
67 # set of meta-relations available for every entity types |
66 # set of meta-relations available for every entity types |
68 META_RTYPES = set(( |
67 META_RTYPES = set(( |
69 'owned_by', 'created_by', 'is', 'is_instance_of', 'identity', |
68 'owned_by', 'created_by', 'is', 'is_instance_of', 'identity', |
70 'eid', 'creation_date', 'cw_source', 'modification_date', 'has_text', 'cwuri', |
69 'eid', 'creation_date', 'cw_source', 'modification_date', 'has_text', 'cwuri', |
71 )) |
70 )) |
72 WORKFLOW_RTYPES = set(('custom_workflow', 'in_state', 'wf_info_for')) |
71 WORKFLOW_RTYPES = set(('custom_workflow', 'in_state', 'wf_info_for')) |
73 WORKFLOW_DEF_RTYPES = set(('workflow_of', 'state_of', 'transition_of', |
72 WORKFLOW_DEF_RTYPES = set(('workflow_of', 'state_of', 'transition_of', |
74 'initial_state', 'default_workflow', |
73 'initial_state', 'default_workflow', |
75 'allowed_transition', 'destination_state', |
74 'allowed_transition', 'destination_state', |
76 'from_state', 'to_state', 'condition', |
75 'from_state', 'to_state', 'condition', |
96 'relation_type', 'from_entity', 'to_entity', |
95 'relation_type', 'from_entity', 'to_entity', |
97 'constrained_by', 'cstrtype', |
96 'constrained_by', 'cstrtype', |
98 'constraint_of', 'relations', |
97 'constraint_of', 'relations', |
99 'read_permission', 'add_permission', |
98 'read_permission', 'add_permission', |
100 'delete_permission', 'update_permission', |
99 'delete_permission', 'update_permission', |
101 )) |
100 )) |
102 |
101 |
103 WORKFLOW_TYPES = set(('Transition', 'State', 'TrInfo', 'Workflow', |
102 WORKFLOW_TYPES = set(('Transition', 'State', 'TrInfo', 'Workflow', |
104 'WorkflowTransition', 'BaseTransition', |
103 'WorkflowTransition', 'BaseTransition', |
105 'SubWorkflowExitPoint')) |
104 'SubWorkflowExitPoint')) |
106 |
105 |
114 _LOGGER = getLogger('cubicweb.schemaloader') |
113 _LOGGER = getLogger('cubicweb.schemaloader') |
115 |
114 |
116 # entity and relation schema created from serialized schema have an eid |
115 # entity and relation schema created from serialized schema have an eid |
117 ybo.ETYPE_PROPERTIES += ('eid',) |
116 ybo.ETYPE_PROPERTIES += ('eid',) |
118 ybo.RTYPE_PROPERTIES += ('eid',) |
117 ybo.RTYPE_PROPERTIES += ('eid',) |
|
118 |
119 |
119 |
120 def build_schema_from_namespace(items): |
120 def build_schema_from_namespace(items): |
121 schema = CubicWebSchema('noname') |
121 schema = CubicWebSchema('noname') |
122 fill_schema_from_namespace(schema, items, register_base_types=False) |
122 fill_schema_from_namespace(schema, items, register_base_types=False) |
123 return schema |
123 return schema |
|
124 |
124 |
125 |
125 # Bases for manipulating RQL in schema ######################################### |
126 # Bases for manipulating RQL in schema ######################################### |
126 |
127 |
127 def guess_rrqlexpr_mainvars(expression): |
128 def guess_rrqlexpr_mainvars(expression): |
128 defined = set(split_expression(expression)) |
129 defined = set(split_expression(expression)) |
161 single selected node, etc.), raise BadSchemaDefinition if not |
164 single selected node, etc.), raise BadSchemaDefinition if not |
162 """ |
165 """ |
163 if len(formula_rqlst.children) != 1: |
166 if len(formula_rqlst.children) != 1: |
164 raise BadSchemaDefinition('computed attribute %(attr)s on %(etype)s: ' |
167 raise BadSchemaDefinition('computed attribute %(attr)s on %(etype)s: ' |
165 'can not use UNION in formula %(form)r' % |
168 'can not use UNION in formula %(form)r' % |
166 {'attr' : rdef.rtype, |
169 {'attr': rdef.rtype, |
167 'etype' : rdef.subject.type, |
170 'etype': rdef.subject.type, |
168 'form' : rdef.formula}) |
171 'form': rdef.formula}) |
169 select = formula_rqlst.children[0] |
172 select = formula_rqlst.children[0] |
170 if len(select.selection) != 1: |
173 if len(select.selection) != 1: |
171 raise BadSchemaDefinition('computed attribute %(attr)s on %(etype)s: ' |
174 raise BadSchemaDefinition('computed attribute %(attr)s on %(etype)s: ' |
172 'can only select one term in formula %(form)r' % |
175 'can only select one term in formula %(form)r' % |
173 {'attr' : rdef.rtype, |
176 {'attr': rdef.rtype, |
174 'etype' : rdef.subject.type, |
177 'etype': rdef.subject.type, |
175 'form' : rdef.formula}) |
178 'form': rdef.formula}) |
176 term = select.selection[0] |
179 term = select.selection[0] |
177 types = set(term.get_type(sol) for sol in select.solutions) |
180 types = set(term.get_type(sol) for sol in select.solutions) |
178 if len(types) != 1: |
181 if len(types) != 1: |
179 raise BadSchemaDefinition('computed attribute %(attr)s on %(etype)s: ' |
182 raise BadSchemaDefinition('computed attribute %(attr)s on %(etype)s: ' |
180 'multiple possible types (%(types)s) for formula %(form)r' % |
183 'multiple possible types (%(types)s) for formula %(form)r' % |
181 {'attr' : rdef.rtype, |
184 {'attr': rdef.rtype, |
182 'etype' : rdef.subject.type, |
185 'etype': rdef.subject.type, |
183 'types' : list(types), |
186 'types': list(types), |
184 'form' : rdef.formula}) |
187 'form': rdef.formula}) |
185 computed_type = types.pop() |
188 computed_type = types.pop() |
186 expected_type = rdef.object.type |
189 expected_type = rdef.object.type |
187 if computed_type != expected_type: |
190 if computed_type != expected_type: |
188 raise BadSchemaDefinition('computed attribute %(attr)s on %(etype)s: ' |
191 raise BadSchemaDefinition('computed attribute %(attr)s on %(etype)s: ' |
189 'computed attribute type (%(comp_type)s) mismatch with ' |
192 'computed attribute type (%(comp_type)s) mismatch with ' |
190 'specified type (%(attr_type)s)' % |
193 'specified type (%(attr_type)s)' % |
191 {'attr' : rdef.rtype, |
194 {'attr': rdef.rtype, |
192 'etype' : rdef.subject.type, |
195 'etype': rdef.subject.type, |
193 'comp_type' : computed_type, |
196 'comp_type': computed_type, |
194 'attr_type' : expected_type}) |
197 'attr_type': expected_type}) |
195 |
198 |
196 |
199 |
197 class RQLExpression(object): |
200 class RQLExpression(object): |
198 """Base class for RQL expression used in schema (constraints and |
201 """Base class for RQL expression used in schema (constraints and |
199 permissions) |
202 permissions) |
200 """ |
203 """ |
201 # these are overridden by set_log_methods below |
204 # these are overridden by set_log_methods below |
202 # only defining here to prevent pylint from complaining |
205 # only defining here to prevent pylint from complaining |
203 info = warning = error = critical = exception = debug = lambda msg,*a,**kw: None |
206 info = warning = error = critical = exception = debug = lambda msg, *a, **kw: None |
204 # to be defined in concrete classes |
207 # to be defined in concrete classes |
205 predefined_variables = None |
208 predefined_variables = None |
206 |
209 |
207 # Internal cache for parsed expressions |
210 # Internal cache for parsed expressions |
208 _rql_cache = {} |
211 _rql_cache = {} |
220 :type mainvars: sequence of RQL variables' names. Can be provided as a |
223 :type mainvars: sequence of RQL variables' names. Can be provided as a |
221 comma separated string. |
224 comma separated string. |
222 :param mainvars: names of the variables being selected. |
225 :param mainvars: names of the variables being selected. |
223 |
226 |
224 """ |
227 """ |
225 self.eid = eid # eid of the entity representing this rql expression |
228 self.eid = eid # eid of the entity representing this rql expression |
226 assert mainvars, 'bad mainvars %s' % mainvars |
229 assert mainvars, 'bad mainvars %s' % mainvars |
227 if isinstance(mainvars, string_types): |
230 if isinstance(mainvars, string_types): |
228 mainvars = set(splitstrip(mainvars)) |
231 mainvars = set(splitstrip(mainvars)) |
229 elif not isinstance(mainvars, set): |
232 elif not isinstance(mainvars, set): |
230 mainvars = set(mainvars) |
233 mainvars = set(mainvars) |
266 def __hash__(self): |
269 def __hash__(self): |
267 return hash(self.expression) |
270 return hash(self.expression) |
268 |
271 |
269 def __deepcopy__(self, memo): |
272 def __deepcopy__(self, memo): |
270 return self.__class__(self.expression, self.mainvars) |
273 return self.__class__(self.expression, self.mainvars) |
|
274 |
271 def __getstate__(self): |
275 def __getstate__(self): |
272 return (self.expression, self.mainvars) |
276 return (self.expression, self.mainvars) |
|
277 |
273 def __setstate__(self, state): |
278 def __setstate__(self, state): |
274 self.__init__(*state) |
279 self.__init__(*state) |
275 |
280 |
276 @cachedproperty |
281 @cachedproperty |
277 def rqlst(self): |
282 def rqlst(self): |
278 # Don't use _cached_parse here because the rqlst is modified |
283 # Don't use _cached_parse here because the rqlst is modified |
279 select = parse(self.minimal_rql, print_errors=False).children[0] |
284 select = parse(self.minimal_rql, print_errors=False).children[0] |
280 defined = set(split_expression(self.expression)) |
285 defined = set(split_expression(self.expression)) |
281 for varname in self.predefined_variables: |
286 for varname in self.predefined_variables: |
282 if varname in defined: |
287 if varname in defined: |
283 select.add_eid_restriction(select.get_variable(varname), varname.lower(), 'Substitute') |
288 select.add_eid_restriction(select.get_variable(varname), varname.lower(), |
|
289 'Substitute') |
284 return select |
290 return select |
285 |
291 |
286 # permission rql expression specific stuff ################################# |
292 # permission rql expression specific stuff ################################# |
287 |
293 |
288 @cached |
294 @cached |
432 return ERQLExpression(expression, mainvars, eid) |
437 return ERQLExpression(expression, mainvars, eid) |
433 return RRQLExpression(expression, mainvars, eid) |
438 return RRQLExpression(expression, mainvars, eid) |
434 |
439 |
435 def check_permission_definitions(self): |
440 def check_permission_definitions(self): |
436 super(CubicWebRelationDefinitionSchema, self).check_permission_definitions() |
441 super(CubicWebRelationDefinitionSchema, self).check_permission_definitions() |
437 schema = self.subject.schema |
|
438 for action, groups in self.permissions.items(): |
442 for action, groups in self.permissions.items(): |
439 for group_or_rqlexpr in groups: |
443 for group_or_rqlexpr in groups: |
440 if action == 'read' and \ |
444 if action == 'read' and isinstance(group_or_rqlexpr, RQLExpression): |
441 isinstance(group_or_rqlexpr, RQLExpression): |
|
442 msg = "can't use rql expression for read permission of %s" |
445 msg = "can't use rql expression for read permission of %s" |
443 raise BadSchemaDefinition(msg % self) |
446 raise BadSchemaDefinition(msg % self) |
444 if self.final and isinstance(group_or_rqlexpr, RRQLExpression): |
447 if self.final and isinstance(group_or_rqlexpr, RRQLExpression): |
445 msg = "can't use RRQLExpression on %s, use an ERQLExpression" |
448 msg = "can't use RRQLExpression on %s, use an ERQLExpression" |
446 raise BadSchemaDefinition(msg % self) |
449 raise BadSchemaDefinition(msg % self) |
447 if not self.final and isinstance(group_or_rqlexpr, ERQLExpression): |
450 if not self.final and isinstance(group_or_rqlexpr, ERQLExpression): |
448 msg = "can't use ERQLExpression on %s, use a RRQLExpression" |
451 msg = "can't use ERQLExpression on %s, use a RRQLExpression" |
449 raise BadSchemaDefinition(msg % self) |
452 raise BadSchemaDefinition(msg % self) |
|
453 |
450 |
454 |
451 def vargraph(rqlst): |
455 def vargraph(rqlst): |
452 """ builds an adjacency graph of variables from the rql syntax tree, e.g: |
456 """ builds an adjacency graph of variables from the rql syntax tree, e.g: |
453 Any O,S WHERE T subworkflow_exit S, T subworkflow WF, O state_of WF |
457 Any O,S WHERE T subworkflow_exit S, T subworkflow WF, O state_of WF |
454 => {'WF': ['O', 'T'], 'S': ['T'], 'T': ['WF', 'S'], 'O': ['WF']} |
458 => {'WF': ['O', 'T'], 'S': ['T'], 'T': ['WF', 'S'], 'O': ['WF']} |
510 if 'delete' in yams.DEFAULT_COMPUTED_RELPERMS: |
513 if 'delete' in yams.DEFAULT_COMPUTED_RELPERMS: |
511 del yams.DEFAULT_COMPUTED_RELPERMS['delete'] |
514 del yams.DEFAULT_COMPUTED_RELPERMS['delete'] |
512 |
515 |
513 |
516 |
514 PUB_SYSTEM_ENTITY_PERMS = { |
517 PUB_SYSTEM_ENTITY_PERMS = { |
515 'read': ('managers', 'users', 'guests',), |
518 'read': ('managers', 'users', 'guests',), |
516 'add': ('managers',), |
519 'add': ('managers',), |
517 'delete': ('managers',), |
520 'delete': ('managers',), |
518 'update': ('managers',), |
521 'update': ('managers',), |
519 } |
522 } |
520 PUB_SYSTEM_REL_PERMS = { |
523 PUB_SYSTEM_REL_PERMS = { |
521 'read': ('managers', 'users', 'guests',), |
524 'read': ('managers', 'users', 'guests',), |
522 'add': ('managers',), |
525 'add': ('managers',), |
523 'delete': ('managers',), |
526 'delete': ('managers',), |
524 } |
527 } |
525 PUB_SYSTEM_ATTR_PERMS = { |
528 PUB_SYSTEM_ATTR_PERMS = { |
526 'read': ('managers', 'users', 'guests',), |
529 'read': ('managers', 'users', 'guests',), |
527 'add': ('managers',), |
530 'add': ('managers',), |
528 'update': ('managers',), |
531 'update': ('managers',), |
529 } |
532 } |
530 RO_REL_PERMS = { |
533 RO_REL_PERMS = { |
531 'read': ('managers', 'users', 'guests',), |
534 'read': ('managers', 'users', 'guests',), |
532 'add': (), |
535 'add': (), |
533 'delete': (), |
536 'delete': (), |
534 } |
537 } |
535 RO_ATTR_PERMS = { |
538 RO_ATTR_PERMS = { |
536 'read': ('managers', 'users', 'guests',), |
539 'read': ('managers', 'users', 'guests',), |
537 'add': ybo.DEFAULT_ATTRPERMS['add'], |
540 'add': ybo.DEFAULT_ATTRPERMS['add'], |
538 'update': (), |
541 'update': (), |
539 } |
542 } |
|
543 |
540 |
544 |
541 # XXX same algorithm as in reorder_cubes and probably other place, |
545 # XXX same algorithm as in reorder_cubes and probably other place, |
542 # may probably extract a generic function |
546 # may probably extract a generic function |
543 def order_eschemas(eschemas): |
547 def order_eschemas(eschemas): |
544 """return entity schemas ordered such that entity types which specializes an |
548 """return entity schemas ordered such that entity types which specializes an |
567 deps.remove(eschema) |
571 deps.remove(eschema) |
568 except KeyError: |
572 except KeyError: |
569 continue |
573 continue |
570 return eschemas |
574 return eschemas |
571 |
575 |
|
576 |
572 def bw_normalize_etype(etype): |
577 def bw_normalize_etype(etype): |
573 if etype in ETYPE_NAME_MAP: |
578 if etype in ETYPE_NAME_MAP: |
574 msg = '%s has been renamed to %s, please update your code' % ( |
579 msg = '%s has been renamed to %s, please update your code' % ( |
575 etype, ETYPE_NAME_MAP[etype]) |
580 etype, ETYPE_NAME_MAP[etype]) |
576 warn(msg, DeprecationWarning, stacklevel=4) |
581 warn(msg, DeprecationWarning, stacklevel=4) |
577 etype = ETYPE_NAME_MAP[etype] |
582 etype = ETYPE_NAME_MAP[etype] |
578 return etype |
583 return etype |
|
584 |
579 |
585 |
580 def display_name(req, key, form='', context=None): |
586 def display_name(req, key, form='', context=None): |
581 """return a internationalized string for the key (schema entity or relation |
587 """return a internationalized string for the key (schema entity or relation |
582 name) in a given form |
588 name) in a given form |
583 """ |
589 """ |
652 :param permissions: the groups and rql expressions allowing the given action |
658 :param permissions: the groups and rql expressions allowing the given action |
653 """ |
659 """ |
654 orig_set_action_permissions(self, action, tuple(permissions)) |
660 orig_set_action_permissions(self, action, tuple(permissions)) |
655 clear_cache(self, 'get_rqlexprs') |
661 clear_cache(self, 'get_rqlexprs') |
656 clear_cache(self, 'get_groups') |
662 clear_cache(self, 'get_groups') |
|
663 orig_set_action_permissions = PermissionMixIn.set_action_permissions |
657 PermissionMixIn.set_action_permissions = set_action_permissions |
664 PermissionMixIn.set_action_permissions = set_action_permissions |
|
665 |
658 |
666 |
659 def has_local_role(self, action): |
667 def has_local_role(self, action): |
660 """return true if the action *may* be granted locally (i.e. either rql |
668 """return true if the action *may* be granted locally (i.e. either rql |
661 expressions or the owners group are used in security definition) |
669 expressions or the owners group are used in security definition) |
662 |
670 |
669 if action in ('update', 'delete'): |
677 if action in ('update', 'delete'): |
670 return 'owners' in self.get_groups(action) |
678 return 'owners' in self.get_groups(action) |
671 return False |
679 return False |
672 PermissionMixIn.has_local_role = has_local_role |
680 PermissionMixIn.has_local_role = has_local_role |
673 |
681 |
|
682 |
674 def may_have_permission(self, action, req): |
683 def may_have_permission(self, action, req): |
675 if action != 'read' and not (self.has_local_role('read') or |
684 if action != 'read' and not (self.has_local_role('read') or |
676 self.has_perm(req, 'read')): |
685 self.has_perm(req, 'read')): |
677 return False |
686 return False |
678 return self.has_local_role(action) or self.has_perm(req, action) |
687 return self.has_local_role(action) or self.has_perm(req, action) |
679 PermissionMixIn.may_have_permission = may_have_permission |
688 PermissionMixIn.may_have_permission = may_have_permission |
|
689 |
680 |
690 |
681 def has_perm(self, _cw, action, **kwargs): |
691 def has_perm(self, _cw, action, **kwargs): |
682 """return true if the action is granted globally or locally""" |
692 """return true if the action is granted globally or locally""" |
683 try: |
693 try: |
684 self.check_perm(_cw, action, **kwargs) |
694 self.check_perm(_cw, action, **kwargs) |
871 elif not need_has_text and has_has_text: |
881 elif not need_has_text and has_has_text: |
872 # use rschema.del_relation_def and not schema.del_relation_def to |
882 # use rschema.del_relation_def and not schema.del_relation_def to |
873 # avoid deleting the relation type accidentally... |
883 # avoid deleting the relation type accidentally... |
874 self.schema['has_text'].del_relation_def(self, self.schema['String']) |
884 self.schema['has_text'].del_relation_def(self, self.schema['String']) |
875 |
885 |
876 def schema_entity(self): # XXX @property for consistency with meta |
886 def schema_entity(self): # XXX @property for consistency with meta |
877 """return True if this entity type is used to build the schema""" |
887 """return True if this entity type is used to build the schema""" |
878 return self.type in SCHEMA_TYPES |
888 return self.type in SCHEMA_TYPES |
879 |
889 |
880 def rql_expression(self, expression, mainvars=None, eid=None): |
890 def rql_expression(self, expression, mainvars=None, eid=None): |
881 """rql expression factory""" |
891 """rql expression factory""" |
1371 |
1383 |
1372 def _load_definition_files(self, cubes=None): |
1384 def _load_definition_files(self, cubes=None): |
1373 # bootstraping, ignore cubes |
1385 # bootstraping, ignore cubes |
1374 filepath = join(cubicweb.CW_SOFTWARE_ROOT, 'schemas', 'bootstrap.py') |
1386 filepath = join(cubicweb.CW_SOFTWARE_ROOT, 'schemas', 'bootstrap.py') |
1375 self.info('loading %s', filepath) |
1387 self.info('loading %s', filepath) |
1376 with tempattr(ybo, 'PACKAGE', 'cubicweb'): # though we don't care here |
1388 with tempattr(ybo, 'PACKAGE', 'cubicweb'): # though we don't care here |
1377 self.handle_file(filepath) |
1389 self.handle_file(filepath) |
1378 |
1390 |
1379 def unhandled_file(self, filepath): |
1391 def unhandled_file(self, filepath): |
1380 """called when a file without handler associated has been found""" |
1392 """called when a file without handler associated has been found""" |
1381 self.warning('ignoring file %r', filepath) |
1393 self.warning('ignoring file %r', filepath) |
1382 |
1394 |
1383 # these are overridden by set_log_methods below |
1395 # these are overridden by set_log_methods below |
1384 # only defining here to prevent pylint from complaining |
1396 # only defining here to prevent pylint from complaining |
1385 info = warning = error = critical = exception = debug = lambda msg,*a,**kw: None |
1397 info = warning = error = critical = exception = debug = lambda msg, *a, **kw: None |
|
1398 |
1386 |
1399 |
1387 class CubicWebSchemaLoader(BootstrapSchemaLoader): |
1400 class CubicWebSchemaLoader(BootstrapSchemaLoader): |
1388 """cubicweb specific schema loader, automatically adding metadata to the |
1401 """cubicweb specific schema loader, automatically adding metadata to the |
1389 instance's schema |
1402 instance's schema |
1390 """ |
1403 """ |
1421 with tempattr(ybo, 'PACKAGE', basename(cube)): |
1434 with tempattr(ybo, 'PACKAGE', basename(cube)): |
1422 self.handle_file(filepath) |
1435 self.handle_file(filepath) |
1423 |
1436 |
1424 # these are overridden by set_log_methods below |
1437 # these are overridden by set_log_methods below |
1425 # only defining here to prevent pylint from complaining |
1438 # only defining here to prevent pylint from complaining |
1426 info = warning = error = critical = exception = debug = lambda msg,*a,**kw: None |
1439 info = warning = error = critical = exception = debug = lambda msg, *a, **kw: None |
1427 |
1440 |
1428 |
1441 |
1429 set_log_methods(CubicWebSchemaLoader, getLogger('cubicweb.schemaloader')) |
1442 set_log_methods(CubicWebSchemaLoader, getLogger('cubicweb.schemaloader')) |
1430 set_log_methods(BootstrapSchemaLoader, getLogger('cubicweb.bootstrapschemaloader')) |
1443 set_log_methods(BootstrapSchemaLoader, getLogger('cubicweb.bootstrapschemaloader')) |
1431 set_log_methods(RQLExpression, getLogger('cubicweb.schema')) |
1444 set_log_methods(RQLExpression, getLogger('cubicweb.schema')) |
1432 |
1445 |
1433 # _() is just there to add messages to the catalog, don't care about actual |
1446 # _() is just there to add messages to the catalog, don't care about actual |
1434 # translation |
1447 # translation |
1435 MAY_USE_TEMPLATE_FORMAT = set(('managers',)) |
1448 MAY_USE_TEMPLATE_FORMAT = set(('managers',)) |
1436 NEED_PERM_FORMATS = [_('text/cubicweb-page-template')] |
1449 NEED_PERM_FORMATS = [_('text/cubicweb-page-template')] |
|
1450 |
1437 |
1451 |
1438 @monkeypatch(FormatConstraint) |
1452 @monkeypatch(FormatConstraint) |
1439 def vocabulary(self, entity=None, form=None): |
1453 def vocabulary(self, entity=None, form=None): |
1440 cw = None |
1454 cw = None |
1441 if form is None and entity is not None: |
1455 if form is None and entity is not None: |
1442 cw = entity._cw |
1456 cw = entity._cw |
1443 elif form is not None: |
1457 elif form is not None: |
1444 cw = form._cw |
1458 cw = form._cw |
1445 if cw is not None: |
1459 if cw is not None: |
1446 if hasattr(cw, 'write_security'): # test it's a session and not a request |
1460 if hasattr(cw, 'write_security'): # test it's a session and not a request |
1447 # cw is a server session |
1461 # cw is a server session |
1448 hasperm = not cw.write_security or \ |
1462 hasperm = (not cw.write_security or |
1449 not cw.is_hook_category_activated('integrity') or \ |
1463 not cw.is_hook_category_activated('integrity') or |
1450 cw.user.matching_groups(MAY_USE_TEMPLATE_FORMAT) |
1464 cw.user.matching_groups(MAY_USE_TEMPLATE_FORMAT)) |
1451 else: |
1465 else: |
1452 hasperm = cw.user.matching_groups(MAY_USE_TEMPLATE_FORMAT) |
1466 hasperm = cw.user.matching_groups(MAY_USE_TEMPLATE_FORMAT) |
1453 if hasperm: |
1467 if hasperm: |
1454 return self.regular_formats + tuple(NEED_PERM_FORMATS) |
1468 return self.regular_formats + tuple(NEED_PERM_FORMATS) |
1455 return self.regular_formats |
1469 return self.regular_formats |
1456 |
1470 |
1457 # XXX itou for some Statement methods |
1471 # XXX itou for some Statement methods |
1458 from rql import stmts |
1472 from rql import stmts |
1459 orig_get_etype = stmts.ScopeNode.get_etype |
1473 |
|
1474 |
1460 def bw_get_etype(self, name): |
1475 def bw_get_etype(self, name): |
1461 return orig_get_etype(self, bw_normalize_etype(name)) |
1476 return orig_get_etype(self, bw_normalize_etype(name)) |
|
1477 orig_get_etype = stmts.ScopeNode.get_etype |
1462 stmts.ScopeNode.get_etype = bw_get_etype |
1478 stmts.ScopeNode.get_etype = bw_get_etype |
1463 |
1479 |
1464 orig_add_main_variable_delete = stmts.Delete.add_main_variable |
1480 |
1465 def bw_add_main_variable_delete(self, etype, vref): |
1481 def bw_add_main_variable_delete(self, etype, vref): |
1466 return orig_add_main_variable_delete(self, bw_normalize_etype(etype), vref) |
1482 return orig_add_main_variable_delete(self, bw_normalize_etype(etype), vref) |
|
1483 orig_add_main_variable_delete = stmts.Delete.add_main_variable |
1467 stmts.Delete.add_main_variable = bw_add_main_variable_delete |
1484 stmts.Delete.add_main_variable = bw_add_main_variable_delete |
1468 |
1485 |
1469 orig_add_main_variable_insert = stmts.Insert.add_main_variable |
1486 |
1470 def bw_add_main_variable_insert(self, etype, vref): |
1487 def bw_add_main_variable_insert(self, etype, vref): |
1471 return orig_add_main_variable_insert(self, bw_normalize_etype(etype), vref) |
1488 return orig_add_main_variable_insert(self, bw_normalize_etype(etype), vref) |
|
1489 orig_add_main_variable_insert = stmts.Insert.add_main_variable |
1472 stmts.Insert.add_main_variable = bw_add_main_variable_insert |
1490 stmts.Insert.add_main_variable = bw_add_main_variable_insert |
1473 |
1491 |
1474 orig_set_statement_type = stmts.Select.set_statement_type |
1492 |
1475 def bw_set_statement_type(self, etype): |
1493 def bw_set_statement_type(self, etype): |
1476 return orig_set_statement_type(self, bw_normalize_etype(etype)) |
1494 return orig_set_statement_type(self, bw_normalize_etype(etype)) |
|
1495 orig_set_statement_type = stmts.Select.set_statement_type |
1477 stmts.Select.set_statement_type = bw_set_statement_type |
1496 stmts.Select.set_statement_type = bw_set_statement_type |