3737from six .moves .urllib .parse import urljoin
3838from sqlalchemy import UniqueConstraint , event
3939from sqlalchemy .orm import validates
40+ from sqlalchemy .orm .base import NO_VALUE
4041from sqlalchemy .orm .exc import NoResultFound
4142from werkzeug .utils import import_string
4243
4344from cap .types import json_type
4445
4546from .permissions import SchemaAdminAction , SchemaReadAction
4647from .serializers import resolved_schemas_serializer , schema_serializer
48+ from .signals import deposit_mapping_updated , record_mapping_updated
4749
4850ES_FORBIDDEN = r' ,"\<*>|?'
4951
@@ -208,11 +210,30 @@ def add_read_access_for_all_users(self):
208210 """Give read access to all authenticated users."""
209211 assert self .id
210212
211- db .session .add (
212- ActionSystemRoles .allow (SchemaReadAction (self .id ),
213- role = authenticated_user ))
213+ try :
214+ ActionSystemRoles .query .filter (
215+ ActionSystemRoles .action == 'schema-object-read' ,
216+ ActionSystemRoles .argument == str (self .id ),
217+ ActionSystemRoles .role_name == 'authenticated_user' ).one ()
218+ except NoResultFound :
219+ db .session .add (
220+ ActionSystemRoles .allow (SchemaReadAction (self .id ),
221+ role = authenticated_user ))
214222 db .session .flush ()
215223
224+ def revoke_access_for_all_users (self ):
225+ """Revoke read access to all authenticated users."""
226+ assert self .id
227+
228+ try :
229+ db .session .delete (
230+ ActionSystemRoles .query .filter (
231+ ActionSystemRoles .action == 'schema-object-read' ,
232+ ActionSystemRoles .argument == str (self .id ),
233+ ActionSystemRoles .role_name == 'authenticated_user' ).one ())
234+ except NoResultFound :
235+ pass
236+
216237 def give_admin_access_for_user (self , user ):
217238 """Give admin access for users."""
218239 assert self .id
@@ -270,39 +291,55 @@ def name_to_es_name(name):
270291 return name .replace ('/' , '-' )
271292
272293
273- def create_index (index_name , mapping_body , aliases ):
274- """Create index in elasticsearch, add under given aliases."""
275- if not es .indices .exists (index_name ):
276- current_search .mappings [index_name ] = {} # invenio search needs it
277-
278- es .indices .create (index = index_name ,
279- body = {'mappings' : mapping_body },
280- ignore = False )
281-
282- for alias in aliases :
283- es .indices .update_aliases (
284- {'actions' : [{
285- 'add' : {
286- 'index' : index_name ,
287- 'alias' : alias
288- }
289- }]})
290-
291-
292294@event .listens_for (Schema , 'after_insert' )
293295def after_insert_schema (target , value , schema ):
294296 """On schema insert, create corresponding indexes and aliases in ES."""
295297 if schema .is_indexed :
296- create_index (schema .deposit_index , schema .deposit_mapping ,
297- schema .deposit_aliases )
298- create_index (schema .record_index , schema .record_mapping ,
299- schema .record_aliases )
298+ _recreate_deposit_mapping_in_ES (schema , schema .deposit_mapping )
299+ _recreate_record_mapping_in_ES (schema , schema .record_mapping )
300300
301301 # invenio search needs it
302302 mappings_imp = current_app .config .get ('SEARCH_GET_MAPPINGS_IMP' )
303303 current_cache .delete_memoized (import_string (mappings_imp ))
304304
305305
306+ @event .listens_for (Schema .deposit_mapping , 'set' )
307+ def after_deposit_mapping_updated (target , value , oldvalue , initiator ):
308+ """If deposit mapping field was updated:
309+ * trigger mapping update in ES
310+ * send signal
311+
312+ Skip if:
313+ * triggered on creation of schema (not update)
314+ * schema not indexed in ES
315+ """
316+ if oldvalue == NO_VALUE or not target .is_indexed :
317+ return
318+
319+ _recreate_deposit_mapping_in_ES (target , value )
320+
321+ if target .use_deposit_as_record :
322+ _recreate_record_mapping_in_ES (target , value )
323+
324+
325+ @event .listens_for (Schema .record_mapping , 'set' )
326+ def after_record_mapping_updated (target , value , oldvalue , initiator ):
327+ """If record mapping field was updated:
328+ * trigger mapping update in ES
329+ * send signal
330+
331+ Skip if:
332+ * triggered on creation of schema (not update)
333+ * schema not indexed in ES
334+ * flag use_deposit_as_record, so record mapping changes can be ignored
335+ """
336+ if oldvalue == NO_VALUE or not target .is_indexed or \
337+ target .use_deposit_as_record :
338+ return
339+
340+ _recreate_record_mapping_in_ES (target , value )
341+
342+
306343@event .listens_for (Schema , 'after_delete' )
307344def before_delete_schema (mapper , connect , schema ):
308345 """On schema delete, delete corresponding indexes and aliases in ES."""
@@ -316,7 +353,36 @@ def before_delete_schema(mapper, connect, schema):
316353 current_cache .delete_memoized (import_string (mappings_imp ))
317354
318355
319- @db .event .listens_for (Schema , 'before_update' , propagate = True )
320- def timestamp_before_update (mapper , connection , target ):
321- """Update `updated` property with current time on `before_update` event."""
322- target .updated = datetime .utcnow ()
356+ def _create_index (index_name , mapping_body , aliases ):
357+ """Create index in elasticsearch, add under given aliases."""
358+ if not es .indices .exists (index_name ):
359+ current_search .mappings [index_name ] = {} # invenio search needs it
360+
361+ es .indices .create (index = index_name ,
362+ body = {'mappings' : mapping_body },
363+ ignore = False )
364+
365+ for alias in aliases :
366+ es .indices .update_aliases (
367+ {'actions' : [{
368+ 'add' : {
369+ 'index' : index_name ,
370+ 'alias' : alias
371+ }
372+ }]})
373+
374+
375+ def _recreate_deposit_mapping_in_ES (schema , mapping ):
376+ if es .indices .exists (schema .deposit_index ):
377+ es .indices .delete (index = schema .deposit_index )
378+
379+ _create_index (schema .deposit_index , mapping , schema .deposit_aliases )
380+ deposit_mapping_updated .send (schema )
381+
382+
383+ def _recreate_record_mapping_in_ES (schema , mapping ):
384+ if es .indices .exists (schema .record_index ):
385+ es .indices .delete (index = schema .record_index )
386+
387+ _create_index (schema .record_index , mapping , schema .record_aliases )
388+ record_mapping_updated .send (schema )
0 commit comments