diff --git a/etc/keycloak/auth.json b/etc/keycloak/auth.json
index 9b366b1f..6c661bbc 100644
--- a/etc/keycloak/auth.json
+++ b/etc/keycloak/auth.json
@@ -748,6 +748,30 @@
}
]
},
+ {
+ "name": "item_keyword",
+ "ownerManagedAccess": false,
+ "displayName": "Item_keyword",
+ "attributes": {},
+ "_id": "558d5b97-1c6a-40b4-9f53-b597ba42dd64",
+ "uris": [
+ "/api/item_keyword/{id}"
+ ],
+ "scopes": [
+ {
+ "name": "item_keyword:update"
+ },
+ {
+ "name": "item_keyword:delete"
+ },
+ {
+ "name": "item_keyword:add"
+ },
+ {
+ "name": "item_keyword:view"
+ }
+ ]
+ },
{
"name": "item_marker",
"ownerManagedAccess": false,
@@ -916,6 +940,30 @@
}
]
},
+ {
+ "name": "keyword",
+ "ownerManagedAccess": false,
+ "displayName": "Keyword",
+ "attributes": {},
+ "_id": "b61cec50-7643-4e89-953a-f6f73514a365",
+ "uris": [
+ "/api/keyword/{id}"
+ ],
+ "scopes": [
+ {
+ "name": "keyword:update"
+ },
+ {
+ "name": "keyword:delete"
+ },
+ {
+ "name": "keyword:add"
+ },
+ {
+ "name": "keyword:view"
+ }
+ ]
+ },
{
"name": "language",
"ownerManagedAccess": false,
@@ -1361,7 +1409,7 @@
"decisionStrategy": "AFFIRMATIVE",
"config": {
"roles": "[{\"id\":\"francoralite-users\",\"required\":true}]",
- "scopes": "[\"location:view\",\"collection_location:view\",\"domain_tale:view\",\"item_usefulness:view\",\"media_item:view\",\"item_thematic:view\",\"item_informer:view\",\"musical_group:view\",\"instrument:view\",\"item_domain_tale:view\",\"authority:view\",\"fond:view\",\"performance_collection_musician:view\",\"acquisition_mode:view\",\"hornbostelsachs:view\",\"item_marker:view\",\"domain_song:view\",\"mission:view\",\"enumeration:view\",\"legal_rights:view\",\"publisher:view\",\"institution:view\",\"user:view\",\"collection_informer:view\",\"collection_publisher:view\",\"thematic:view\",\"item_domain_vocal:view\",\"item_musical_group:view\",\"musical_organization:view\",\"location_gis:view\",\"mediatype:view\",\"usefulness:view\",\"domain_vocal:view\",\"ext_media_item:view\",\"item_domain_music:view\",\"performance_collection:view\",\"item_collector:view\",\"collection_language:view\",\"emit_vox:view\",\"recording_context:view\",\"timeside_item:view\",\"item_analysis:view\",\"item_dance:view\",\"item:view\",\"coupe:view\",\"collectioncollectors:view\",\"language:view\",\"item_transcoding_flag:view\",\"dance:view\",\"collection:view\",\"item_musical_organization:view\",\"domain_music:view\",\"item_domain_song:view\",\"block:view\"]"
+ "scopes": "[\"location:view\",\"collection_location:view\",\"domain_tale:view\",\"item_usefulness:view\",\"media_item:view\",\"item_thematic:view\",\"item_informer:view\",\"musical_group:view\",\"instrument:view\",\"item_domain_tale:view\",\"authority:view\",\"fond:view\",\"performance_collection_musician:view\",\"acquisition_mode:view\",\"hornbostelsachs:view\",\"item_marker:view\",\"domain_song:view\",\"mission:view\",\"enumeration:view\",\"legal_rights:view\",\"publisher:view\",\"institution:view\",\"user:view\",\"collection_informer:view\",\"collection_publisher:view\",\"thematic:view\",\"item_domain_vocal:view\",\"item_musical_group:view\",\"musical_organization:view\",\"location_gis:view\",\"mediatype:view\",\"usefulness:view\",\"domain_vocal:view\",\"ext_media_item:view\",\"item_domain_music:view\",\"performance_collection:view\",\"item_collector:view\",\"collection_language:view\",\"emit_vox:view\",\"recording_context:view\",\"timeside_item:view\",\"item_analysis:view\",\"item_dance:view\",\"item:view\",\"coupe:view\",\"collectioncollectors:view\",\"language:view\",\"item_transcoding_flag:view\",\"dance:view\",\"collection:view\",\"item_musical_organization:view\",\"domain_music:view\",\"item_domain_song:view\",\"block:view\",\"keyword:view\",\"item_keyword:view\"]"
}
},
{
@@ -1372,7 +1420,7 @@
"decisionStrategy": "AFFIRMATIVE",
"config": {
"roles": "[{\"id\":\"francoralite-contributors\",\"required\":true}]",
- "scopes": "[\"collection_language:delete\",\"fond:add\",\"performance_collection:update\",\"item_usefulness:update\",\"location:view\",\"item_usefulness:delete\",\"authority:update\",\"collection_location:view\",\"item_usefulness:view\",\"item_domain_tale:delete\",\"item_domain_tale:add\",\"item_thematic:view\",\"item_domain_music:add\",\"item_informer:view\",\"collection_publisher:update\",\"item_thematic:add\",\"item_domain_tale:view\",\"authority:view\",\"collection_informer:add\",\"fond:view\",\"item_collector:add\",\"collection_location:update\",\"performance_collection_musician:view\",\"collectioncollectors:delete\",\"collection_language:update\",\"collectioncollectors:update\",\"item_usefulness:add\",\"mission:view\",\"location:add\",\"mission:update\",\"fond:delete\",\"collection_location:add\",\"item_informer:add\",\"authority:add\",\"item_collector:delete\",\"item_informer:delete\",\"performance_collection_musician:delete\",\"performance_collection_musician:add\",\"collection_publisher:add\",\"item_collector:update\",\"collection_informer:view\",\"collection_publisher:view\",\"item_domain_song:update\",\"mission:delete\",\"item:update\",\"collection:add\",\"item_thematic:delete\",\"collection_language:add\",\"location:delete\",\"fond:update\",\"mission:add\",\"item_domain_tale:update\",\"item_domain_music:view\",\"performance_collection:delete\",\"performance_collection:view\",\"collectioncollectors:add\",\"item_collector:view\",\"performance_collection_musician:update\",\"collection_language:view\",\"collection_informer:update\",\"item_dance:delete\",\"item_thematic:update\",\"location:update\",\"performance_collection:add\",\"item_dance:view\",\"item:view\",\"collection_publisher:delete\",\"collectioncollectors:view\",\"collection:update\",\"item_domain_music:delete\",\"item_informer:update\",\"item_domain_song:add\",\"collection_location:delete\",\"collection:delete\",\"collection:view\",\"item:delete\",\"item_domain_song:delete\",\"item_dance:add\",\"authority:delete\",\"collection_informer:delete\",\"item_dance:update\",\"item_domain_music:update\",\"item_domain_song:view\",\"item:add\",\"block:view\",\"location_gis:add\",\"location_gis:update\",\"location_gis:delete\",\"instrument:view\",\"legal_rights:view\",\"mediatype:view\",\"publisher:view\",\"recording_context:view\",\"musical_group:view\",\"item:view\"]"
+ "scopes": "[\"collection_language:delete\",\"fond:add\",\"performance_collection:update\",\"item_usefulness:update\",\"location:view\",\"item_usefulness:delete\",\"authority:update\",\"collection_location:view\",\"item_usefulness:view\",\"item_domain_tale:delete\",\"item_domain_tale:add\",\"item_thematic:view\",\"item_domain_music:add\",\"item_informer:view\",\"collection_publisher:update\",\"item_thematic:add\",\"item_domain_tale:view\",\"authority:view\",\"collection_informer:add\",\"fond:view\",\"item_collector:add\",\"collection_location:update\",\"performance_collection_musician:view\",\"collectioncollectors:delete\",\"collection_language:update\",\"collectioncollectors:update\",\"item_usefulness:add\",\"mission:view\",\"location:add\",\"mission:update\",\"fond:delete\",\"collection_location:add\",\"item_informer:add\",\"authority:add\",\"item_collector:delete\",\"item_informer:delete\",\"performance_collection_musician:delete\",\"performance_collection_musician:add\",\"collection_publisher:add\",\"item_collector:update\",\"collection_informer:view\",\"collection_publisher:view\",\"item_domain_song:update\",\"mission:delete\",\"item:update\",\"collection:add\",\"item_thematic:delete\",\"collection_language:add\",\"location:delete\",\"fond:update\",\"mission:add\",\"item_domain_tale:update\",\"item_domain_music:view\",\"performance_collection:delete\",\"performance_collection:view\",\"collectioncollectors:add\",\"item_collector:view\",\"performance_collection_musician:update\",\"collection_language:view\",\"collection_informer:update\",\"item_dance:delete\",\"item_thematic:update\",\"location:update\",\"performance_collection:add\",\"item_dance:view\",\"item:view\",\"collection_publisher:delete\",\"collectioncollectors:view\",\"collection:update\",\"item_domain_music:delete\",\"item_informer:update\",\"item_domain_song:add\",\"collection_location:delete\",\"collection:delete\",\"collection:view\",\"item:delete\",\"item_domain_song:delete\",\"item_dance:add\",\"authority:delete\",\"collection_informer:delete\",\"item_dance:update\",\"item_domain_music:update\",\"item_domain_song:view\",\"item:add\",\"block:view\",\"location_gis:add\",\"location_gis:update\",\"location_gis:delete\",\"instrument:view\",\"legal_rights:view\",\"mediatype:view\",\"publisher:view\",\"recording_context:view\",\"musical_group:view\",\"item:view\",\"keyword:add\",\"keyword:delete\",\"keyword:update\",\"keyword:view\",\"item_keyword:add\",\"item_keyword:delete\",\"item_keyword:update\",\"item_keyword:view\"]"
}
},
{
@@ -1383,7 +1431,7 @@
"decisionStrategy": "AFFIRMATIVE",
"config": {
"roles": "[{\"id\":\"francoralite-administrators\",\"required\":true}]",
- "scopes": "[\"fond:add\",\"performance_collection:update\",\"user:update\",\"item_usefulness:delete\",\"item_informer:view\",\"musical_group:view\",\"publisher:update\",\"instrument:view\",\"item_musical_organization:add\",\"fond:view\",\"collectioncollectors:delete\",\"acquisition_mode:view\",\"hornbostelsachs:view\",\"item_analysis:delete\",\"hornbostelsachs:add\",\"domain_song:view\",\"timeside_item:delete\",\"enumeration:view\",\"fond:delete\",\"authority:add\",\"item_musical_group:delete\",\"item_collector:delete\",\"publisher:view\",\"item_informer:delete\",\"usefulness:add\",\"coupe:add\",\"collection_publisher:view\",\"item_musical_organization:delete\",\"thematic:view\",\"dance:add\",\"item:update\",\"user:add\",\"musical_organization:update\",\"coupe:delete\",\"legal_rights:update\",\"collection_language:add\",\"instrument:delete\",\"location:delete\",\"domain_music:add\",\"ext_media_item:view\",\"item_collector:view\",\"recording_context:view\",\"usefulness:delete\",\"collection_informer:update\",\"hornbostelsachs:update\",\"domain_vocal:update\",\"ext_media_item:update\",\"item_domain_music:delete\",\"collection:delete\",\"instrument:update\",\"collection_language:delete\",\"enumeration:add\",\"item_usefulness:update\",\"domain_tale:view\",\"item_domain_tale:add\",\"musical_group:delete\",\"domain_song:update\",\"domain_tale:add\",\"location_gis:delete\",\"acquisition_mode:delete\",\"item_domain_tale:view\",\"item_collector:add\",\"emit_vox:delete\",\"collectioncollectors:update\",\"item_marker:view\",\"item_usefulness:add\",\"language:delete\",\"collection_location:add\",\"item_analysis:update\",\"domain_tale:update\",\"institution:view\",\"performance_collection_musician:add\",\"collection_publisher:add\",\"user:view\",\"item_domain_song:update\",\"item_marker:delete\",\"mission:delete\",\"usefulness:update\",\"domain_music:update\",\"hornbostelsachs:delete\",\"fond:update\",\"acquisition_mode:add\",\"mediatype:view\",\"location_gis:add\",\"recording_context:add\",\"institution:add\",\"emit_vox:view\",\"item_dance:delete\",\"performance_collection:add\",\"item:view\",\"collection_publisher:delete\",\"collection:update\",\"dance:view\",\"item:delete\",\"item_domain_music:update\",\"item_domain_song:view\",\"item:add\",\"mediatype:delete\",\"musical_organization:add\",\"location:view\",\"authority:update\",\"collection_location:view\",\"item_usefulness:view\",\"thematic:update\",\"item_thematic:view\",\"mediatype:add\",\"item_domain_music:add\",\"authority:view\",\"musical_organization:delete\",\"performance_collection_musician:view\",\"media_item:update\",\"item_domain_vocal:delete\",\"mission:view\",\"domain_vocal:delete\",\"location:add\",\"language:add\",\"emit_vox:update\",\"ext_media_item:delete\",\"dance:update\",\"item_analysis:add\",\"emit_vox:add\",\"performance_collection_musician:delete\",\"ext_media_item:add\",\"item_collector:update\",\"dance:delete\",\"item_transcoding_flag:add\",\"item_domain_vocal:view\",\"acquisition_mode:update\",\"item_thematic:delete\",\"domain_vocal:add\",\"item_musical_group:view\",\"musical_organization:view\",\"item_domain_vocal:add\",\"mission:add\",\"usefulness:view\",\"domain_vocal:view\",\"item_domain_tale:update\",\"enumeration:delete\",\"collectioncollectors:add\",\"performance_collection_musician:update\",\"collection_language:view\",\"timeside_item:view\",\"timeside_item:add\",\"item_analysis:view\",\"item_dance:view\",\"coupe:view\",\"collectioncollectors:view\",\"language:view\",\"item_domain_song:add\",\"media_item:delete\",\"item_musical_organization:update\",\"item_musical_organization:view\",\"collection_informer:delete\",\"domain_music:view\",\"domain_tale:delete\",\"media_item:view\",\"item_domain_tale:delete\",\"location_gis:update\",\"media_item:add\",\"recording_context:delete\",\"collection_publisher:update\",\"item_thematic:add\",\"collection_informer:add\",\"item_musical_group:update\",\"collection_location:update\",\"collection_language:update\",\"item_marker:update\",\"item_transcoding_flag:update\",\"musical_group:update\",\"user:delete\",\"institution:delete\",\"thematic:add\",\"mission:update\",\"publisher:add\",\"coupe:update\",\"item_informer:add\",\"legal_rights:view\",\"legal_rights:add\",\"domain_song:delete\",\"collection_informer:view\",\"domain_music:delete\",\"enumeration:update\",\"instrument:add\",\"domain_song:add\",\"collection:add\",\"item_musical_group:add\",\"item_transcoding_flag:delete\",\"publisher:delete\",\"item_marker:add\",\"location_gis:view\",\"language:update\",\"mediatype:update\",\"timeside_item:update\",\"item_domain_music:view\",\"performance_collection:delete\",\"institution:update\",\"performance_collection:view\",\"musical_group:add\",\"item_thematic:update\",\"location:update\",\"legal_rights:delete\",\"item_informer:update\",\"item_transcoding_flag:view\",\"recording_context:update\",\"collection_location:delete\",\"collection:view\",\"item_domain_song:delete\",\"item_dance:add\",\"item_domain_vocal:update\",\"authority:delete\",\"thematic:delete\",\"item_dance:update\"]"
+ "scopes": "[\"fond:add\",\"performance_collection:update\",\"user:update\",\"item_usefulness:delete\",\"item_informer:view\",\"musical_group:view\",\"publisher:update\",\"instrument:view\",\"item_musical_organization:add\",\"fond:view\",\"collectioncollectors:delete\",\"acquisition_mode:view\",\"hornbostelsachs:view\",\"item_analysis:delete\",\"hornbostelsachs:add\",\"domain_song:view\",\"timeside_item:delete\",\"enumeration:view\",\"fond:delete\",\"authority:add\",\"item_musical_group:delete\",\"item_collector:delete\",\"publisher:view\",\"item_informer:delete\",\"usefulness:add\",\"coupe:add\",\"collection_publisher:view\",\"item_musical_organization:delete\",\"thematic:view\",\"dance:add\",\"item:update\",\"user:add\",\"musical_organization:update\",\"coupe:delete\",\"legal_rights:update\",\"collection_language:add\",\"instrument:delete\",\"location:delete\",\"domain_music:add\",\"ext_media_item:view\",\"item_collector:view\",\"recording_context:view\",\"usefulness:delete\",\"collection_informer:update\",\"hornbostelsachs:update\",\"domain_vocal:update\",\"ext_media_item:update\",\"item_domain_music:delete\",\"collection:delete\",\"instrument:update\",\"collection_language:delete\",\"enumeration:add\",\"item_usefulness:update\",\"domain_tale:view\",\"item_domain_tale:add\",\"musical_group:delete\",\"domain_song:update\",\"domain_tale:add\",\"location_gis:delete\",\"acquisition_mode:delete\",\"item_domain_tale:view\",\"item_collector:add\",\"emit_vox:delete\",\"collectioncollectors:update\",\"item_marker:view\",\"item_usefulness:add\",\"language:delete\",\"collection_location:add\",\"item_analysis:update\",\"domain_tale:update\",\"institution:view\",\"performance_collection_musician:add\",\"collection_publisher:add\",\"user:view\",\"item_domain_song:update\",\"item_marker:delete\",\"mission:delete\",\"usefulness:update\",\"domain_music:update\",\"hornbostelsachs:delete\",\"fond:update\",\"acquisition_mode:add\",\"mediatype:view\",\"location_gis:add\",\"recording_context:add\",\"institution:add\",\"emit_vox:view\",\"item_dance:delete\",\"performance_collection:add\",\"item:view\",\"collection_publisher:delete\",\"collection:update\",\"dance:view\",\"item:delete\",\"item_domain_music:update\",\"item_domain_song:view\",\"item:add\",\"mediatype:delete\",\"musical_organization:add\",\"location:view\",\"authority:update\",\"collection_location:view\",\"item_usefulness:view\",\"thematic:update\",\"item_thematic:view\",\"mediatype:add\",\"item_domain_music:add\",\"authority:view\",\"musical_organization:delete\",\"performance_collection_musician:view\",\"media_item:update\",\"item_domain_vocal:delete\",\"mission:view\",\"domain_vocal:delete\",\"location:add\",\"language:add\",\"emit_vox:update\",\"ext_media_item:delete\",\"dance:update\",\"item_analysis:add\",\"emit_vox:add\",\"performance_collection_musician:delete\",\"ext_media_item:add\",\"item_collector:update\",\"dance:delete\",\"item_transcoding_flag:add\",\"item_domain_vocal:view\",\"acquisition_mode:update\",\"item_thematic:delete\",\"domain_vocal:add\",\"item_musical_group:view\",\"musical_organization:view\",\"item_domain_vocal:add\",\"mission:add\",\"usefulness:view\",\"domain_vocal:view\",\"item_domain_tale:update\",\"enumeration:delete\",\"collectioncollectors:add\",\"performance_collection_musician:update\",\"collection_language:view\",\"timeside_item:view\",\"timeside_item:add\",\"item_analysis:view\",\"item_dance:view\",\"coupe:view\",\"collectioncollectors:view\",\"language:view\",\"item_domain_song:add\",\"media_item:delete\",\"item_musical_organization:update\",\"item_musical_organization:view\",\"collection_informer:delete\",\"domain_music:view\",\"domain_tale:delete\",\"media_item:view\",\"item_domain_tale:delete\",\"location_gis:update\",\"media_item:add\",\"recording_context:delete\",\"collection_publisher:update\",\"item_thematic:add\",\"collection_informer:add\",\"item_musical_group:update\",\"collection_location:update\",\"collection_language:update\",\"item_marker:update\",\"item_transcoding_flag:update\",\"musical_group:update\",\"user:delete\",\"institution:delete\",\"thematic:add\",\"mission:update\",\"publisher:add\",\"coupe:update\",\"item_informer:add\",\"legal_rights:view\",\"legal_rights:add\",\"domain_song:delete\",\"collection_informer:view\",\"domain_music:delete\",\"enumeration:update\",\"instrument:add\",\"domain_song:add\",\"collection:add\",\"item_musical_group:add\",\"item_transcoding_flag:delete\",\"publisher:delete\",\"item_marker:add\",\"location_gis:view\",\"language:update\",\"mediatype:update\",\"timeside_item:update\",\"item_domain_music:view\",\"performance_collection:delete\",\"institution:update\",\"performance_collection:view\",\"musical_group:add\",\"item_thematic:update\",\"location:update\",\"legal_rights:delete\",\"item_informer:update\",\"item_transcoding_flag:view\",\"recording_context:update\",\"collection_location:delete\",\"collection:view\",\"item_domain_song:delete\",\"item_dance:add\",\"item_domain_vocal:update\",\"authority:delete\",\"thematic:delete\",\"item_dance:update\",\"keyword:add\",\"keyword:delete\",\"keyword:update\",\"keyword:view\",\"item_keyword:add\",\"item_keyword:delete\",\"item_keyword:update\",\"item_keyword:view\"]"
}
},
{
@@ -1393,7 +1441,7 @@
"logic": "POSITIVE",
"decisionStrategy": "UNANIMOUS",
"config": {
- "scopes": "[\"skos_concept:view\",\"location:view\",\"collection_location:view\",\"domain_tale:view\",\"item_usefulness:view\",\"media_item:view\",\"item_thematic:view\",\"item_informer:view\",\"musical_group:view\",\"instrument:view\",\"item_domain_tale:view\",\"authority:view\",\"fond:view\",\"performance_collection_musician:view\",\"acquisition_mode:view\",\"hornbostelsachs:view\",\"item_marker:view\",\"domain_song:view\",\"mission:view\",\"enumeration:view\",\"coirault:view\",\"legal_rights:view\",\"publisher:view\",\"institution:view\",\"user:view\",\"collection_informer:view\",\"collection_publisher:view\",\"globalsearch\",\"thematic:view\",\"item_domain_vocal:view\",\"item_musical_group:view\",\"musical_organization:view\",\"location_gis:view\",\"mediatype:view\",\"usefulness:view\",\"domain_vocal:view\",\"ext_media_item:view\",\"item_domain_music:view\",\"performance_collection:view\",\"item_collector:view\",\"collection_language:view\",\"emit_vox:view\",\"recording_context:view\",\"timeside_item:view\",\"item_analysis:view\",\"item_dance:view\",\"coupe:view\",\"collectioncollectors:view\",\"language:view\",\"item_transcoding_flag:view\",\"dance:view\",\"collection:view\",\"item_musical_organization:view\",\"domain_music:view\",\"item_domain_song:view\",\"block:view\",\"item:view\"]",
+ "scopes": "[\"skos_concept:view\",\"location:view\",\"collection_location:view\",\"domain_tale:view\",\"item_usefulness:view\",\"media_item:view\",\"item_thematic:view\",\"item_informer:view\",\"musical_group:view\",\"instrument:view\",\"item_domain_tale:view\",\"authority:view\",\"fond:view\",\"performance_collection_musician:view\",\"acquisition_mode:view\",\"hornbostelsachs:view\",\"item_marker:view\",\"domain_song:view\",\"mission:view\",\"enumeration:view\",\"coirault:view\",\"legal_rights:view\",\"publisher:view\",\"institution:view\",\"user:view\",\"collection_informer:view\",\"collection_publisher:view\",\"globalsearch\",\"thematic:view\",\"item_domain_vocal:view\",\"item_musical_group:view\",\"musical_organization:view\",\"location_gis:view\",\"mediatype:view\",\"usefulness:view\",\"domain_vocal:view\",\"ext_media_item:view\",\"item_domain_music:view\",\"performance_collection:view\",\"item_collector:view\",\"collection_language:view\",\"emit_vox:view\",\"recording_context:view\",\"timeside_item:view\",\"item_analysis:view\",\"item_dance:view\",\"coupe:view\",\"collectioncollectors:view\",\"language:view\",\"item_transcoding_flag:view\",\"dance:view\",\"collection:view\",\"item_musical_organization:view\",\"domain_music:view\",\"item_domain_song:view\",\"block:view\",\"item:view\",\"keyword:view\",\"item_keyword:view\"]",
"applyPolicies": "[\"francoralite-users-pol\"]"
}
},
@@ -1416,7 +1464,7 @@
"logic": "POSITIVE",
"decisionStrategy": "UNANIMOUS",
"config": {
- "scopes": "[\"fond:add\",\"item_coirault:add\",\"performance_collection:update\",\"document:add\",\"location:view\",\"item_usefulness:delete\",\"authority:update\",\"collection_location:view\",\"item_usefulness:view\",\"document_fonds:delete\",\"item_thematic:view\",\"item_domain_music:add\",\"item_informer:view\",\"item_musical_organization:add\",\"item_coirault:delete\",\"authority:view\",\"fond:view\",\"item_author:update\",\"performance_collection_musician:view\",\"collectioncollectors:delete\",\"acquisition_mode:view\",\"hornbostelsachs:view\",\"item_domain_vocal:delete\",\"domain_song:view\",\"mission:view\",\"enumeration:view\",\"item_author:delete\",\"location:add\",\"document_collection:add\",\"fond:delete\",\"authority:add\",\"item_analysis:add\",\"item_language:add\",\"item_musical_group:delete\",\"item_coirault:update\",\"item_collector:delete\",\"item_informer:delete\",\"performance_collection_musician:delete\",\"item_collector:update\",\"collection_publisher:view\",\"item_musical_organization:delete\",\"document_item:add\",\"thematic:view\",\"item_compositor:add\",\"item_domain_vocal:view\",\"item:update\",\"item_thematic:delete\",\"document:view\",\"document:update\",\"collection_language:add\",\"location:delete\",\"item_musical_group:view\",\"musical_organization:view\",\"item_domain_vocal:add\",\"mission:add\",\"item_coirault:view\",\"usefulness:view\",\"domain_vocal:view\",\"ext_media_item:view\",\"item_domain_tale:update\",\"item_compositor:update\",\"collectioncollectors:add\",\"item_collector:view\",\"performance_collection_musician:update\",\"collection_language:view\",\"collection_informer:update\",\"document_collection:view\",\"item_dance:view\",\"coupe:view\",\"collectioncollectors:view\",\"language:view\",\"document_mission:view\",\"item_domain_music:delete\",\"item_domain_song:add\",\"item_musical_organization:update\",\"collection:delete\",\"item_musical_organization:view\",\"collection_informer:delete\",\"domain_music:view\",\"document_fonds:update\",\"collection_language:delete\",\"item_performance:update\",\"skos_concept:view\",\"item_usefulness:update\",\"domain_tale:view\",\"item_performance:add\",\"document_mission:add\",\"item_domain_tale:delete\",\"item_domain_tale:add\",\"document_mission:delete\",\"document_item:update\",\"document_collection:delete\",\"item_compositor:delete\",\"item_thematic:add\",\"item_domain_tale:view\",\"collection_informer:add\",\"item_musical_group:update\",\"item_collector:add\",\"document_collection:update\",\"collection_location:update\",\"collection_language:update\",\"collectioncollectors:update\",\"item_usefulness:add\",\"mission:update\",\"item_performance:view\",\"item_language:delete\",\"collection_location:add\",\"coirault:view\",\"item_informer:add\",\"document_item:view\",\"institution:view\",\"performance_collection_musician:add\",\"collection_publisher:add\",\"collection_informer:view\",\"document_mission:update\",\"item_language:update\",\"item_domain_song:update\",\"item_author:view\",\"globalsearch\",\"document_fonds:add\",\"mission:delete\",\"collection:add\",\"item_musical_group:add\",\"fond:update\",\"location_gis:view\",\"document_item:delete\",\"item_domain_music:view\",\"performance_collection:delete\",\"performance_collection:view\",\"emit_vox:view\",\"item_dance:delete\",\"document_fonds:view\",\"item_thematic:update\",\"location:update\",\"performance_collection:add\",\"item:view\",\"collection_publisher:delete\",\"collection:update\",\"item_informer:update\",\"item_author:add\",\"item_language:view\",\"dance:view\",\"document:delete\",\"collection_location:delete\",\"collection:view\",\"item:delete\",\"item_domain_song:delete\",\"item_dance:add\",\"item_domain_vocal:update\",\"authority:delete\",\"item_performance:delete\",\"item_dance:update\",\"item_domain_music:update\",\"item_domain_song:view\",\"item:add\",\"item_compositor:view\",\"block:view\",\"location_gis:add\",\"location_gis:update\",\"location_gis:delete\",\"instrument:view\",\"legal_rights:view\",\"mediatype:view\",\"publisher:view\",\"recording_context:view\",\"musical_group:view\"]",
+ "scopes": "[\"fond:add\",\"item_coirault:add\",\"performance_collection:update\",\"document:add\",\"location:view\",\"item_usefulness:delete\",\"authority:update\",\"collection_location:view\",\"item_usefulness:view\",\"document_fonds:delete\",\"item_thematic:view\",\"item_domain_music:add\",\"item_informer:view\",\"item_musical_organization:add\",\"item_coirault:delete\",\"authority:view\",\"fond:view\",\"item_author:update\",\"performance_collection_musician:view\",\"collectioncollectors:delete\",\"acquisition_mode:view\",\"hornbostelsachs:view\",\"item_domain_vocal:delete\",\"domain_song:view\",\"mission:view\",\"enumeration:view\",\"item_author:delete\",\"location:add\",\"document_collection:add\",\"fond:delete\",\"authority:add\",\"item_analysis:add\",\"item_language:add\",\"item_musical_group:delete\",\"item_coirault:update\",\"item_collector:delete\",\"item_informer:delete\",\"performance_collection_musician:delete\",\"item_collector:update\",\"collection_publisher:view\",\"item_musical_organization:delete\",\"document_item:add\",\"thematic:view\",\"item_compositor:add\",\"item_domain_vocal:view\",\"item:update\",\"item_thematic:delete\",\"document:view\",\"document:update\",\"collection_language:add\",\"location:delete\",\"item_musical_group:view\",\"musical_organization:view\",\"item_domain_vocal:add\",\"mission:add\",\"item_coirault:view\",\"usefulness:view\",\"domain_vocal:view\",\"ext_media_item:view\",\"item_domain_tale:update\",\"item_compositor:update\",\"collectioncollectors:add\",\"item_collector:view\",\"performance_collection_musician:update\",\"collection_language:view\",\"collection_informer:update\",\"document_collection:view\",\"item_dance:view\",\"coupe:view\",\"collectioncollectors:view\",\"language:view\",\"document_mission:view\",\"item_domain_music:delete\",\"item_domain_song:add\",\"item_musical_organization:update\",\"collection:delete\",\"item_musical_organization:view\",\"collection_informer:delete\",\"domain_music:view\",\"document_fonds:update\",\"collection_language:delete\",\"item_performance:update\",\"skos_concept:view\",\"item_usefulness:update\",\"domain_tale:view\",\"item_performance:add\",\"document_mission:add\",\"item_domain_tale:delete\",\"item_domain_tale:add\",\"document_mission:delete\",\"document_item:update\",\"document_collection:delete\",\"item_compositor:delete\",\"item_thematic:add\",\"item_domain_tale:view\",\"collection_informer:add\",\"item_musical_group:update\",\"item_collector:add\",\"document_collection:update\",\"collection_location:update\",\"collection_language:update\",\"collectioncollectors:update\",\"item_usefulness:add\",\"mission:update\",\"item_performance:view\",\"item_language:delete\",\"collection_location:add\",\"coirault:view\",\"item_informer:add\",\"document_item:view\",\"institution:view\",\"performance_collection_musician:add\",\"collection_publisher:add\",\"collection_informer:view\",\"document_mission:update\",\"item_language:update\",\"item_domain_song:update\",\"item_author:view\",\"globalsearch\",\"document_fonds:add\",\"mission:delete\",\"collection:add\",\"item_musical_group:add\",\"fond:update\",\"location_gis:view\",\"document_item:delete\",\"item_domain_music:view\",\"performance_collection:delete\",\"performance_collection:view\",\"emit_vox:view\",\"item_dance:delete\",\"document_fonds:view\",\"item_thematic:update\",\"location:update\",\"performance_collection:add\",\"item:view\",\"collection_publisher:delete\",\"collection:update\",\"item_informer:update\",\"item_author:add\",\"item_language:view\",\"dance:view\",\"document:delete\",\"collection_location:delete\",\"collection:view\",\"item:delete\",\"item_domain_song:delete\",\"item_dance:add\",\"item_domain_vocal:update\",\"authority:delete\",\"item_performance:delete\",\"item_dance:update\",\"item_domain_music:update\",\"item_domain_song:view\",\"item:add\",\"item_compositor:view\",\"block:view\",\"location_gis:add\",\"location_gis:update\",\"location_gis:delete\",\"instrument:view\",\"legal_rights:view\",\"mediatype:view\",\"publisher:view\",\"recording_context:view\",\"musical_group:view\",\"keyword:add\",\"keyword:delete\",\"keyword:update\",\"keyword:view\",\"item_keyword:add\",\"item_keyword:delete\",\"item_keyword:update\",\"item_keyword:view\"]",
"applyPolicies": "[\"francoralite-contributors-pol\"]"
}
},
@@ -1427,7 +1475,7 @@
"logic": "POSITIVE",
"decisionStrategy": "UNANIMOUS",
"config": {
- "scopes": "[\"fond:add\",\"performance_collection:update\",\"item_usefulness:delete\",\"document_fonds:delete\",\"publisher:update\",\"item_informer:view\",\"musical_group:view\",\"item_musical_organization:add\",\"instrument:view\",\"item_coirault:delete\",\"fond:view\",\"item_author:update\",\"collectioncollectors:delete\",\"acquisition_mode:view\",\"hornbostelsachs:view\",\"item_analysis:delete\",\"hornbostelsachs:add\",\"domain_song:view\",\"enumeration:view\",\"fond:delete\",\"authority:add\",\"item_language:add\",\"item_musical_group:delete\",\"item_coirault:update\",\"publisher:view\",\"item_collector:delete\",\"item_informer:delete\",\"usefulness:add\",\"coupe:add\",\"collection_publisher:view\",\"item_musical_organization:delete\",\"thematic:view\",\"dance:add\",\"item:update\",\"musical_organization:update\",\"document:view\",\"coupe:delete\",\"legal_rights:update\",\"collection_language:add\",\"instrument:delete\",\"location:delete\",\"domain_music:add\",\"ext_media_item:view\",\"item_collector:view\",\"recording_context:view\",\"usefulness:delete\",\"collection_informer:update\",\"document_collection:view\",\"hornbostelsachs:update\",\"domain_vocal:update\",\"ext_media_item:update\",\"item_domain_music:delete\",\"collection:delete\",\"instrument:update\",\"document_fonds:update\",\"collection_language:delete\",\"enumeration:add\",\"skos_concept:view\",\"item_usefulness:update\",\"domain_tale:view\",\"item_performance:add\",\"item_domain_tale:add\",\"document_item:update\",\"musical_group:delete\",\"domain_song:update\",\"domain_tale:add\",\"document_collection:delete\",\"location_gis:delete\",\"acquisition_mode:delete\",\"item_domain_tale:view\",\"item_collector:add\",\"document_collection:update\",\"emit_vox:delete\",\"collectioncollectors:update\",\"item_usefulness:add\",\"item_marker:view\",\"language:delete\",\"item_performance:view\",\"collection_location:add\",\"document_item:view\",\"item_analysis:update\",\"domain_tale:update\",\"institution:view\",\"performance_collection_musician:add\",\"collection_publisher:add\",\"document_mission:update\",\"item_language:update\",\"item_domain_song:update\",\"item_author:view\",\"item_marker:delete\",\"usefulness:update\",\"domain_music:update\",\"hornbostelsachs:delete\",\"fond:update\",\"acquisition_mode:add\",\"mediatype:view\",\"location_gis:add\",\"document_item:delete\",\"recording_context:add\",\"institution:add\",\"emit_vox:view\",\"item_dance:delete\",\"performance_collection:add\",\"item:view\",\"collection_publisher:delete\",\"collection:update\",\"dance:view\",\"document:delete\",\"item:delete\",\"item_performance:delete\",\"item_domain_song:view\",\"item_domain_music:update\",\"item:add\",\"item_compositor:view\",\"mediatype:delete\",\"musical_organization:add\",\"item_coirault:add\",\"document:add\",\"location:view\",\"authority:update\",\"item_usefulness:view\",\"collection_location:view\",\"thematic:update\",\"item_thematic:view\",\"mediatype:add\",\"item_domain_music:add\",\"authority:view\",\"musical_organization:delete\",\"performance_collection_musician:view\",\"item_author:delete\",\"domain_vocal:delete\",\"location:add\",\"language:add\",\"document_collection:add\",\"emit_vox:update\",\"ext_media_item:delete\",\"dance:update\",\"item_analysis:add\",\"emit_vox:add\",\"performance_collection_musician:delete\",\"ext_media_item:add\",\"item_collector:update\",\"dance:delete\",\"document_item:add\",\"item_transcoding_flag:add\",\"item_compositor:add\",\"acquisition_mode:update\",\"item_thematic:delete\",\"document:update\",\"domain_vocal:add\",\"item_musical_group:view\",\"musical_organization:view\",\"item_domain_vocal:add\",\"item_coirault:view\",\"usefulness:view\",\"domain_vocal:view\",\"item_domain_tale:update\",\"enumeration:delete\",\"item_compositor:update\",\"collectioncollectors:add\",\"performance_collection_musician:update\",\"collection_language:view\",\"item_analysis:view\",\"item_dance:view\",\"coupe:view\",\"collectioncollectors:view\",\"language:view\",\"document_mission:view\",\"item_domain_song:add\",\"item_musical_organization:update\",\"item_musical_organization:view\",\"collection_informer:delete\",\"domain_music:view\",\"item_performance:update\",\"domain_tale:delete\",\"document_mission:add\",\"location_gis:update\",\"item_domain_tale:delete\",\"document_mission:delete\",\"recording_context:delete\",\"item_compositor:delete\",\"collection_publisher:update\",\"item_thematic:add\",\"collection_informer:add\",\"item_musical_group:update\",\"collection_location:update\",\"collection_language:update\",\"item_transcoding_flag:update\",\"item_marker:update\",\"musical_group:update\",\"institution:delete\",\"thematic:add\",\"item_language:delete\",\"publisher:add\",\"coirault:view\",\"item_informer:add\",\"coupe:update\",\"legal_rights:view\",\"legal_rights:add\",\"domain_song:delete\",\"collection_informer:view\",\"domain_music:delete\",\"enumeration:update\",\"instrument:add\",\"globalsearch\",\"domain_song:add\",\"document_fonds:add\",\"collection:add\",\"item_musical_group:add\",\"publisher:delete\",\"item_transcoding_flag:delete\",\"item_marker:add\",\"location_gis:view\",\"mediatype:update\",\"language:update\",\"item_domain_music:view\",\"performance_collection:delete\",\"institution:update\",\"performance_collection:view\",\"musical_group:add\",\"document_fonds:view\",\"item_thematic:update\",\"location:update\",\"legal_rights:delete\",\"item_informer:update\",\"item_author:add\",\"item_transcoding_flag:view\",\"recording_context:update\",\"item_language:view\",\"collection_location:delete\",\"collection:view\",\"item_domain_song:delete\",\"item_dance:add\",\"authority:delete\",\"thematic:delete\",\"item_dance:update\",\"block:view\",\"block:add\",\"block:delete\",\"block:update\",\"mission:view\",\"mission:add\",\"mission:update\",\"mission:delete\"]",
+ "scopes": "[\"fond:add\",\"performance_collection:update\",\"item_usefulness:delete\",\"document_fonds:delete\",\"publisher:update\",\"item_informer:view\",\"musical_group:view\",\"item_musical_organization:add\",\"instrument:view\",\"item_coirault:delete\",\"fond:view\",\"item_author:update\",\"collectioncollectors:delete\",\"acquisition_mode:view\",\"hornbostelsachs:view\",\"item_analysis:delete\",\"hornbostelsachs:add\",\"domain_song:view\",\"enumeration:view\",\"fond:delete\",\"authority:add\",\"item_language:add\",\"item_musical_group:delete\",\"item_coirault:update\",\"publisher:view\",\"item_collector:delete\",\"item_informer:delete\",\"usefulness:add\",\"coupe:add\",\"collection_publisher:view\",\"item_musical_organization:delete\",\"thematic:view\",\"dance:add\",\"item:update\",\"musical_organization:update\",\"document:view\",\"coupe:delete\",\"legal_rights:update\",\"collection_language:add\",\"instrument:delete\",\"location:delete\",\"domain_music:add\",\"ext_media_item:view\",\"item_collector:view\",\"recording_context:view\",\"usefulness:delete\",\"collection_informer:update\",\"document_collection:view\",\"hornbostelsachs:update\",\"domain_vocal:update\",\"ext_media_item:update\",\"item_domain_music:delete\",\"collection:delete\",\"instrument:update\",\"document_fonds:update\",\"collection_language:delete\",\"enumeration:add\",\"skos_concept:view\",\"item_usefulness:update\",\"domain_tale:view\",\"item_performance:add\",\"item_domain_tale:add\",\"document_item:update\",\"musical_group:delete\",\"domain_song:update\",\"domain_tale:add\",\"document_collection:delete\",\"location_gis:delete\",\"acquisition_mode:delete\",\"item_domain_tale:view\",\"item_collector:add\",\"document_collection:update\",\"emit_vox:delete\",\"collectioncollectors:update\",\"item_usefulness:add\",\"item_marker:view\",\"language:delete\",\"item_performance:view\",\"collection_location:add\",\"document_item:view\",\"item_analysis:update\",\"domain_tale:update\",\"institution:view\",\"performance_collection_musician:add\",\"collection_publisher:add\",\"document_mission:update\",\"item_language:update\",\"item_domain_song:update\",\"item_author:view\",\"item_marker:delete\",\"usefulness:update\",\"domain_music:update\",\"hornbostelsachs:delete\",\"fond:update\",\"acquisition_mode:add\",\"mediatype:view\",\"location_gis:add\",\"document_item:delete\",\"recording_context:add\",\"institution:add\",\"emit_vox:view\",\"item_dance:delete\",\"performance_collection:add\",\"item:view\",\"collection_publisher:delete\",\"collection:update\",\"dance:view\",\"document:delete\",\"item:delete\",\"item_performance:delete\",\"item_domain_song:view\",\"item_domain_music:update\",\"item:add\",\"item_compositor:view\",\"mediatype:delete\",\"musical_organization:add\",\"item_coirault:add\",\"document:add\",\"location:view\",\"authority:update\",\"item_usefulness:view\",\"collection_location:view\",\"thematic:update\",\"item_thematic:view\",\"mediatype:add\",\"item_domain_music:add\",\"authority:view\",\"musical_organization:delete\",\"performance_collection_musician:view\",\"item_author:delete\",\"domain_vocal:delete\",\"location:add\",\"language:add\",\"document_collection:add\",\"emit_vox:update\",\"ext_media_item:delete\",\"dance:update\",\"item_analysis:add\",\"emit_vox:add\",\"performance_collection_musician:delete\",\"ext_media_item:add\",\"item_collector:update\",\"dance:delete\",\"document_item:add\",\"item_transcoding_flag:add\",\"item_compositor:add\",\"acquisition_mode:update\",\"item_thematic:delete\",\"document:update\",\"domain_vocal:add\",\"item_musical_group:view\",\"musical_organization:view\",\"item_domain_vocal:add\",\"item_coirault:view\",\"usefulness:view\",\"domain_vocal:view\",\"item_domain_tale:update\",\"enumeration:delete\",\"item_compositor:update\",\"collectioncollectors:add\",\"performance_collection_musician:update\",\"collection_language:view\",\"item_analysis:view\",\"item_dance:view\",\"coupe:view\",\"collectioncollectors:view\",\"language:view\",\"document_mission:view\",\"item_domain_song:add\",\"item_musical_organization:update\",\"item_musical_organization:view\",\"collection_informer:delete\",\"domain_music:view\",\"item_performance:update\",\"domain_tale:delete\",\"document_mission:add\",\"location_gis:update\",\"item_domain_tale:delete\",\"document_mission:delete\",\"recording_context:delete\",\"item_compositor:delete\",\"collection_publisher:update\",\"item_thematic:add\",\"collection_informer:add\",\"item_musical_group:update\",\"collection_location:update\",\"collection_language:update\",\"item_transcoding_flag:update\",\"item_marker:update\",\"musical_group:update\",\"institution:delete\",\"thematic:add\",\"item_language:delete\",\"publisher:add\",\"coirault:view\",\"item_informer:add\",\"coupe:update\",\"legal_rights:view\",\"legal_rights:add\",\"domain_song:delete\",\"collection_informer:view\",\"domain_music:delete\",\"enumeration:update\",\"instrument:add\",\"globalsearch\",\"domain_song:add\",\"document_fonds:add\",\"collection:add\",\"item_musical_group:add\",\"publisher:delete\",\"item_transcoding_flag:delete\",\"item_marker:add\",\"location_gis:view\",\"mediatype:update\",\"language:update\",\"item_domain_music:view\",\"performance_collection:delete\",\"institution:update\",\"performance_collection:view\",\"musical_group:add\",\"document_fonds:view\",\"item_thematic:update\",\"location:update\",\"legal_rights:delete\",\"item_informer:update\",\"item_author:add\",\"item_transcoding_flag:view\",\"recording_context:update\",\"item_language:view\",\"collection_location:delete\",\"collection:view\",\"item_domain_song:delete\",\"item_dance:add\",\"authority:delete\",\"thematic:delete\",\"item_dance:update\",\"block:view\",\"block:add\",\"block:delete\",\"block:update\",\"mission:view\",\"mission:add\",\"mission:update\",\"mission:delete\",\"keyword:add\",\"keyword:delete\",\"keyword:update\",\"keyword:view\",\"item_keyword:add\",\"item_keyword:delete\",\"item_keyword:update\",\"item_keyword:view\"]",
"applyPolicies": "[\"francoralite-administrators-pol\"]"
}
}
@@ -1917,6 +1965,22 @@
"id": "8529432f-7acc-4f75-bc7e-aa7af2f068aa",
"name": "item_informer:update"
},
+ {
+ "id": "6a4947e5-6936-49cd-84a2-dfe1f907b058",
+ "name": "item_keyword:delete"
+ },
+ {
+ "id": "c95ca5b1-2da4-468e-ac24-a7b666dbbc0e",
+ "name": "item_keyword:view"
+ },
+ {
+ "id": "4eec8675-4b86-4df7-9f7f-7429b131b58c",
+ "name": "item_keyword:add"
+ },
+ {
+ "id": "0390d13a-8896-43d0-9ae1-f687b7fcc6b5",
+ "name": "item_keyword:update"
+ },
{
"id": "835503d8-7873-4139-bbf5-9bd46a4d7555",
"name": "item_marker:delete"
@@ -2029,6 +2093,22 @@
"id": "8d38ebb7-2e06-49e8-83cc-ff0831ec5fe4",
"name": "item_usefulness:update"
},
+ {
+ "id": "bc3ea9f0-08ec-4f9d-baea-1e23a5220168",
+ "name": "keyword:delete"
+ },
+ {
+ "id": "3dcf3e0e-1cf0-4946-af4f-4f0db415a0e1",
+ "name": "keyword:view"
+ },
+ {
+ "id": "e2d47bca-3b53-400e-82b9-e70cad0d81d7",
+ "name": "keyword:add"
+ },
+ {
+ "id": "a6f202d2-1d4d-4b80-b90f-1f512b5a933d",
+ "name": "keyword:update"
+ },
{
"id": "c098d34e-a341-4d3b-b4dd-eb3551b96ebd",
"name": "language:delete"
diff --git a/francoralite/apps/francoralite_api/migrations/0010_itemkeyword_keyword.py b/francoralite/apps/francoralite_api/migrations/0010_itemkeyword_keyword.py
new file mode 100644
index 00000000..0783a297
--- /dev/null
+++ b/francoralite/apps/francoralite_api/migrations/0010_itemkeyword_keyword.py
@@ -0,0 +1,41 @@
+# Generated by Django 3.1.14 on 2023-12-11 17:49
+
+from django.db import migrations, models
+import django.db.models.deletion
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('francoralite_api', '0009_block'),
+ ]
+
+ operations = [
+ migrations.CreateModel(
+ name='Keyword',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('name', models.CharField(max_length=255, unique=True, verbose_name='Nom')),
+ ('notes', models.TextField(blank=True, null=True, verbose_name='Notes')),
+ ],
+ options={
+ 'verbose_name_plural': 'keywords',
+ 'db_table': 'api_keyword',
+ 'ordering': ['name'],
+ },
+ ),
+ migrations.CreateModel(
+ name='ItemKeyword',
+ fields=[
+ ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
+ ('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='francoralite_api.item', verbose_name='Item')),
+ ('keyword', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='francoralite_api.keyword', verbose_name='Keyword')),
+ ],
+ options={
+ 'verbose_name_plural': 'item_keywords',
+ 'db_table': 'api_item_keyword',
+ 'ordering': [],
+ 'unique_together': {('item', 'keyword')},
+ },
+ ),
+ ]
diff --git a/francoralite/apps/francoralite_api/models/__init__.py b/francoralite/apps/francoralite_api/models/__init__.py
index 5d79401a..904d6f0f 100644
--- a/francoralite/apps/francoralite_api/models/__init__.py
+++ b/francoralite/apps/francoralite_api/models/__init__.py
@@ -21,6 +21,7 @@
from .item_domain_tale import ItemDomainTale
from .item_usefulness import ItemUsefulness
from .item_dance import ItemDance
+from .item_keyword import ItemKeyword
from .item_thematic import ItemThematic
from .item_language import ItemLanguage
from .item_musical_organization import ItemMusicalOrganization
@@ -46,6 +47,7 @@
from .item_performance import ItemPerformance
from .musical_organization import MusicalOrganization
from .musical_group import MusicalGroup
+from .keyword import Keyword
from .thematic import Thematic
from .dance import Dance
from .domain_tale import DomainTale
diff --git a/francoralite/apps/francoralite_api/models/item_keyword.py b/francoralite/apps/francoralite_api/models/item_keyword.py
new file mode 100644
index 00000000..993bcf5c
--- /dev/null
+++ b/francoralite/apps/francoralite_api/models/item_keyword.py
@@ -0,0 +1,31 @@
+# -*- coding: utf-8 -*-
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+# Authors: Luc LEGER / Coopérative ARTEFACTS
+
+
+from django.db import models
+from django.utils.translation import gettext_lazy as _
+
+# Add nested/related tables
+from .item import Item
+from .keyword import Keyword
+
+
+class ItemKeyword(models.Model):
+ # Description of the table
+ "Relation between an item and its keywords"
+
+ # List of the fields
+ keyword = models.ForeignKey(Keyword, verbose_name=_(
+ 'Keyword'), on_delete=models.CASCADE)
+ item = models.ForeignKey(Item, verbose_name=_('Item'),
+ on_delete=models.CASCADE)
+
+ class Meta:
+ app_label = 'francoralite_api'
+ db_table = 'api_item_keyword'
+ verbose_name_plural = _('item_keywords')
+ ordering = []
+ unique_together = (('item', 'keyword'), )
diff --git a/francoralite/apps/francoralite_api/models/keyword.py b/francoralite/apps/francoralite_api/models/keyword.py
new file mode 100644
index 00000000..019c5974
--- /dev/null
+++ b/francoralite/apps/francoralite_api/models/keyword.py
@@ -0,0 +1,27 @@
+# -*- coding: utf-8 -*-
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+# Authors: Luc LEGER / Cooperative Artefacts
+
+
+from django.db import models
+from django.utils.translation import gettext_lazy as _
+
+
+class Keyword(models.Model):
+ # Description of the table
+ "Keyword used by a deposit (for each item)"
+
+ # List of the fields
+ name = models.CharField(_('Nom'), unique=True, max_length=255)
+ notes = models.TextField(_('Notes'), null=True, blank=True)
+
+ class Meta:
+ app_label = 'francoralite_api'
+ db_table = 'api_keyword'
+ verbose_name_plural = _('keywords')
+ ordering = ['name']
+
+ def __unicode__(self):
+ return self.name
diff --git a/francoralite/apps/francoralite_api/serializers/item_keyword.py b/francoralite/apps/francoralite_api/serializers/item_keyword.py
new file mode 100644
index 00000000..9c5d3cca
--- /dev/null
+++ b/francoralite/apps/francoralite_api/serializers/item_keyword.py
@@ -0,0 +1,57 @@
+# -*- coding: utf-8 -*-
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+# Authors: Luc LEGER / Coopérative ARTEFACTS
+from rest_framework import serializers
+
+from .asymetric_related_field import AsymetricRelatedField
+
+# Add nested/related serializers
+from .item import ItemSerializer
+from .keyword import KeywordSerializer
+
+from ..models.item_keyword import (
+ ItemKeyword as ItemKeywordModel)
+
+
+class ItemKeywordSerializer(serializers.ModelSerializer):
+ """
+ Common serializer for all ItemKeyword actions
+ """
+
+ # fields of the serializer
+ item = AsymetricRelatedField.from_serializer(
+ ItemSerializer, kwargs={'required': True})
+ keyword = AsymetricRelatedField.from_serializer(
+ KeywordSerializer, kwargs={'required': True})
+
+ class Meta:
+ model = ItemKeywordModel
+ fields = '__all__'
+
+ # TODO : use it with with a complete create
+ # def create(self, validated_data):
+ # """
+ # Overriding the default create method of the Model serializer.
+ # :param validated_data: data containing all the details
+ # of ItemKeyword
+ # :return: returns a successfully created ext_collection record
+ # """
+ #
+ # # FIXIT : Add nested/related data
+ # collection_data = validated_data.pop('collection')
+ # # Create an oject Mediacollection with the data converted in dict
+ # collection = MediacollectionModel.objects.create(**collection_data)
+ #
+ # collector_data = validated_data.pop('collector')
+ # # Create an oject collector (Authority)
+ # # with the data converted in dict
+ # collector = AuthorityModel.objects.create(**collector_data)
+ #
+ # # Create an oject item_keywords
+ # item_keywords = \
+ # ItemKeywordModel.objects.create(
+ # collection=collection, collector=collector, **validated_data)
+ #
+ # return item_keywords
diff --git a/francoralite/apps/francoralite_api/serializers/keyword.py b/francoralite/apps/francoralite_api/serializers/keyword.py
new file mode 100644
index 00000000..2f326cd0
--- /dev/null
+++ b/francoralite/apps/francoralite_api/serializers/keyword.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+# Authors: Luc LEGER / Coopérative ARTEFACTS
+
+from rest_framework import serializers
+from rest_framework.validators import UniqueValidator
+from ..models.keyword import (
+ Keyword as KeywordModel)
+
+
+class KeywordSerializer(serializers.ModelSerializer):
+ """
+ Common serializer for all Keyword actions
+ """
+
+ name = serializers.CharField(
+ required=True,
+ validators=[UniqueValidator(queryset=KeywordModel.objects.all())]
+ )
+ notes = serializers.CharField(required=False, allow_blank=True)
+
+ class Meta:
+ model = KeywordModel
+ fields = '__all__'
diff --git a/francoralite/apps/francoralite_api/tests/factories/item_keyword.py b/francoralite/apps/francoralite_api/tests/factories/item_keyword.py
new file mode 100644
index 00000000..b12d7d40
--- /dev/null
+++ b/francoralite/apps/francoralite_api/tests/factories/item_keyword.py
@@ -0,0 +1,29 @@
+# -*- coding: utf-8 -*-
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+# Authors: Luc LEGER / Coopérative ARTEFACTS
+"""
+item_keyword factory to execute tests
+"""
+
+import factory
+from ...models.item_keyword import ItemKeyword
+# import nested/related factories
+from .keyword import KeywordFactory
+
+
+class ItemKeywordFactory(factory.django.DjangoModelFactory):
+ """
+ ItemKeyword factory
+ """
+
+ class Meta:
+ model = ItemKeyword
+ django_get_or_create = (
+ 'item',
+ 'keyword',)
+
+ # Nested/related factories
+ item = factory.SubFactory("francoralite.apps.francoralite_api.tests.factories.item.ItemFactory")
+ keyword = factory.SubFactory(KeywordFactory)
diff --git a/francoralite/apps/francoralite_api/tests/factories/keyword.py b/francoralite/apps/francoralite_api/tests/factories/keyword.py
new file mode 100644
index 00000000..10d24294
--- /dev/null
+++ b/francoralite/apps/francoralite_api/tests/factories/keyword.py
@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+# Authors: Luc LEGER / Coopérative ARTEFACTS
+"""
+Keyword factory to execute tests
+"""
+
+import factory
+from ...models.keyword import Keyword
+
+
+class KeywordFactory(factory.django.DjangoModelFactory):
+ """
+ Keyword factory
+ """
+
+ class Meta:
+ model = Keyword
+
+ name = factory.Sequence(lambda n: 'theme%d' % n)
+ notes = factory.Faker('paragraph', nb_sentences=1)
diff --git a/francoralite/apps/francoralite_api/tests/test_item_keyword.py b/francoralite/apps/francoralite_api/tests/test_item_keyword.py
new file mode 100644
index 00000000..d89db814
--- /dev/null
+++ b/francoralite/apps/francoralite_api/tests/test_item_keyword.py
@@ -0,0 +1,175 @@
+# -*- coding: utf-8 -*-
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+# Authors: Luc LEGER / Coopérative ARTEFACTS
+
+"""
+Item Keyword tests
+"""
+
+import factory
+import pytest
+
+from django.urls import reverse
+from parameterized import parameterized
+from rest_framework import status
+from rest_framework.test import APITestCase
+
+from .factories.item_keyword import ItemKeywordFactory
+from .fake_data.fake_sound import CleanMediaMixin
+from ..models.item_keyword import ItemKeyword
+
+from .keycloak import get_token
+
+# Expected structure for Item_keyword objects
+ITEMKEYWORD_STRUCTURE = [
+ ('id', int),
+ ('item', dict),
+ ('keyword', dict),
+]
+
+# Expected keys for MODEL objects
+ITEMKEYWORD_FIELDS = sorted(
+ [item[0] for item in ITEMKEYWORD_STRUCTURE])
+
+
+@pytest.mark.django_db
+class TestItemKeywordList(CleanMediaMixin, APITestCase):
+ """
+ This class manage all ItemKeyword tests
+ """
+
+ def setUp(self):
+ """
+ Run needed commands to have a fully working project
+ """
+ get_token(self)
+
+ # Create a set of sample data
+ ItemKeywordFactory.create_batch(6)
+
+ def test_can_get_item_keyword_list(self):
+ """
+ Ensure ItemKeyword objects exists
+ """
+ # kwargs for the related tables
+ url = reverse('itemkeyword-list', kwargs={
+ 'item_pk': 1})
+
+ # ORM side
+ item_keywords = ItemKeyword.objects.all()
+ self.assertEqual(len(item_keywords), 6)
+
+ # API side
+ response = self.client.get(url)
+
+ self.assertIsInstance(response.data, list)
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertEqual(len(response.data), 1)
+
+ @parameterized.expand(ITEMKEYWORD_STRUCTURE)
+ def test_has_valid_item_keyword_values(self, attribute, attribute_type):
+ """
+ Ensure ItemKeyword objects have valid values
+ """
+
+ # kwargs for the related tables
+ url = reverse('itemkeyword-list', kwargs={
+ 'item_pk': 1})
+ response = self.client.get(url)
+
+ self.assertIsInstance(response.data, list)
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+
+ for item_keyword in response.data:
+ # Check only expected attributes returned
+ self.assertEqual(
+ sorted(item_keyword.keys()), ITEMKEYWORD_FIELDS)
+
+ # Ensure type of each attribute
+ if attribute_type == str:
+ self.assertIsInstance(item_keyword[attribute], str)
+ else:
+ self.assertIsInstance(item_keyword[attribute], attribute_type)
+ self.assertIsNot(item_keyword[attribute], '')
+
+ def test_get_an_item_keyword(self):
+ """
+ Ensure we can get an ItemKeyword objects
+ using an existing id
+ """
+
+ item = ItemKeyword.objects.first()
+ # kwargs for the related tables
+ url = reverse('itemkeyword-detail', kwargs={
+ 'item_pk': item.item.id,
+ 'pk': item.keyword.id})
+ response = self.client.get(url)
+
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertIsInstance(response.data, dict)
+
+ def test_create_an_item_keyword(self):
+ """
+ Ensure we can create an ItemKeyword object
+ """
+
+ data = factory.build(
+ dict,
+ FACTORY_CLASS=ItemKeywordFactory)
+
+ # Convert the related entity in dictionnary.
+ # Then they will be easily converted in JSON format.
+ data['item'] = 1
+ data['keyword'] = 2
+
+ url = reverse('itemkeyword-list', kwargs={
+ 'item_pk': data['item']})
+ response = self.client.post(url, data, format='json')
+
+ # Check only expected attributes returned
+ self.assertEqual(response.status_code, status.HTTP_201_CREATED)
+ self.assertIsInstance(response.data, dict)
+ self.assertEqual(
+ sorted(response.data.keys()),
+ ITEMKEYWORD_FIELDS)
+
+ # kwargs for the related tables
+ url = reverse(
+ 'itemkeyword-detail',
+ kwargs={'item_pk': response.data['item']['id'],
+ 'pk': response.data['id']}
+ )
+ response_get = self.client.get(url)
+
+ self.assertEqual(response_get.status_code, status.HTTP_200_OK)
+ self.assertIsInstance(response_get.data, dict)
+
+ def test_delete_an_item_keyword(self):
+ """
+ Ensure we can delete an ItemKeyword object
+ """
+
+ item = ItemKeyword.objects.first()
+
+ # Delete this object
+ # kwargs for the related tables
+ url = reverse(
+ 'itemkeyword-detail', kwargs={
+ 'item_pk': item.item.id,
+ 'pk': item.keyword.id}
+ )
+ response = self.client.delete(url)
+
+ self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
+
+ # Ensure ItemKeyword removed
+ # kwargs for the related tables
+ url_get = reverse(
+ 'itemkeyword-detail', kwargs={
+ 'item_pk': item.item.id,
+ 'pk': item.keyword.id}
+ )
+ response_get = self.client.get(url_get)
+ self.assertEqual(response_get.status_code, status.HTTP_404_NOT_FOUND)
diff --git a/francoralite/apps/francoralite_api/tests/test_keyword.py b/francoralite/apps/francoralite_api/tests/test_keyword.py
new file mode 100644
index 00000000..5bd4b8d7
--- /dev/null
+++ b/francoralite/apps/francoralite_api/tests/test_keyword.py
@@ -0,0 +1,211 @@
+# -*- coding: utf-8 -*-
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+# Authors: Luc LEGER / Coopérative ARTEFACTS
+
+"""
+Keyword tests
+"""
+
+import factory
+import pytest
+
+from django.urls import reverse
+from parameterized import parameterized
+from rest_framework import status
+from rest_framework.test import APITestCase
+
+from .factories.keyword import KeywordFactory
+from ..models.keyword import Keyword
+
+from .keycloak import get_token
+
+# Expected structure for Keyword objects
+KEYWORD_STRUCTURE = [
+ ('id', int),
+ ('name', str),
+ ('notes', str),
+]
+
+# Expected keys for MODEL objects
+KEYWORD_FIELDS = sorted(
+ [item[0] for item in KEYWORD_STRUCTURE])
+
+
+@pytest.mark.django_db
+class TestKeywordList(APITestCase):
+ """
+ This class manage all Keyword tests
+ """
+
+ def setUp(self):
+ """
+ Run needed commands to have a fully working project
+ """
+ get_token(self, username="administrateur")
+
+ # Create a set of sample data
+ KeywordFactory.create_batch(6)
+
+ def test_can_get_keyword_list(self):
+ """
+ Ensure Keyword objects exists
+ """
+ url = reverse('keyword-list')
+
+ # ORM side
+ keywords = Keyword.objects.all()
+ self.assertEqual(len(keywords), 6)
+
+ # API side
+ response = self.client.get(url)
+
+ self.assertIsInstance(response.data, list)
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertEqual(len(response.data), 6)
+
+ @parameterized.expand(KEYWORD_STRUCTURE)
+ def test_has_valid_keyword_values(
+ self, attribute, attribute_type):
+ """
+ Ensure Keyword objects have valid values
+ """
+
+ url = reverse('keyword-list')
+ response = self.client.get(url)
+
+ self.assertIsInstance(response.data, list)
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+
+ for keyword in response.data:
+ # Check only expected attributes returned
+ self.assertEqual(
+ sorted(
+ keyword.keys()), KEYWORD_FIELDS)
+
+ # Ensure type of each attribute
+ if attribute_type == str:
+ self.assertIsInstance(keyword[attribute], str)
+ else:
+ self.assertIsInstance(
+ keyword[attribute], attribute_type)
+ self.assertIsNot(keyword[attribute], '')
+
+ def test_get_an_keyword(self):
+ """
+ Ensure we can get an Keyword objects
+ using an existing id
+ """
+
+ item = Keyword.objects.first()
+ url = reverse('keyword-detail',
+ kwargs={'pk': item.id})
+ response = self.client.get(url)
+
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertIsInstance(response.data, dict)
+
+ def test_create_an_keyword(self):
+ """
+ Ensure we can create an Keyword object
+ """
+
+ data = factory.build(
+ dict,
+ FACTORY_CLASS=KeywordFactory)
+ url = reverse('keyword-list')
+ print("+-+-+-+")
+ print(data)
+ response = self.client.post(url, data, format='json')
+
+ # Check only expected attributes returned
+ self.assertEqual(response.status_code, status.HTTP_201_CREATED)
+ self.assertIsInstance(response.data, dict)
+ self.assertEqual(
+ sorted(response.data.keys()),
+ KEYWORD_FIELDS)
+
+ url = reverse(
+ 'keyword-detail',
+ kwargs={'pk': response.data['id']}
+ )
+ response_get = self.client.get(url)
+
+ self.assertEqual(response_get.status_code, status.HTTP_200_OK)
+ self.assertIsInstance(response_get.data, dict)
+
+ def test_update_an_keyword(self):
+ """
+ Ensure we can update an Keyword object
+ """
+
+ item = Keyword.objects.first()
+ self.assertNotEqual(item.name, 'foobar_test_put')
+
+ # Get existing object from API
+ url_get = reverse(
+ 'keyword-detail',
+ kwargs={'pk': item.id})
+ data = self.client.get(url_get).data
+
+ data['name'] = 'foobar_test_put'
+ url = reverse(
+ 'keyword-detail',
+ kwargs={'pk': item.id})
+ response = self.client.put(url, data, format='json')
+
+ # Ensure new name returned
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertIsInstance(response.data, dict)
+ self.assertEqual(
+ sorted(response.data.keys()),
+ KEYWORD_FIELDS)
+
+ self.assertEqual(response.data['name'], 'foobar_test_put')
+
+ def test_patch_an_keyword(self):
+ """
+ Ensure we can patch an Keyword object
+ """
+
+ item = Keyword.objects.first()
+
+ self.assertNotEqual(item.name, 'foobar_test_patch')
+
+ data = {'name': 'foobar_test_patch'}
+ url = reverse(
+ 'keyword-detail',
+ kwargs={'pk': item.id})
+ response = self.client.patch(url, data, format='json')
+
+ # Ensure new name returned
+ self.assertEqual(response.status_code, status.HTTP_200_OK)
+ self.assertIsInstance(response.data, dict)
+ self.assertEqual(
+ sorted(response.data.keys()),
+ KEYWORD_FIELDS)
+
+ self.assertEqual(response.data['name'], 'foobar_test_patch')
+
+ def test_delete_an_keyword(self):
+ """
+ Ensure we can delete an Keyword object
+ """
+
+ item = Keyword.objects.first()
+
+ # Delete this object
+ url = reverse(
+ 'keyword-detail',
+ kwargs={'pk': item.id})
+ response = self.client.delete(url)
+
+ self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
+
+ # Ensure Keyword removed
+ url_get = reverse(
+ 'keyword-detail',
+ kwargs={'pk': item.id})
+ response_get = self.client.get(url_get)
+ self.assertEqual(response_get.status_code, status.HTTP_404_NOT_FOUND)
diff --git a/francoralite/apps/francoralite_api/urls.py b/francoralite/apps/francoralite_api/urls.py
index 220f6a50..6e8a65b3 100644
--- a/francoralite/apps/francoralite_api/urls.py
+++ b/francoralite/apps/francoralite_api/urls.py
@@ -42,12 +42,14 @@
item_domain_tale,
item_domain_vocal,
item_informer,
+ item_keyword,
item_language,
item_musical_group,
item_musical_organization,
item_performance,
item_thematic,
item_usefulness,
+ keyword,
language,
legal_rights,
location_gis,
@@ -151,6 +153,9 @@
router.register(r'musical_group',
musical_group.MusicalGroupViewSet,
basename='musicalgroup')
+router.register(r'keyword',
+ keyword.KeywordViewSet,
+ basename='keyword')
router.register(r'thematic',
thematic.ThematicViewSet,
basename='thematic')
@@ -249,6 +254,8 @@
r'dance', item_dance.ItemDanceViewSet)
item_router.register(
r'language', item_language.ItemLanguageViewSet)
+item_router.register(
+ r'keyword', item_keyword.ItemKeywordViewSet)
item_router.register(
r'thematic', item_thematic.ItemThematicViewSet)
item_router.register(
diff --git a/francoralite/apps/francoralite_api/views/item_keyword.py b/francoralite/apps/francoralite_api/views/item_keyword.py
new file mode 100644
index 00000000..fb231cc5
--- /dev/null
+++ b/francoralite/apps/francoralite_api/views/item_keyword.py
@@ -0,0 +1,36 @@
+# -*- coding: utf-8 -*-
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+# Authors: Luc LEGER / Coopérative ARTEFACTS
+
+from django.db.models.query import QuerySet
+from rest_framework import viewsets
+from ..models.item_keyword import (
+ ItemKeyword as ItemKeywordModel)
+from ..serializers.item_keyword import ItemKeywordSerializer
+
+
+class ItemKeywordViewSet(viewsets.ModelViewSet):
+ """
+ ItemKeyword management
+ """
+
+ queryset = ItemKeywordModel.objects.all()
+ serializer_class = ItemKeywordSerializer
+
+ keycloak_scopes = {
+ 'GET': 'item_keyword:view',
+ 'POST': 'item_keyword:add',
+ 'PATCH': 'item_keyword:update',
+ 'PUT': 'item_keyword:update',
+ 'DELETE': 'item_keyword:delete'
+ }
+
+ def get_queryset(self):
+ queryset = self.queryset
+ if isinstance(queryset, QuerySet):
+ # Ensure queryset is re-evaluated on each request.
+ queryset = ItemKeywordModel.objects.filter(
+ item_id=self.kwargs['item_pk'])
+ return queryset
diff --git a/francoralite/apps/francoralite_api/views/keyword.py b/francoralite/apps/francoralite_api/views/keyword.py
new file mode 100644
index 00000000..a55fef2a
--- /dev/null
+++ b/francoralite/apps/francoralite_api/views/keyword.py
@@ -0,0 +1,33 @@
+# -*- coding: utf-8 -*-
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see .
+#
+# Authors: Luc LEGER / Coopérative ARTEFACTS
+
+
+from django_filters.rest_framework import DjangoFilterBackend
+from rest_framework import filters
+from rest_framework import viewsets
+
+from ..models.keyword import Keyword as KeywordModel
+from ..serializers.keyword import KeywordSerializer
+
+
+class KeywordViewSet(viewsets.ModelViewSet):
+ """
+ Keyword management
+ """
+
+ queryset = KeywordModel.objects.all()
+ serializer_class = KeywordSerializer
+
+ filter_backends = (DjangoFilterBackend, filters.SearchFilter)
+ search_fields = ('name',)
+
+ keycloak_scopes = {
+ 'GET': 'keyword:view',
+ 'POST': 'keyword:add',
+ 'PATCH': 'keyword:update',
+ 'PUT': 'keyword:update',
+ 'DELETE': 'keyword:delete',
+ }
diff --git a/francoralite/middleware/keycloak_mw.py b/francoralite/middleware/keycloak_mw.py
index 8dac6dfc..807f3213 100644
--- a/francoralite/middleware/keycloak_mw.py
+++ b/francoralite/middleware/keycloak_mw.py
@@ -139,6 +139,7 @@ def process_view(self, request, view_func, view_args, view_kwargs):
'item_domain_tale:view',
'item_domain_vocal:view',
'item_informer:view',
+ 'item_keyword:view',
'item_language:view',
'item_musical_group:view',
'item_musical_organization:view',
@@ -146,6 +147,7 @@ def process_view(self, request, view_func, view_args, view_kwargs):
'item_thematic:view',
'item_usefulness:view',
'item:view',
+ 'keyword:view',
'language:view',
'legal_rights:view',
'location_gis:view',