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,25 +291,6 @@ 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."""
@@ -303,6 +305,57 @@ def after_insert_schema(target, value, schema):
303
305
current_cache .delete_memoized (import_string (mappings_imp ))
304
306
305
307
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
+
306
359
@event .listens_for (Schema , 'after_delete' )
307
360
def before_delete_schema (mapper , connect , schema ):
308
361
"""On schema delete, delete corresponding indexes and aliases in ES."""
@@ -316,7 +369,20 @@ def before_delete_schema(mapper, connect, schema):
316
369
current_cache .delete_memoized (import_string (mappings_imp ))
317
370
318
371
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