-
Notifications
You must be signed in to change notification settings - Fork 50
/
permissions.py
107 lines (85 loc) · 3.68 KB
/
permissions.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# -*- coding: utf-8 -*-
#
# Copyright (C) 2018 CERN.
#
# invenio-app-ils is free software; you can redistribute it and/or modify it
# under the terms of the MIT License; see LICENSE file for more details.
"""ILS records permissions."""
from flask import current_app
from flask_principal import ActionNeed, RoleNeed, UserNeed
from invenio_access import Permission, any_user
from six import string_types
from invenio_app_ils.permissions import backoffice_access_action
create_records_action = ActionNeed("create-records")
def record_create_permission_factory(record=None):
"""Record create permission factory."""
return RecordPermission(record=record, action="create")
def record_update_permission_factory(record=None):
"""Record update permission factory."""
return RecordPermission(record=record, action="update")
def record_delete_permission_factory(record=None):
"""Record delete permission factory."""
return RecordPermission(record=record, action="delete")
def record_read_permission_factory(record=None):
"""Record read permission factory."""
return RecordPermission(record=record, action="read")
class RecordPermission(Permission):
"""Record permission.
- Create action given to librarian, admin and specified users.
- Read access given to everyone with possibility to hide.
- Delete access to admin and specified users.
"""
def __init__(self, record, action):
"""Constructor."""
self.record = record
self.current_action = action
record_needs = self.collect_needs()
super().__init__(*record_needs)
def collect_needs(self):
"""Collect permission policy per action."""
if self.current_action == "read":
return self.read_permissions()
elif self.current_action == "create":
return [create_records_action, backoffice_access_action]
elif self.current_action == "update":
return self.record_needs() + [backoffice_access_action]
else:
return self.record_needs()
def read_permissions(self):
"""Define read permission policy per record."""
if self.is_public():
return [any_user]
else:
return self.record_needs() + [backoffice_access_action]
def record_explicit_restrictions(self):
"""Return the list of user ids/roles allowed for the given action."""
if current_app.config.get("ILS_RECORDS_EXPLICIT_PERMISSIONS_ENABLED"):
return self.record.get("_access", {}).get(self.current_action, [])
return []
def record_needs(self):
"""Create needs of the record."""
needs = []
for access_entity in self.record_explicit_restrictions():
try:
if isinstance(access_entity, string_types):
needs.append(UserNeed(int(access_entity)))
elif isinstance(access_entity, int):
needs.append(UserNeed(access_entity))
except ValueError:
needs.append(RoleNeed(access_entity.lower()))
return needs
def is_public(self):
"""Check if the record is fully public.
Explicit permission = `_access` field
Implicit permission = `restricted` field
Explicit, when defined, takes precedence over implicit which is
ignored.
The record is public when `_access.read` is not defined and
`restricted` is False.
"""
has_explicit_perm = current_app.config.get(
"ILS_RECORDS_EXPLICIT_PERMISSIONS_ENABLED"
) and self.record.get("_access", {}).get("read", [])
if not has_explicit_perm:
return self.record.get("restricted", False) is False
return False