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,25 +291,6 @@ 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."""
@@ -303,6 +305,57 @@ def after_insert_schema(target, value, schema):
303305 current_cache .delete_memoized (import_string (mappings_imp ))
304306
305307
308+ @event .listens_for (Schema .deposit_mapping , 'set' )
309+ def after_deposit_mapping_updated (target , value , oldvalue , initiator ):
310+ """If deposit mapping field was updated:
311+ * trigger mapping update in ES
312+ * send signal
313+
314+ Skip if:
315+ * triggered on creation of schema (not update)
316+ * schema not indexed in ES
317+ """
318+ if oldvalue == NO_VALUE or not target .is_indexed :
319+ return
320+
321+ if es .indices .exists (target .deposit_index ):
322+ es .indices .delete (index = target .deposit_index )
323+
324+ create_index (target .deposit_index , value , target .deposit_aliases )
325+ deposit_mapping_updated .send (target )
326+
327+ if target .use_deposit_as_record :
328+ if es .indices .exists (target .record_index ):
329+ es .indices .delete (index = target .record_index )
330+
331+ create_index (target .record_index , value , target .record_aliases )
332+
333+ record_mapping_updated .send (target )
334+
335+
336+ @event .listens_for (Schema .record_mapping , 'set' )
337+ def after_record_mapping_updated (target , value , oldvalue , initiator ):
338+ """If record mapping field was updated:
339+ * trigger mapping update in ES
340+ * send signal
341+
342+ Skip if:
343+ * triggered on creation of schema (not update)
344+ * schema not indexed in ES
345+ * flag use_deposit_as_record, so record mapping changes can be ignored
346+ """
347+ if oldvalue == NO_VALUE or not target .is_indexed or \
348+ target .use_deposit_as_record :
349+ return
350+
351+ if es .indices .exists (target .record_index ):
352+ es .indices .delete (index = target .record_index )
353+
354+ create_index (target .record_index , value , target .record_aliases )
355+
356+ record_mapping_updated .send (target )
357+
358+
306359@event .listens_for (Schema , 'after_delete' )
307360def before_delete_schema (mapper , connect , schema ):
308361 """On schema delete, delete corresponding indexes and aliases in ES."""
@@ -316,7 +369,20 @@ def before_delete_schema(mapper, connect, schema):
316369 current_cache .delete_memoized (import_string (mappings_imp ))
317370
318371
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 ()
372+ def create_index (index_name , mapping_body , aliases ):
373+ """Create index in elasticsearch, add under given aliases."""
374+ if not es .indices .exists (index_name ):
375+ current_search .mappings [index_name ] = {} # invenio search needs it
376+
377+ es .indices .create (index = index_name ,
378+ body = {'mappings' : mapping_body },
379+ ignore = False )
380+
381+ for alias in aliases :
382+ es .indices .update_aliases (
383+ {'actions' : [{
384+ 'add' : {
385+ 'index' : index_name ,
386+ 'alias' : alias
387+ }
388+ }]})
0 commit comments