57 'initial_state', 'default_workflow', |
57 'initial_state', 'default_workflow', |
58 'allowed_transition', 'destination_state', |
58 'allowed_transition', 'destination_state', |
59 'from_state', 'to_state', 'condition', |
59 'from_state', 'to_state', 'condition', |
60 'subworkflow', 'subworkflow_state', 'subworkflow_exit', |
60 'subworkflow', 'subworkflow_state', 'subworkflow_exit', |
61 )) |
61 )) |
62 SYSTEM_RTYPES = set(('in_group', 'require_group', 'require_permission', |
62 SYSTEM_RTYPES = set(('in_group', 'require_group', |
63 # cwproperty |
63 # cwproperty |
64 'for_user', |
64 'for_user', |
65 )) | WORKFLOW_RTYPES |
65 )) | WORKFLOW_RTYPES |
66 NO_I18NCONTEXT = META_RTYPES | WORKFLOW_RTYPES |
66 NO_I18NCONTEXT = META_RTYPES | WORKFLOW_RTYPES |
67 NO_I18NCONTEXT.add('require_permission') |
|
68 |
67 |
69 SKIP_COMPOSITE_RELS = [('cw_source', 'subject')] |
68 SKIP_COMPOSITE_RELS = [('cw_source', 'subject')] |
70 |
69 |
71 # set of entity and relation types used to build the schema |
70 # set of entity and relation types used to build the schema |
72 SCHEMA_TYPES = set(( |
71 SCHEMA_TYPES = set(( |
83 |
82 |
84 WORKFLOW_TYPES = set(('Transition', 'State', 'TrInfo', 'Workflow', |
83 WORKFLOW_TYPES = set(('Transition', 'State', 'TrInfo', 'Workflow', |
85 'WorkflowTransition', 'BaseTransition', |
84 'WorkflowTransition', 'BaseTransition', |
86 'SubWorkflowExitPoint')) |
85 'SubWorkflowExitPoint')) |
87 |
86 |
88 INTERNAL_TYPES = set(('CWProperty', 'CWPermission', 'CWCache', 'ExternalUri', |
87 INTERNAL_TYPES = set(('CWProperty', 'CWCache', 'ExternalUri', |
89 'CWSource', 'CWSourceHostConfig', 'CWSourceSchemaConfig')) |
88 'CWSource', 'CWSourceHostConfig', 'CWSourceSchemaConfig')) |
90 |
89 |
91 |
90 |
92 _LOGGER = getLogger('cubicweb.schemaloader') |
91 _LOGGER = getLogger('cubicweb.schemaloader') |
93 |
92 |
169 if form == 'subject': |
168 if form == 'subject': |
170 form = '' |
169 form = '' |
171 if form: |
170 if form: |
172 key = key + '_' + form |
171 key = key + '_' + form |
173 # ensure unicode |
172 # ensure unicode |
174 # .lower() in case no translation are available XXX done whatever a translation is there or not! |
|
175 if context is not None: |
173 if context is not None: |
176 return unicode(req.pgettext(context, key)).lower() |
174 return unicode(req.pgettext(context, key)) |
177 else: |
175 else: |
178 return unicode(req._(key)).lower() |
176 return unicode(req._(key)) |
179 |
|
180 __builtins__['display_name'] = deprecated('[3.4] display_name should be imported from cubicweb.schema')(display_name) |
|
181 |
177 |
182 |
178 |
183 # Schema objects definition ################################################### |
179 # Schema objects definition ################################################### |
184 |
180 |
185 def ERSchema_display_name(self, req, form='', context=None): |
181 def ERSchema_display_name(self, req, form='', context=None): |
850 assert creating == False |
846 assert creating == False |
851 return self._check(session, x=eid, **kwargs) |
847 return self._check(session, x=eid, **kwargs) |
852 return self._check(session, **kwargs) |
848 return self._check(session, **kwargs) |
853 |
849 |
854 |
850 |
|
851 def vargraph(rqlst): |
|
852 """ builds an adjacency graph of variables from the rql syntax tree, e.g: |
|
853 Any O,S WHERE T subworkflow_exit S, T subworkflow WF, O state_of WF |
|
854 => {'WF': ['O', 'T'], 'S': ['T'], 'T': ['WF', 'S'], 'O': ['WF']} |
|
855 """ |
|
856 vargraph = {} |
|
857 for relation in rqlst.get_nodes(nodes.Relation): |
|
858 try: |
|
859 rhsvarname = relation.children[1].children[0].variable.name |
|
860 lhsvarname = relation.children[0].name |
|
861 except AttributeError: |
|
862 pass |
|
863 else: |
|
864 vargraph.setdefault(lhsvarname, []).append(rhsvarname) |
|
865 vargraph.setdefault(rhsvarname, []).append(lhsvarname) |
|
866 #vargraph[(lhsvarname, rhsvarname)] = relation.r_type |
|
867 return vargraph |
|
868 |
|
869 |
|
870 class GeneratedConstraint(object): |
|
871 def __init__(self, rqlst, mainvars): |
|
872 self.snippet_rqlst = rqlst |
|
873 self.mainvars = mainvars |
|
874 self.vargraph = vargraph(rqlst) |
|
875 |
|
876 |
855 class RRQLExpression(RQLExpression): |
877 class RRQLExpression(RQLExpression): |
856 def __init__(self, expression, mainvars=None, eid=None): |
878 def __init__(self, expression, mainvars=None, eid=None): |
857 if mainvars is None: |
879 if mainvars is None: |
858 mainvars = guess_rrqlexpr_mainvars(expression) |
880 mainvars = guess_rrqlexpr_mainvars(expression) |
859 RQLExpression.__init__(self, expression, mainvars, eid) |
881 RQLExpression.__init__(self, expression, mainvars, eid) |
860 # graph of links between variable, used by rql rewriter |
882 # graph of links between variable, used by rql rewriter |
861 self.vargraph = {} |
883 self.vargraph = vargraph(self.rqlst) |
862 for relation in self.rqlst.get_nodes(nodes.Relation): |
|
863 try: |
|
864 rhsvarname = relation.children[1].children[0].variable.name |
|
865 lhsvarname = relation.children[0].name |
|
866 except AttributeError: |
|
867 pass |
|
868 else: |
|
869 self.vargraph.setdefault(lhsvarname, []).append(rhsvarname) |
|
870 self.vargraph.setdefault(rhsvarname, []).append(lhsvarname) |
|
871 #self.vargraph[(lhsvarname, rhsvarname)] = relation.r_type |
|
872 |
884 |
873 @property |
885 @property |
874 def full_rql(self): |
886 def full_rql(self): |
875 rql = self.minimal_rql |
887 rql = self.minimal_rql |
876 rqlst = getattr(self, 'rqlst', None) # may be not set yet |
888 rqlst = getattr(self, 'rqlst', None) # may be not set yet |
957 """ |
969 """ |
958 |
970 |
959 def repo_check(self, session, eidfrom, rtype, eidto): |
971 def repo_check(self, session, eidfrom, rtype, eidto): |
960 """raise ValidationError if the relation doesn't satisfy the constraint |
972 """raise ValidationError if the relation doesn't satisfy the constraint |
961 """ |
973 """ |
962 pass # this is a vocabulary constraint, not enforce |
974 pass # this is a vocabulary constraint, not enforced |
963 |
975 |
964 |
976 |
965 class RepoEnforcedRQLConstraintMixIn(object): |
977 class RepoEnforcedRQLConstraintMixIn(object): |
966 |
978 |
967 def __init__(self, expression, mainvars=None, msg=None): |
979 def __init__(self, expression, mainvars=None, msg=None): |
1174 set_log_methods(BootstrapSchemaLoader, getLogger('cubicweb.bootstrapschemaloader')) |
1186 set_log_methods(BootstrapSchemaLoader, getLogger('cubicweb.bootstrapschemaloader')) |
1175 set_log_methods(RQLExpression, getLogger('cubicweb.schema')) |
1187 set_log_methods(RQLExpression, getLogger('cubicweb.schema')) |
1176 |
1188 |
1177 # _() is just there to add messages to the catalog, don't care about actual |
1189 # _() is just there to add messages to the catalog, don't care about actual |
1178 # translation |
1190 # translation |
1179 PERM_USE_TEMPLATE_FORMAT = _('use_template_format') |
1191 MAY_USE_TEMPLATE_FORMAT = set(('managers',)) |
1180 NEED_PERM_FORMATS = [_('text/cubicweb-page-template')] |
1192 NEED_PERM_FORMATS = [_('text/cubicweb-page-template')] |
1181 |
1193 |
1182 @monkeypatch(FormatConstraint) |
1194 @monkeypatch(FormatConstraint) |
1183 def vocabulary(self, entity=None, form=None): |
1195 def vocabulary(self, entity=None, form=None): |
1184 cw = None |
1196 cw = None |
1189 if cw is not None: |
1201 if cw is not None: |
1190 if hasattr(cw, 'write_security'): # test it's a session and not a request |
1202 if hasattr(cw, 'write_security'): # test it's a session and not a request |
1191 # cw is a server session |
1203 # cw is a server session |
1192 hasperm = not cw.write_security or \ |
1204 hasperm = not cw.write_security or \ |
1193 not cw.is_hook_category_activated('integrity') or \ |
1205 not cw.is_hook_category_activated('integrity') or \ |
1194 cw.user.has_permission(PERM_USE_TEMPLATE_FORMAT) |
1206 cw.user.matching_groups(MAY_USE_TEMPLATE_FORMAT) |
1195 else: |
1207 else: |
1196 hasperm = cw.user.has_permission(PERM_USE_TEMPLATE_FORMAT) |
1208 hasperm = cw.user.matching_groups(MAY_USE_TEMPLATE_FORMAT) |
1197 if hasperm: |
1209 if hasperm: |
1198 return self.regular_formats + tuple(NEED_PERM_FORMATS) |
1210 return self.regular_formats + tuple(NEED_PERM_FORMATS) |
1199 return self.regular_formats |
1211 return self.regular_formats |
1200 |
1212 |
1201 # XXX monkey patch PyFileReader.import_erschema until bw_normalize_etype is |
1213 # XXX monkey patch PyFileReader.import_erschema until bw_normalize_etype is |