241 rschema = eschema.subjrels[attr] |
241 rschema = eschema.subjrels[attr] |
242 except KeyError: |
242 except KeyError: |
243 cls.warning('skipping fetch_attr %s defined in %s (not found in schema)', |
243 cls.warning('skipping fetch_attr %s defined in %s (not found in schema)', |
244 attr, cls.id) |
244 attr, cls.id) |
245 continue |
245 continue |
246 if not user.matching_groups(rschema.get_groups('read')): |
246 rdef = eschema.rdef(attr) |
|
247 if not user.matching_groups(rdef.get_groups('read')): |
247 continue |
248 continue |
248 var = varmaker.next() |
249 var = varmaker.next() |
249 selection.append(var) |
250 selection.append(var) |
250 restriction = '%s %s %s' % (mainvar, attr, var) |
251 restriction = '%s %s %s' % (mainvar, attr, var) |
251 restrictions.append(restriction) |
252 restrictions.append(restriction) |
252 if not rschema.final: |
253 if not rschema.final: |
253 # XXX this does not handle several destination types |
254 # XXX this does not handle several destination types |
254 desttype = rschema.objects(eschema.type)[0] |
255 desttype = rschema.objects(eschema.type)[0] |
255 card = rschema.rproperty(eschema, desttype, 'cardinality')[0] |
256 card = rdef.cardinality[0] |
256 if card not in '?1': |
257 if card not in '?1': |
257 cls.warning('bad relation %s specified in fetch attrs for %s', |
258 cls.warning('bad relation %s specified in fetch attrs for %s', |
258 attr, cls) |
259 attr, cls) |
259 selection.pop() |
260 selection.pop() |
260 restrictions.pop() |
261 restrictions.pop() |
360 def clear_local_perm_cache(self, action): |
361 def clear_local_perm_cache(self, action): |
361 for rqlexpr in self.e_schema.get_rqlexprs(action): |
362 for rqlexpr in self.e_schema.get_rqlexprs(action): |
362 self.req.local_perm_cache.pop((rqlexpr.eid, (('x', self.eid),)), None) |
363 self.req.local_perm_cache.pop((rqlexpr.eid, (('x', self.eid),)), None) |
363 |
364 |
364 def check_perm(self, action): |
365 def check_perm(self, action): |
365 self.e_schema.check_perm(self.req, action, self.eid) |
366 self.e_schema.check_perm(self.req, action, eid=self.eid) |
366 |
367 |
367 def has_perm(self, action): |
368 def has_perm(self, action): |
368 return self.e_schema.has_perm(self.req, action, self.eid) |
369 return self.e_schema.has_perm(self.req, action, eid=self.eid) |
369 |
370 |
370 def view(self, vid, __registry='views', **kwargs): |
371 def view(self, vid, __registry='views', **kwargs): |
371 """shortcut to apply a view on this entity""" |
372 """shortcut to apply a view on this entity""" |
372 return self.vreg[__registry].render(vid, self.req, rset=self.rset, |
373 return self.vreg[__registry].render(vid, self.req, rset=self.rset, |
373 row=self.row, col=self.col, **kwargs) |
374 row=self.row, col=self.col, **kwargs) |
441 value = value.strip() |
442 value = value.strip() |
442 if value is None or value == '': # don't use "not", 0 is an acceptable value |
443 if value is None or value == '': # don't use "not", 0 is an acceptable value |
443 return u'' |
444 return u'' |
444 if attrtype is None: |
445 if attrtype is None: |
445 attrtype = self.e_schema.destination(attr) |
446 attrtype = self.e_schema.destination(attr) |
446 props = self.e_schema.rproperties(attr) |
447 props = self.e_schema.rdef(attr) |
447 if attrtype == 'String': |
448 if attrtype == 'String': |
448 # internalinalized *and* formatted string such as schema |
449 # internalinalized *and* formatted string such as schema |
449 # description... |
450 # description... |
450 if props.get('internationalizable'): |
451 if props.internationalizable: |
451 value = self.req._(value) |
452 value = self.req._(value) |
452 attrformat = self.attr_metadata(attr, 'format') |
453 attrformat = self.attr_metadata(attr, 'format') |
453 if attrformat: |
454 if attrformat: |
454 return self.mtc_transform(value, attrformat, format, |
455 return self.mtc_transform(value, attrformat, format, |
455 self.req.encoding) |
456 self.req.encoding) |
493 if getattr(self, rschema.type): |
494 if getattr(self, rschema.type): |
494 continue |
495 continue |
495 if rschema.type in self.skip_copy_for: |
496 if rschema.type in self.skip_copy_for: |
496 continue |
497 continue |
497 # skip composite relation |
498 # skip composite relation |
498 if self.e_schema.subjrproperty(rschema, 'composite'): |
499 rdef = self.e_schema.rdef(rschema) |
|
500 if rdef.composite: |
499 continue |
501 continue |
500 # skip relation with card in ?1 else we either change the copied |
502 # skip relation with card in ?1 else we either change the copied |
501 # object (inlined relation) or inserting some inconsistency |
503 # object (inlined relation) or inserting some inconsistency |
502 if self.e_schema.subjrproperty(rschema, 'cardinality')[1] in '?1': |
504 if rdef.cardinality[1] in '?1': |
503 continue |
505 continue |
504 rql = 'SET X %s V WHERE X eid %%(x)s, Y eid %%(y)s, Y %s V' % ( |
506 rql = 'SET X %s V WHERE X eid %%(x)s, Y eid %%(y)s, Y %s V' % ( |
505 rschema.type, rschema.type) |
507 rschema.type, rschema.type) |
506 execute(rql, {'x': self.eid, 'y': ceid}, ('x', 'y')) |
508 execute(rql, {'x': self.eid, 'y': ceid}, ('x', 'y')) |
507 self.clear_related_cache(rschema.type, 'subject') |
509 self.clear_related_cache(rschema.type, 'subject') |
508 for rschema in self.e_schema.object_relations(): |
510 for rschema in self.e_schema.object_relations(): |
509 if rschema.meta: |
511 if rschema.meta: |
510 continue |
512 continue |
511 # skip already defined relations |
513 # skip already defined relations |
512 if getattr(self, 'reverse_%s' % rschema.type): |
514 if self.related(rschema.type, 'object'): |
513 continue |
515 continue |
|
516 rdef = self.e_schema.rdef(rschema, 'object') |
514 # skip composite relation |
517 # skip composite relation |
515 if self.e_schema.objrproperty(rschema, 'composite'): |
518 if rdef.composite: |
516 continue |
519 continue |
517 # skip relation with card in ?1 else we either change the copied |
520 # skip relation with card in ?1 else we either change the copied |
518 # object (inlined relation) or inserting some inconsistency |
521 # object (inlined relation) or inserting some inconsistency |
519 if self.e_schema.objrproperty(rschema, 'cardinality')[0] in '?1': |
522 if rdef.cardinality[0] in '?1': |
520 continue |
523 continue |
521 rql = 'SET V %s X WHERE X eid %%(x)s, Y eid %%(y)s, V %s Y' % ( |
524 rql = 'SET V %s X WHERE X eid %%(x)s, Y eid %%(y)s, V %s Y' % ( |
522 rschema.type, rschema.type) |
525 rschema.type, rschema.type) |
523 execute(rql, {'x': self.eid, 'y': ceid}, ('x', 'y')) |
526 execute(rql, {'x': self.eid, 'y': ceid}, ('x', 'y')) |
524 self.clear_related_cache(rschema.type, 'object') |
527 self.clear_related_cache(rschema.type, 'object') |
535 def to_complete_relations(self): |
538 def to_complete_relations(self): |
536 """by default complete final relations to when calling .complete()""" |
539 """by default complete final relations to when calling .complete()""" |
537 for rschema in self.e_schema.subject_relations(): |
540 for rschema in self.e_schema.subject_relations(): |
538 if rschema.final: |
541 if rschema.final: |
539 continue |
542 continue |
540 if len(rschema.objects(self.e_schema)) > 1: |
543 targets = rschema.objects(self.e_schema) |
|
544 if len(targets) > 1: |
541 # ambigous relations, the querier doesn't handle |
545 # ambigous relations, the querier doesn't handle |
542 # outer join correctly in this case |
546 # outer join correctly in this case |
543 continue |
547 continue |
544 if rschema.inlined: |
548 if rschema.inlined: |
|
549 rdef = rschema.rdef(self.e_schema, targets[0]) |
545 matching_groups = self.req.user.matching_groups |
550 matching_groups = self.req.user.matching_groups |
546 if matching_groups(rschema.get_groups('read')) and \ |
551 if matching_groups(rdef.get_groups('read')) and \ |
547 all(matching_groups(es.get_groups('read')) |
552 all(matching_groups(e.get_groups('read')) for e in targets): |
548 for es in rschema.objects(self.e_schema)): |
|
549 yield rschema, 'subject' |
553 yield rschema, 'subject' |
550 |
554 |
551 def to_complete_attributes(self, skip_bytes=True): |
555 def to_complete_attributes(self, skip_bytes=True): |
552 for rschema, attrschema in self.e_schema.attribute_definitions(): |
556 for rschema, attrschema in self.e_schema.attribute_definitions(): |
553 # skip binary data by default |
557 # skip binary data by default |
591 for rschema, role in self.to_complete_relations(): |
596 for rschema, role in self.to_complete_relations(): |
592 rtype = rschema.type |
597 rtype = rschema.type |
593 if self.relation_cached(rtype, role): |
598 if self.relation_cached(rtype, role): |
594 continue |
599 continue |
595 var = varmaker.next() |
600 var = varmaker.next() |
|
601 targettype = rschema.targets(self.e_schema, role)[0] |
|
602 rdef = rschema.role_rdef(self.e_schema, targettype, role) |
|
603 card = rdef.role_cardinality(role) |
|
604 assert card in '1?', '%s %s %s %s' % (self.e_schema, rtype, |
|
605 role, card) |
596 if role == 'subject': |
606 if role == 'subject': |
597 targettype = rschema.objects(self.e_schema)[0] |
|
598 card = rschema.rproperty(self.e_schema, targettype, |
|
599 'cardinality')[0] |
|
600 if card == '1': |
607 if card == '1': |
601 rql.append('%s %s %s' % (V, rtype, var)) |
608 rql.append('%s %s %s' % (V, rtype, var)) |
602 else: # '?" |
609 else: |
603 rql.append('%s %s %s?' % (V, rtype, var)) |
610 rql.append('%s %s %s?' % (V, rtype, var)) |
604 else: |
611 else: |
605 targettype = rschema.subjects(self.e_schema)[1] |
|
606 card = rschema.rproperty(self.e_schema, targettype, |
|
607 'cardinality')[1] |
|
608 if card == '1': |
612 if card == '1': |
609 rql.append('%s %s %s' % (var, rtype, V)) |
613 rql.append('%s %s %s' % (var, rtype, V)) |
610 else: # '?" |
614 else: |
611 rql.append('%s? %s %s' % (var, rtype, V)) |
615 rql.append('%s? %s %s' % (var, rtype, V)) |
612 assert card in '1?', '%s %s %s %s' % (self.e_schema, rtype, |
|
613 role, card) |
|
614 selected.append(((rtype, role), var)) |
616 selected.append(((rtype, role), var)) |
615 if selected: |
617 if selected: |
616 # select V, we need it as the left most selected variable |
618 # select V, we need it as the left most selected variable |
617 # if some outer join are included to fetch inlined relations |
619 # if some outer join are included to fetch inlined relations |
618 rql = 'Any %s,%s %s' % (V, ','.join(var for attr, var in selected), |
620 rql = 'Any %s,%s %s' % (V, ','.join(var for attr, var in selected), |
754 securitycheck_args = {'toeid': self.eid} |
756 securitycheck_args = {'toeid': self.eid} |
755 else: |
757 else: |
756 restriction = [] |
758 restriction = [] |
757 args = {} |
759 args = {} |
758 securitycheck_args = {} |
760 securitycheck_args = {} |
759 insertsecurity = (rtype.has_local_role('add') and not |
761 rdef = rtype.role_rdef(self.e_schema, targettype, role) |
760 rtype.has_perm(self.req, 'add', **securitycheck_args)) |
762 insertsecurity = (rdef.has_local_role('add') and not |
761 constraints = rtype.rproperty(subjtype, objtype, 'constraints') |
763 rdef.has_perm(self.req, 'add', **securitycheck_args)) |
762 if vocabconstraints: |
764 if vocabconstraints: |
763 # RQLConstraint is a subclass for RQLVocabularyConstraint, so they |
765 # RQLConstraint is a subclass for RQLVocabularyConstraint, so they |
764 # will be included as well |
766 # will be included as well |
765 restriction += [cstr.restriction for cstr in constraints |
767 restriction += [cstr.restriction for cstr in rdef.constraints |
766 if isinstance(cstr, RQLVocabularyConstraint)] |
768 if isinstance(cstr, RQLVocabularyConstraint)] |
767 else: |
769 else: |
768 restriction += [cstr.restriction for cstr in constraints |
770 restriction += [cstr.restriction for cstr in rdef.constraints |
769 if isinstance(cstr, RQLConstraint)] |
771 if isinstance(cstr, RQLConstraint)] |
770 etypecls = self.vreg['etypes'].etype_class(targettype) |
772 etypecls = self.vreg['etypes'].etype_class(targettype) |
771 rql = etypecls.fetch_rql(self.req.user, restriction, |
773 rql = etypecls.fetch_rql(self.req.user, restriction, |
772 mainvar=searchedvar, ordermethod=ordermethod) |
774 mainvar=searchedvar, ordermethod=ordermethod) |
773 # ensure we have an order defined |
775 # ensure we have an order defined |
774 if not ' ORDERBY ' in rql: |
776 if not ' ORDERBY ' in rql: |
775 before, after = rql.split(' WHERE ', 1) |
777 before, after = rql.split(' WHERE ', 1) |
776 rql = '%s ORDERBY %s WHERE %s' % (before, searchedvar, after) |
778 rql = '%s ORDERBY %s WHERE %s' % (before, searchedvar, after) |
777 if insertsecurity: |
779 if insertsecurity: |
778 rqlexprs = rtype.get_rqlexprs('add') |
780 rqlexprs = rdef.get_rqlexprs('add') |
779 rewriter = RQLRewriter(self.req) |
781 rewriter = RQLRewriter(self.req) |
780 rqlst = self.req.vreg.parse(self.req, rql, args) |
782 rqlst = self.req.vreg.parse(self.req, rql, args) |
781 if not self.has_eid(): |
783 if not self.has_eid(): |
782 existant = searchedvar |
784 existant = searchedvar |
783 else: |
785 else: |
825 """set cached values for the given relation""" |
827 """set cached values for the given relation""" |
826 if rset: |
828 if rset: |
827 related = tuple(rset.entities(col)) |
829 related = tuple(rset.entities(col)) |
828 rschema = self.schema.rschema(rtype) |
830 rschema = self.schema.rschema(rtype) |
829 if role == 'subject': |
831 if role == 'subject': |
830 rcard = rschema.rproperty(self.e_schema, related[0].e_schema, |
832 rcard = rschema.rdef(self.e_schema, related[0].e_schema).cardinality[1] |
831 'cardinality')[1] |
|
832 target = 'object' |
833 target = 'object' |
833 else: |
834 else: |
834 rcard = rschema.rproperty(related[0].e_schema, self.e_schema, |
835 rcard = rschema.rdef(related[0].e_schema, self.e_schema).cardinality[0] |
835 'cardinality')[0] |
|
836 target = 'subject' |
836 target = 'subject' |
837 if rcard in '?1': |
837 if rcard in '?1': |
838 for rentity in related: |
838 for rentity in related: |
839 rentity._related_cache['%s_%s' % (rtype, target)] = ( |
839 rentity._related_cache['%s_%s' % (rtype, target)] = ( |
840 self.as_rset(), (self,)) |
840 self.as_rset(), (self,)) |