server/repository.py
changeset 9455 62e89e696a3b
parent 9454 a173f9cf9f26
child 9456 a79e88aad555
equal deleted inserted replaced
9454:a173f9cf9f26 9455:62e89e696a3b
  1121         """
  1121         """
  1122         # begin by inserting eid/type/source/extid into the entities table
  1122         # begin by inserting eid/type/source/extid into the entities table
  1123         hook.CleanupNewEidsCacheOp.get_instance(session).add_data(entity.eid)
  1123         hook.CleanupNewEidsCacheOp.get_instance(session).add_data(entity.eid)
  1124         self.system_source.add_info(session, entity, source, extid, complete)
  1124         self.system_source.add_info(session, entity, source, extid, complete)
  1125 
  1125 
  1126     def delete_info(self, session, entity, sourceuri, scleanup=None):
  1126     def delete_info(self, session, entity, sourceuri):
  1127         """called by external source when some entity known by the system source
  1127         """called by external source when some entity known by the system source
  1128         has been deleted in the external source
  1128         has been deleted in the external source
  1129         """
  1129         """
  1130         # mark eid as being deleted in session info and setup cache update
  1130         # mark eid as being deleted in session info and setup cache update
  1131         # operation
  1131         # operation
  1132         hook.CleanupDeletedEidsCacheOp.get_instance(session).add_data(entity.eid)
  1132         hook.CleanupDeletedEidsCacheOp.get_instance(session).add_data(entity.eid)
  1133         self._delete_info(session, entity, sourceuri, scleanup)
  1133         self._delete_info(session, entity, sourceuri)
  1134 
  1134 
  1135     def _delete_info(self, session, entity, sourceuri, scleanup=None):
  1135     def _delete_info(self, session, entity, sourceuri):
  1136         """delete system information on deletion of an entity:
  1136         """delete system information on deletion of an entity:
  1137 
  1137 
  1138         * delete all remaining relations from/to this entity
  1138         * delete all remaining relations from/to this entity
  1139         * call delete info on the system source
  1139         * call delete info on the system source
  1140 
       
  1141         When scleanup is specified, it's expected to be the source's eid, in
       
  1142         which case we'll specify the target's relation source so that this
       
  1143         source is ignored. E.g. we want to delete relations stored locally, as
       
  1144         the deletion information comes from the external source, it's its
       
  1145         responsability to have cleaned-up its own relations.
       
  1146         """
  1140         """
  1147         pendingrtypes = session.transaction_data.get('pendingrtypes', ())
  1141         pendingrtypes = session.transaction_data.get('pendingrtypes', ())
  1148         if scleanup is not None:
       
  1149             source = self.sources_by_eid[scleanup]
       
  1150         # delete remaining relations: if user can delete the entity, he can
  1142         # delete remaining relations: if user can delete the entity, he can
  1151         # delete all its relations without security checking
  1143         # delete all its relations without security checking
  1152         with session.security_enabled(read=False, write=False):
  1144         with session.security_enabled(read=False, write=False):
  1153             eid = entity.eid
  1145             eid = entity.eid
  1154             for rschema, _, role in entity.e_schema.relation_definitions():
  1146             for rschema, _, role in entity.e_schema.relation_definitions():
  1159                     # don't skip inlined relation so they are regularly
  1151                     # don't skip inlined relation so they are regularly
  1160                     # deleted and so hooks are correctly called
  1152                     # deleted and so hooks are correctly called
  1161                     rql = 'DELETE X %s Y WHERE X eid %%(x)s' % rtype
  1153                     rql = 'DELETE X %s Y WHERE X eid %%(x)s' % rtype
  1162                 else:
  1154                 else:
  1163                     rql = 'DELETE Y %s X WHERE X eid %%(x)s' % rtype
  1155                     rql = 'DELETE Y %s X WHERE X eid %%(x)s' % rtype
  1164                 if scleanup is not None:
       
  1165                     # source cleaning: only delete relations stored locally
       
  1166                     # (here, scleanup
       
  1167                     rql += ', NOT (Y cw_source S, S eid %(seid)s)'
       
  1168                 try:
  1156                 try:
  1169                     session.execute(rql, {'x': eid, 'seid': scleanup},
  1157                     session.execute(rql, {'x': eid}, build_descr=False)
  1170                                     build_descr=False)
       
  1171                 except Exception:
  1158                 except Exception:
  1172                     if self.config.mode == 'test':
  1159                     if self.config.mode == 'test':
  1173                         raise
  1160                         raise
  1174                     self.exception('error while cascading delete for entity %s '
  1161                     self.exception('error while cascading delete for entity %s '
  1175                                    'from %s. RQL: %s', entity, sourceuri, rql)
  1162                                    'from %s. RQL: %s', entity, sourceuri, rql)
  1176         self.system_source.delete_info_multi(session, [entity])
  1163         self.system_source.delete_info_multi(session, [entity])
  1177 
  1164 
  1178     def _delete_info_multi(self, session, entities, scleanup=None):
  1165     def _delete_info_multi(self, session, entities):
  1179         """same as _delete_info but accepts a list of entities with
  1166         """same as _delete_info but accepts a list of entities with
  1180         the same etype and belinging to the same source.
  1167         the same etype and belinging to the same source.
  1181         """
  1168         """
  1182         pendingrtypes = session.transaction_data.get('pendingrtypes', ())
  1169         pendingrtypes = session.transaction_data.get('pendingrtypes', ())
  1183         if scleanup is not None:
       
  1184             source = self.sources_by_eid[scleanup]
       
  1185         # delete remaining relations: if user can delete the entity, he can
  1170         # delete remaining relations: if user can delete the entity, he can
  1186         # delete all its relations without security checking
  1171         # delete all its relations without security checking
  1187         with session.security_enabled(read=False, write=False):
  1172         with session.security_enabled(read=False, write=False):
  1188             in_eids = ','.join([str(_e.eid) for _e in entities])
  1173             in_eids = ','.join([str(_e.eid) for _e in entities])
  1189             for rschema, _, role in entities[0].e_schema.relation_definitions():
  1174             for rschema, _, role in entities[0].e_schema.relation_definitions():
  1194                     # don't skip inlined relation so they are regularly
  1179                     # don't skip inlined relation so they are regularly
  1195                     # deleted and so hooks are correctly called
  1180                     # deleted and so hooks are correctly called
  1196                     rql = 'DELETE X %s Y WHERE X eid IN (%s)' % (rtype, in_eids)
  1181                     rql = 'DELETE X %s Y WHERE X eid IN (%s)' % (rtype, in_eids)
  1197                 else:
  1182                 else:
  1198                     rql = 'DELETE Y %s X WHERE X eid IN (%s)' % (rtype, in_eids)
  1183                     rql = 'DELETE Y %s X WHERE X eid IN (%s)' % (rtype, in_eids)
  1199                 if scleanup is not None:
       
  1200                     # source cleaning: only delete relations stored locally
       
  1201                     rql += ', NOT (Y cw_source S, S eid %(seid)s)'
       
  1202                 try:
  1184                 try:
  1203                     session.execute(rql, {'seid': scleanup}, build_descr=False)
  1185                     session.execute(rql, build_descr=False)
  1204                 except ValidationError:
  1186                 except ValidationError:
  1205                     raise
  1187                     raise
  1206                 except Unauthorized:
  1188                 except Unauthorized:
  1207                     self.exception('Unauthorized exception while cascading delete for entity %s. '
  1189                     self.exception('Unauthorized exception while cascading delete for entity %s. '
  1208                                    'RQL: %s.\nThis should not happen since security is disabled here.',
  1190                                    'RQL: %s.\nThis should not happen since security is disabled here.',