37
37
from six .moves .urllib .parse import urljoin
38
38
from sqlalchemy import UniqueConstraint , event
39
39
from sqlalchemy .orm import validates
40
+ from sqlalchemy .orm .base import NO_VALUE
40
41
from sqlalchemy .orm .exc import NoResultFound
41
42
from werkzeug .utils import import_string
42
43
43
44
from cap .types import json_type
44
45
45
46
from .permissions import SchemaAdminAction , SchemaReadAction
46
47
from .serializers import resolved_schemas_serializer , schema_serializer
48
+ from .signals import deposit_mapping_updated , record_mapping_updated
47
49
48
50
ES_FORBIDDEN = r' ,"\<*>|?'
49
51
@@ -208,11 +210,30 @@ def add_read_access_for_all_users(self):
208
210
"""Give read access to all authenticated users."""
209
211
assert self .id
210
212
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 ))
214
222
db .session .flush ()
215
223
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
+
216
237
def give_admin_access_for_user (self , user ):
217
238
"""Give admin access for users."""
218
239
assert self .id
@@ -270,39 +291,55 @@ def name_to_es_name(name):
270
291
return name .replace ('/' , '-' )
271
292
272
293
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
-
292
294
@event .listens_for (Schema , 'after_insert' )
293
295
def after_insert_schema (target , value , schema ):
294
296
"""On schema insert, create corresponding indexes and aliases in ES."""
295
297
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 )
300
300
301
301
# invenio search needs it
302
302
mappings_imp = current_app .config .get ('SEARCH_GET_MAPPINGS_IMP' )
303
303
current_cache .delete_memoized (import_string (mappings_imp ))
304
304
305
305
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
+
306
343
@event .listens_for (Schema , 'after_delete' )
307
344
def before_delete_schema (mapper , connect , schema ):
308
345
"""On schema delete, delete corresponding indexes and aliases in ES."""
@@ -316,7 +353,36 @@ def before_delete_schema(mapper, connect, schema):
316
353
current_cache .delete_memoized (import_string (mappings_imp ))
317
354
318
355
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