Package: oarepo-enrollment-permissions
oarepo-enrollment-permissionsWork in progress, do not use yetOArepo Enrollment Permissions library is a bridge between oarepo-enrollment library and invenio records. It provides
means to assign user permission to perform actions upon a record (list, update, delete, custom actions).Installationpipinstalloarepo-enrollment-permissionsUsageIn your rest configuration, setsearch_classclass either tooarepo_enrollment_permissions.RecordsSearchor to a class inheriting
fromoarepo_enrollment_permissions.RecordsSearchMixin.If yourread_permission_factory_impis notcheck_elasticsearch, be sure to include the result
ofoarepo_enrollment_permissions.read_permission_factoryin your permission factory - see below for details).Useoarepo_enrollment_permissions.update_permission_factoryas your update permission factory (or call if from
your own permission factory - see below for details).Useoarepo_enrollment_permissions.delete_permission_factoryas your delete permission factory (or call if from
your own permission factory - see below for details).Useoarepo_enrollment_permissions.create_permission_factoryas your create permission factory (or call if from
your own permission factory - see below for details).Now you are all set, no one has an access until granted.Granting accessAccess is granted via enrollment process. The following enrollment types are available:CollectionGives rights to manipulate with a collection. A collection is defined as records with the same values at a given json
pointer (specified in configuration or passed to the enroll call).To grant access to a collection on command-line, call:inveniooarepo:enrollcollection<email><collectionkey>actions=read,update,delete,createIf you want to perform the same in REST API, call:{
    'enrollment_type': "collection",
    'recipient': "someone@example.com",
    'external_key': 'test',
    'operation': 'read'
    // either comma separated or an array
}Single recordYou can grant rights to a single record as well. To do that, invoke:inveniooarepo:enrollrecord<email><record_uuid>actions=read,update,deleteAgain, the same can be achieved via API:{
    'enrollment_type': "record",
    'recipient': "someone@example.com",
    'external_key': '1234-...-1234',
    'operation': 'read'
    // either comma separated or an array
}Listing and Revoking accessSeeoarepo-enrollmentfor help with these.Customizing search/listing permissionsThe provided search class (or mixin) behaves a bit differently than the default invenio RecordsSearch. For anonymous
users, the default behaviour is to return empty collection. For authenticated users, enrollments are inspected and are
used to filter the records.This process can be customized via:fromoarepo_enrollment_permissionsimportRecordsSearchclassMyRecordsSearch(RecordsSearch):classMeta:# put customizations in herepassAnonymous userIf anonymous user should get access to all/some records, specifydefault_anonymous_filterproperty on Meta class.This property can be either elasticsearch query (Q, Bool) or it might be a function with a signaturedefault_anonymous_filter(search=<RecordsSearch>, **kwargs) -> Union[Q, Bool]. The result of the function is passed
to the default elasticsearch filter.Authenticated userOnMetaclass, invenio supports passingdefault_filter. For convenience reasons this library
addsdefault_filter_factory(search=<RecordsSearch>, **kwargs) -> Union[Q, Bool]that takes precedence if used.At first the library looks at all successful enrollments of the user whose handler containsget_elasticsearch_filterclass method. Then these handlers are called (with the enrollments as parameters) to get
filtering query.There might be adefault_filterdefined on the search. If it is, the queries from handlers are combined with the
default filter depending on the value ofdefault_filter_modeMetaproperty:or(the default value) - user is granted access if eitherdefault_filteror at least one of handler filters
matchand- user is granted access ifdefault_filterand at least one of handler filters match.If there is nodefault_filterused, user is granted access to the record if at least one of handler filters match.APIImplementing custom permission-enabled enrollment handlerTo implement a custom permission-enabled handler, add the following methods:fromoarepo_enrollmentsimportEnrollmentHandlerfrominvenio_accounts.modelsimportUserfromelasticsearch_dslimportQclassMyCollectionAccess(EnrollmentHandler):defenroll(self,user:User,role=None,**kwargs)->None:# no handling required for collectionspassdefrevoke(self,user:User,role=None,**kwargs)->None:# no handling required for collectionspassdefget_elasticsearch_filter(self,search=None,queryset=None,**kwargs):collections=[]forenrollmentinqueryset:collection=enrollment.extra_data.get('collection')ifcollection:collections.append(collection)ifcollections:returnQ('terms',collections=collections)returnNonedefpost_filter_elasticsearch_result(self,search=None,result=None,**kwargs):# can be used to hide metadata from resultspassConfigurationCollection permissions configurationTo use builtin collection permissions, you have to specify the path or query for filtering collections. There are two
ways of doing that - global and per-search.Global configurationIn your config file, set:OAREPO_ENROLLMENT_PERMISSIONS_COLLECTION_FILTER='collection'This can be either path in the document that will be placed toQ('terms', <path> = [allowed collections])or it might be a callable(search=None, collections=None, **)that should return either elasticsearchQorBool.Local configurationAlternatively, define the path/callable on Meta:fromoarepo_enrollment_permissionsimportRecordsSearchfromelasticsearch_dslimportQclassMyRecordsSearch(RecordsSearch):classMeta:permissions_collection_filter='collections'# or@classmethoddefpermissions_collection_filter(cls,search=None,collections=None,**kwargs):returnQ('terms',collection__key=collections)Record permissions configurationNormally there is no need to override record configuration.