oarepo-runtime 1.10.3__py3-none-any.whl → 2.0.0.dev4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. oarepo_runtime/__init__.py +24 -0
  2. oarepo_runtime/api.py +210 -0
  3. oarepo_runtime/cli/__init__.py +10 -21
  4. oarepo_runtime/cli/search.py +34 -0
  5. oarepo_runtime/config.py +98 -13
  6. oarepo_runtime/ext.py +64 -82
  7. oarepo_runtime/proxies.py +21 -5
  8. oarepo_runtime/records/__init__.py +11 -50
  9. oarepo_runtime/records/drafts.py +24 -18
  10. oarepo_runtime/records/mapping.py +84 -0
  11. oarepo_runtime/records/pid_providers.py +43 -7
  12. oarepo_runtime/records/systemfields/__init__.py +15 -33
  13. oarepo_runtime/records/systemfields/mapping.py +41 -24
  14. oarepo_runtime/records/systemfields/publication_status.py +61 -0
  15. oarepo_runtime/services/__init__.py +12 -0
  16. oarepo_runtime/services/config/__init__.py +15 -21
  17. oarepo_runtime/services/config/link_conditions.py +69 -75
  18. oarepo_runtime/services/config/permissions.py +62 -0
  19. oarepo_runtime/services/facets/__init__.py +12 -33
  20. oarepo_runtime/services/facets/params.py +45 -110
  21. oarepo_runtime/services/records/__init__.py +14 -1
  22. oarepo_runtime/services/records/links.py +21 -11
  23. oarepo_runtime/services/records/mapping.py +42 -0
  24. oarepo_runtime/services/results.py +98 -109
  25. oarepo_runtime/services/schema/__init__.py +12 -44
  26. oarepo_runtime/services/schema/i18n.py +47 -22
  27. oarepo_runtime/services/schema/i18n_ui.py +61 -24
  28. {oarepo_runtime-1.10.3.dist-info → oarepo_runtime-2.0.0.dev4.dist-info}/METADATA +10 -21
  29. oarepo_runtime-2.0.0.dev4.dist-info/RECORD +32 -0
  30. {oarepo_runtime-1.10.3.dist-info → oarepo_runtime-2.0.0.dev4.dist-info}/WHEEL +1 -2
  31. oarepo_runtime-2.0.0.dev4.dist-info/entry_points.txt +5 -0
  32. oarepo_runtime/cli/assets.py +0 -145
  33. oarepo_runtime/cli/base.py +0 -25
  34. oarepo_runtime/cli/cf.py +0 -15
  35. oarepo_runtime/cli/check.py +0 -167
  36. oarepo_runtime/cli/configuration.py +0 -51
  37. oarepo_runtime/cli/fixtures.py +0 -167
  38. oarepo_runtime/cli/index.py +0 -272
  39. oarepo_runtime/cli/permissions/__init__.py +0 -6
  40. oarepo_runtime/cli/permissions/base.py +0 -26
  41. oarepo_runtime/cli/permissions/evaluate.py +0 -63
  42. oarepo_runtime/cli/permissions/list.py +0 -239
  43. oarepo_runtime/cli/permissions/search.py +0 -121
  44. oarepo_runtime/cli/validate.py +0 -150
  45. oarepo_runtime/datastreams/__init__.py +0 -38
  46. oarepo_runtime/datastreams/asynchronous.py +0 -247
  47. oarepo_runtime/datastreams/catalogue.py +0 -150
  48. oarepo_runtime/datastreams/datastreams.py +0 -152
  49. oarepo_runtime/datastreams/errors.py +0 -54
  50. oarepo_runtime/datastreams/ext.py +0 -41
  51. oarepo_runtime/datastreams/fixtures.py +0 -265
  52. oarepo_runtime/datastreams/json.py +0 -4
  53. oarepo_runtime/datastreams/readers/__init__.py +0 -39
  54. oarepo_runtime/datastreams/readers/attachments.py +0 -51
  55. oarepo_runtime/datastreams/readers/excel.py +0 -123
  56. oarepo_runtime/datastreams/readers/json.py +0 -27
  57. oarepo_runtime/datastreams/readers/service.py +0 -54
  58. oarepo_runtime/datastreams/readers/yaml.py +0 -14
  59. oarepo_runtime/datastreams/semi_asynchronous.py +0 -91
  60. oarepo_runtime/datastreams/synchronous.py +0 -70
  61. oarepo_runtime/datastreams/transformers.py +0 -18
  62. oarepo_runtime/datastreams/types.py +0 -323
  63. oarepo_runtime/datastreams/utils.py +0 -131
  64. oarepo_runtime/datastreams/writers/__init__.py +0 -21
  65. oarepo_runtime/datastreams/writers/attachments_file.py +0 -92
  66. oarepo_runtime/datastreams/writers/attachments_service.py +0 -118
  67. oarepo_runtime/datastreams/writers/publish.py +0 -70
  68. oarepo_runtime/datastreams/writers/service.py +0 -175
  69. oarepo_runtime/datastreams/writers/utils.py +0 -30
  70. oarepo_runtime/datastreams/writers/validation_errors.py +0 -20
  71. oarepo_runtime/datastreams/writers/yaml.py +0 -56
  72. oarepo_runtime/ext_config.py +0 -67
  73. oarepo_runtime/i18n/__init__.py +0 -3
  74. oarepo_runtime/info/__init__.py +0 -0
  75. oarepo_runtime/info/check.py +0 -95
  76. oarepo_runtime/info/permissions/__init__.py +0 -0
  77. oarepo_runtime/info/permissions/debug.py +0 -191
  78. oarepo_runtime/info/views.py +0 -586
  79. oarepo_runtime/profile.py +0 -60
  80. oarepo_runtime/records/dumpers/__init__.py +0 -8
  81. oarepo_runtime/records/dumpers/edtf_interval.py +0 -38
  82. oarepo_runtime/records/dumpers/multilingual_dumper.py +0 -34
  83. oarepo_runtime/records/entity_resolvers/__init__.py +0 -13
  84. oarepo_runtime/records/entity_resolvers/proxies.py +0 -57
  85. oarepo_runtime/records/mappings/__init__.py +0 -0
  86. oarepo_runtime/records/mappings/rdm_parent_mapping.json +0 -483
  87. oarepo_runtime/records/owners/__init__.py +0 -3
  88. oarepo_runtime/records/owners/registry.py +0 -22
  89. oarepo_runtime/records/relations/__init__.py +0 -22
  90. oarepo_runtime/records/relations/base.py +0 -296
  91. oarepo_runtime/records/relations/internal.py +0 -46
  92. oarepo_runtime/records/relations/lookup.py +0 -28
  93. oarepo_runtime/records/relations/pid_relation.py +0 -102
  94. oarepo_runtime/records/systemfields/featured_file.py +0 -45
  95. oarepo_runtime/records/systemfields/has_draftcheck.py +0 -47
  96. oarepo_runtime/records/systemfields/icu.py +0 -371
  97. oarepo_runtime/records/systemfields/owner.py +0 -115
  98. oarepo_runtime/records/systemfields/record_status.py +0 -35
  99. oarepo_runtime/records/systemfields/selectors.py +0 -98
  100. oarepo_runtime/records/systemfields/synthetic.py +0 -130
  101. oarepo_runtime/resources/__init__.py +0 -4
  102. oarepo_runtime/resources/config.py +0 -12
  103. oarepo_runtime/resources/file_resource.py +0 -15
  104. oarepo_runtime/resources/json_serializer.py +0 -27
  105. oarepo_runtime/resources/localized_ui_json_serializer.py +0 -54
  106. oarepo_runtime/resources/resource.py +0 -53
  107. oarepo_runtime/resources/responses.py +0 -20
  108. oarepo_runtime/services/components.py +0 -429
  109. oarepo_runtime/services/config/draft_link.py +0 -23
  110. oarepo_runtime/services/config/permissions_presets.py +0 -174
  111. oarepo_runtime/services/config/service.py +0 -117
  112. oarepo_runtime/services/custom_fields/__init__.py +0 -80
  113. oarepo_runtime/services/custom_fields/mappings.py +0 -188
  114. oarepo_runtime/services/entity/__init__.py +0 -0
  115. oarepo_runtime/services/entity/config.py +0 -14
  116. oarepo_runtime/services/entity/schema.py +0 -9
  117. oarepo_runtime/services/entity/service.py +0 -48
  118. oarepo_runtime/services/expansions/__init__.py +0 -0
  119. oarepo_runtime/services/expansions/expandable_fields.py +0 -21
  120. oarepo_runtime/services/expansions/service.py +0 -4
  121. oarepo_runtime/services/facets/base.py +0 -12
  122. oarepo_runtime/services/facets/date.py +0 -72
  123. oarepo_runtime/services/facets/enum.py +0 -11
  124. oarepo_runtime/services/facets/facet_groups_names.py +0 -17
  125. oarepo_runtime/services/facets/max_facet.py +0 -13
  126. oarepo_runtime/services/facets/multilingual_facet.py +0 -33
  127. oarepo_runtime/services/facets/nested_facet.py +0 -32
  128. oarepo_runtime/services/facets/year_histogram.py +0 -200
  129. oarepo_runtime/services/files/__init__.py +0 -8
  130. oarepo_runtime/services/files/components.py +0 -62
  131. oarepo_runtime/services/files/service.py +0 -16
  132. oarepo_runtime/services/generators.py +0 -10
  133. oarepo_runtime/services/permissions/__init__.py +0 -3
  134. oarepo_runtime/services/permissions/generators.py +0 -103
  135. oarepo_runtime/services/relations/__init__.py +0 -0
  136. oarepo_runtime/services/relations/components.py +0 -15
  137. oarepo_runtime/services/relations/errors.py +0 -18
  138. oarepo_runtime/services/relations/mapping.py +0 -38
  139. oarepo_runtime/services/schema/cf.py +0 -13
  140. oarepo_runtime/services/schema/i18n_validation.py +0 -7
  141. oarepo_runtime/services/schema/marshmallow.py +0 -44
  142. oarepo_runtime/services/schema/marshmallow_to_json_schema.py +0 -72
  143. oarepo_runtime/services/schema/oneofschema.py +0 -192
  144. oarepo_runtime/services/schema/polymorphic.py +0 -21
  145. oarepo_runtime/services/schema/rdm.py +0 -146
  146. oarepo_runtime/services/schema/rdm_ui.py +0 -156
  147. oarepo_runtime/services/schema/ui.py +0 -251
  148. oarepo_runtime/services/schema/validation.py +0 -70
  149. oarepo_runtime/services/search.py +0 -282
  150. oarepo_runtime/services/service.py +0 -61
  151. oarepo_runtime/tasks.py +0 -6
  152. oarepo_runtime/translations/cs/LC_MESSAGES/messages.mo +0 -0
  153. oarepo_runtime/translations/cs/LC_MESSAGES/messages.po +0 -95
  154. oarepo_runtime/translations/default_translations.py +0 -6
  155. oarepo_runtime/translations/en/LC_MESSAGES/messages.mo +0 -0
  156. oarepo_runtime/translations/en/LC_MESSAGES/messages.po +0 -97
  157. oarepo_runtime/translations/messages.pot +0 -100
  158. oarepo_runtime/uow.py +0 -146
  159. oarepo_runtime/utils/__init__.py +0 -0
  160. oarepo_runtime/utils/functools.py +0 -37
  161. oarepo_runtime/utils/identity_utils.py +0 -35
  162. oarepo_runtime/utils/index.py +0 -11
  163. oarepo_runtime/utils/path.py +0 -97
  164. oarepo_runtime-1.10.3.dist-info/RECORD +0 -163
  165. oarepo_runtime-1.10.3.dist-info/entry_points.txt +0 -16
  166. oarepo_runtime-1.10.3.dist-info/top_level.txt +0 -2
  167. tests/marshmallow_to_json/__init__.py +0 -0
  168. tests/marshmallow_to_json/test_datacite_ui_schema.py +0 -1410
  169. tests/marshmallow_to_json/test_simple_schema.py +0 -52
  170. tests/pkg_data/__init__.py +0 -0
  171. {oarepo_runtime-1.10.3.dist-info → oarepo_runtime-2.0.0.dev4.dist-info}/licenses/LICENSE +0 -0
@@ -1,272 +0,0 @@
1
- import sys
2
- import traceback
3
- from io import StringIO
4
-
5
- import click
6
- import yaml
7
- from flask.cli import with_appcontext
8
- from invenio_db import db
9
- from invenio_records_resources.proxies import current_service_registry
10
- from invenio_search.proxies import current_search
11
- from werkzeug.utils import ImportStringError, import_string
12
-
13
- try:
14
- from tqdm import tqdm
15
- except ImportError:
16
-
17
- def tqdm(generator):
18
- yield from generator
19
-
20
-
21
- from .base import oarepo
22
-
23
-
24
- @oarepo.group()
25
- def index():
26
- "OARepo indexing addons"
27
-
28
-
29
- @index.command(
30
- help="Create all indices that do not exist yet. "
31
- "This is like 'invenio index init' but does not throw "
32
- "an exception if some indices already exist"
33
- )
34
- @with_appcontext
35
- def init():
36
- click.secho("Creating indexes...", fg="green", bold=True, file=sys.stderr)
37
- all_indices = list(gather_all_indices())
38
- new_indices = []
39
- with click.progressbar(all_indices, label="Checking which indices exist") as bar:
40
- for name, alias in bar:
41
- if not current_search.client.indices.exists(alias):
42
- new_indices.append(name)
43
- if new_indices:
44
- with click.progressbar(
45
- current_search.create(
46
- ignore=[400], ignore_existing=True, index_list=new_indices
47
- ),
48
- length=len(new_indices),
49
- ) as bar:
50
- for name, response in bar:
51
- bar.label = name
52
-
53
-
54
- def gather_all_indices():
55
- """Yield index_file, index_name for all indices."""
56
-
57
- # partially copied from invenio-search
58
- def _build(tree_or_filename, alias=None):
59
- """Build a list of index/alias actions to perform."""
60
- for name, value in tree_or_filename.items():
61
- if isinstance(value, dict):
62
- yield from _build(value, alias=name)
63
- else:
64
- index_result, alias_result = current_search.create_index(
65
- name, dry_run=True
66
- )
67
- yield name, alias_result[0]
68
-
69
- yield from _build(current_search.active_aliases)
70
-
71
-
72
- def record_or_service(model):
73
- # TODO: is this still used (maybe from somewhere else?)
74
- try:
75
- service = current_service_registry.get(model)
76
- except KeyError:
77
- service = None
78
- if service and getattr(service, "config", None):
79
- record = getattr(service.config, "record_cls", None)
80
- else:
81
- try:
82
- record = import_string(model)
83
- except ImportStringError:
84
- record = None
85
-
86
- if record is None:
87
- click.secho(
88
- "Service or model not found. Known services: ",
89
- fg="red",
90
- bold=True,
91
- file=sys.stderr,
92
- )
93
- for svc in sorted(current_service_registry._services):
94
- click.secho(f" {svc}", file=sys.stderr)
95
- sys.exit(1)
96
- return record
97
-
98
-
99
- @index.command()
100
- @with_appcontext
101
- @click.argument("model", required=False)
102
- @click.option("--bulk-size", required=False, default=5000, type=int)
103
- @click.option("--verbose/--no-verbose", default=False)
104
- def reindex(model, bulk_size, verbose):
105
- if not model:
106
- services = list(current_service_registry._services.keys())
107
- else:
108
- services = [model]
109
- services = sort_services(services)
110
- for service_id in services:
111
- click.secho(f"Preparing to index {service_id}", file=sys.stderr)
112
-
113
- try:
114
- service = current_service_registry.get(service_id)
115
- except KeyError:
116
- click.secho(f"Service {service_id} not in known services:", color="red")
117
- for known_service_id, known_service in sorted(
118
- current_service_registry._services.items()
119
- ):
120
- click.secho(
121
- f" {known_service_id} -> {type(known_service).__module__}.{type(known_service).__name__}",
122
- color="red",
123
- )
124
- sys.exit(1)
125
- record_class = getattr(service.config, "record_cls", None)
126
-
127
- id_generators = []
128
-
129
- record_generator = RECORD_GENERATORS.get(service_id, model_records_generator)
130
-
131
- if record_class and hasattr(service, "indexer"):
132
- try:
133
- id_generators.append(record_generator(record_class))
134
- except Exception as e:
135
- click.secho(
136
- f"Could not get record ids for {service_id}, exception {e}",
137
- file=sys.stderr,
138
- )
139
-
140
- draft_class = getattr(service.config, "draft_cls", None)
141
-
142
- if draft_class and hasattr(service, "indexer"):
143
- try:
144
- id_generators.append(record_generator(draft_class))
145
- except Exception as e:
146
- click.secho(
147
- f"Could not get draft record ids for {service_id}, exception {e}",
148
- file=sys.stderr,
149
- )
150
-
151
- click.secho(f"Indexing {service_id}", file=sys.stderr)
152
- count = 0
153
- errors = 0
154
- for gen in id_generators:
155
- for bulk in generate_bulk_data(gen, service.indexer, bulk_size=bulk_size):
156
- index_result = service.indexer.client.bulk(bulk)
157
- count += len(bulk) // 2
158
- for index_item_result in index_result["items"]:
159
- result = index_item_result["index"]
160
- if result["status"] not in (200, 201):
161
- errors += 1
162
- click.secho(
163
- f"Error indexing record with id {result['_id']}",
164
- fg="red",
165
- file=sys.stderr,
166
- )
167
- click.secho(
168
- dump_yaml(result.get("error")), fg="red", file=sys.stderr
169
- )
170
- if verbose:
171
- click.secho("Record:", file=sys.stderr)
172
- rec = [
173
- bulk[idx + 1]
174
- for idx in range(0, len(bulk), 2)
175
- if bulk[idx]["index"]["_id"] == result["_id"]
176
- ]
177
- if rec:
178
- click.secho(dump_yaml(rec[0]))
179
- else:
180
- click.secho("<no record found>")
181
-
182
- if count:
183
- service.indexer.refresh()
184
-
185
- if errors:
186
- click.secho(
187
- f"Indexing {service_id} failed, indexed {count - errors} records, failed {errors} records.",
188
- fg="red",
189
- file=sys.stderr,
190
- )
191
- if not verbose:
192
- click.secho("Run with --verbose to see information about the errors")
193
- else:
194
- click.secho(
195
- f"Indexing {service_id} finished, indexed {count} records",
196
- fg="green",
197
- file=sys.stderr,
198
- )
199
-
200
-
201
- def generate_bulk_data(record_generator, record_indexer, bulk_size):
202
- data = []
203
- n = 0
204
- for record in tqdm(record_generator):
205
- try:
206
- index = record_indexer.record_to_index(record)
207
- body = record_indexer._prepare_record(record, index)
208
- index = record_indexer._prepare_index(index)
209
- data.append(
210
- {
211
- "index": {
212
- "_index": index,
213
- "version": record.revision_id,
214
- "version_type": "external_gte",
215
- "_id": body["uuid"],
216
- }
217
- }
218
- )
219
- data.append(body)
220
- if len(data) >= bulk_size:
221
- yield data
222
- data = []
223
- except:
224
- traceback.print_exc()
225
- if data:
226
- yield data
227
-
228
-
229
- def dump_yaml(data):
230
- io = StringIO()
231
- yaml.dump(data, io, allow_unicode=True)
232
- return io.getvalue()
233
-
234
-
235
- def model_records_generator(model_class):
236
- try:
237
- for x in db.session.query(model_class.model_cls.id).filter(
238
- model_class.model_cls.is_deleted.is_(False)
239
- ):
240
- rec_id = x[0]
241
- yield model_class.get_record(rec_id)
242
- except Exception as e:
243
- click.secho(f"Could not index {model_class}: {e}", fg="red", file=sys.stderr)
244
-
245
-
246
- def users_record_generator(model_class):
247
- from invenio_accounts.models import User
248
- from invenio_users_resources.records.api import UserAggregate
249
-
250
- try:
251
- for x in db.session.query(User.id):
252
- rec_id = x[0]
253
- yield UserAggregate.get_record(rec_id)
254
- except Exception as e:
255
- click.secho(f"Could not index {model_class}: {e}", fg="red", file=sys.stderr)
256
-
257
-
258
- priorities = ["vocabular", "users", "groups"]
259
-
260
-
261
- def sort_services(services):
262
- def idx(x):
263
- for idx, p in enumerate(priorities):
264
- if p in x:
265
- return idx, x
266
- return len(priorities), x
267
-
268
- services.sort(key=idx)
269
- return services
270
-
271
-
272
- RECORD_GENERATORS = {"users": users_record_generator}
@@ -1,6 +0,0 @@
1
- from .base import permissions
2
- from .evaluate import evaluate_permissions # noqa
3
- from .list import list_permissions # noqa
4
- from .search import search_permissions # noqa
5
-
6
- __all__ = ["permissions"]
@@ -1,26 +0,0 @@
1
- from flask import current_app
2
- from flask_principal import Identity, UserNeed, identity_loaded
3
- from invenio_access.models import User
4
-
5
- from ..base import oarepo
6
-
7
-
8
- @oarepo.group()
9
- def permissions():
10
- """Commands for checking and explaining permissions."""
11
-
12
-
13
- def get_user_and_identity(user_id_or_email):
14
- try:
15
- user_id = int(user_id_or_email)
16
- user = User.query.filter_by(id=user_id).one()
17
- except ValueError:
18
- user = User.query.filter_by(email=user_id_or_email).one()
19
-
20
- identity = Identity(user.id)
21
- identity.provides.add(UserNeed(str(user.id)))
22
- api_app = current_app.wsgi_app.mounts["/api"]
23
- with api_app.app_context():
24
- with current_app.test_request_context("/api"):
25
- identity_loaded.send(api_app, identity=identity)
26
- return user, identity
@@ -1,63 +0,0 @@
1
- import json
2
-
3
- import click
4
- from invenio_records_permissions.policies.records import RecordPermissionPolicy
5
- from invenio_records_resources.proxies import current_service_registry
6
-
7
- from oarepo_runtime.info.permissions.debug import add_debugging
8
-
9
- from .base import get_user_and_identity, permissions
10
-
11
-
12
- @permissions.command(name="evaluate")
13
- @click.argument("user_id_or_email")
14
- @click.argument("service_name")
15
- @click.argument("record_id", required=False)
16
- @click.option("--data", "-d", help="Data to pass to the policy check")
17
- @click.option("--explain/--no-explain", default=False)
18
- @click.option("--draft/--published", default=False)
19
- def evaluate_permissions(
20
- user_id_or_email: str,
21
- service_name: str,
22
- record_id: str | None = None,
23
- data: str | None = None,
24
- explain: bool = False,
25
- draft: bool = False,
26
- ):
27
- """Evaluate permissions for a given workflow, community or service."""
28
- service = current_service_registry.get(service_name)
29
- user, identity = get_user_and_identity(user_id_or_email)
30
-
31
- over = {}
32
- if record_id:
33
- if draft:
34
- over["record"] = service.config.draft_cls.pid.resolve(
35
- record_id, registered_only=False
36
- )
37
- else:
38
- over["record"] = service.config.record_cls.pid.resolve(record_id)
39
- if data:
40
- over["data"] = json.loads(data)
41
-
42
- if explain:
43
- over["debug_identity"] = identity
44
- add_debugging()
45
-
46
- policy_cls = service.config.permission_policy_cls
47
- click.secho(f"Policy: {policy_cls}")
48
-
49
- for action_name in dir(policy_cls):
50
- if not action_name.startswith("can_"):
51
- continue
52
-
53
- policy: RecordPermissionPolicy = policy_cls(action_name[4:], **over)
54
- if explain:
55
- click.secho()
56
- click.secho(f"## {action_name}")
57
- try:
58
- if policy.allows(identity):
59
- click.secho(f"{action_name}: True", fg="green")
60
- else:
61
- click.secho(f"{action_name}: False", fg="red")
62
- except Exception as e:
63
- click.secho(f"{action_name}: {e}", fg="yellow")
@@ -1,239 +0,0 @@
1
- from typing import get_type_hints
2
-
3
- import click
4
-
5
- from oarepo_runtime.info.permissions.debug import add_debugging
6
-
7
- from .base import permissions
8
-
9
-
10
- @permissions.command(name="list")
11
- @click.option("--workflow", "-w", help="Workflow name")
12
- @click.option("--community", "-c", help="Community name")
13
- @click.option("--service", "-s", help="Service name")
14
- def list_permissions(workflow, community, service):
15
- """List all permissions for a given workflow, community or service."""
16
- # intentionally import here to enable oarepo-runtime to be used
17
- # without oarepo-workflows and oarepo-communities
18
- from invenio_communities.communities.records.api import Community
19
- from invenio_communities.communities.records.models import CommunityMetadata
20
- from oarepo_workflows.proxies import current_oarepo_workflows
21
-
22
- if workflow:
23
- wf = current_oarepo_workflows.record_workflows[workflow]
24
- permission_policy = wf.permission_policy_cls
25
- elif community:
26
- community_db = CommunityMetadata.query.filter_by(slug=community).one()
27
- community_obj = Community(community_db.data, model=community_db)
28
- workflow = community_obj["custom_fields"].get("workflow", "default")
29
- wf = current_oarepo_workflows.record_workflows[workflow]
30
- permission_policy = wf.permission_policy_cls
31
- elif service:
32
- from invenio_records_resources.proxies import current_service_registry
33
-
34
- swc = current_service_registry.get(service)
35
- permission_policy = swc.config.permission_policy_cls
36
- else:
37
- raise click.UsageError(
38
- "You must specify either --workflow, --community or --service."
39
- )
40
-
41
- add_debugging()
42
-
43
- p = permission_policy("read")
44
-
45
- for action_name in dir(permission_policy):
46
- if not action_name.startswith("can_"):
47
- continue
48
- action_permission_generators = getattr(p, action_name)
49
- debugs = []
50
- for x in action_permission_generators:
51
- debugs.append(x.to_debug_dict())
52
-
53
- print("")
54
- print(f"## {action_name}")
55
- print(get_permission_documentation(permission_policy, action_name))
56
- for perm in debugs:
57
- print_permission_markdown(perm)
58
-
59
-
60
- def is_simple_dict(d):
61
- return all(isinstance(v, (str, int, float, bool)) for v in d.values())
62
-
63
-
64
- def format_simple_dict_values(d):
65
- # returns k=v, k=v, ...
66
- return ", ".join(f"{k}={v}" for k, v in d.items())
67
-
68
-
69
- def print_permission_markdown(p, level=0):
70
- for k, v in p.items():
71
- prologue = " " * level + f"- {k}"
72
- if v is None or v == {} or v == []:
73
- print(prologue)
74
- continue
75
- elif isinstance(v, dict):
76
- if is_simple_dict(v):
77
- print(f"{prologue}: {format_simple_dict_values(v)}")
78
- else:
79
- print(prologue)
80
- print_permission_markdown(v, level + 1)
81
- elif isinstance(v, list):
82
- print(prologue)
83
- for x in v:
84
- print_permission_markdown(x, level + 1)
85
- else:
86
- print(" " * (level + 1) + f"{v}")
87
-
88
-
89
- def get_permission_documentation(policy, permission_can_name):
90
- type_hints = get_type_hints(policy, include_extras=True)
91
- annotation = type_hints.get(permission_can_name)
92
- if annotation:
93
- for md in annotation.__metadata__:
94
- if isinstance(md, str):
95
- return md
96
- ret = default_permissions_documentation.get(permission_can_name, "")
97
- return "\n".join(x.strip() for x in ret.split("\n"))
98
-
99
-
100
- default_permissions_documentation = {
101
- # records
102
- "can_create": """
103
- Grants users the ability to create new records in the
104
- repository, often assigned to roles like submitters, owners, or curators.
105
- The result of this action is typically a draft record.
106
- """,
107
- "can_read": """
108
- Allows users to view or access records, with access
109
- possibly dependent on the record's state (e.g., draft or published) and the
110
- user's role.
111
- """,
112
- "can_read_deleted": """
113
- Permission to view or access records, including soft-deleted ones. This
114
- permission is used to filter search results. It should include an
115
- `IfRecordDeleted` permission generator, which grants access to deleted
116
- records to a subset of users (e.g., owners, curators, etc.). For
117
- `service.read`, this permission is applied when record is deleted and
118
- `include_deleted` is passed; otherwise, a `RecordDeletedException` is raised.
119
- """,
120
- "can_search": """
121
- Grants users the ability to search for records within the
122
- repository, typically available to all users. The search results are
123
- filtered based on the can_read_deleted permission for published records (/api/datasets)
124
- and the can_read_draft permission for draft records (/api/user/datasets).
125
- """,
126
- "can_update": """
127
- Grants users the ability to update or modify published records.
128
- In NRP repositories, this is normally disabled as updates are performed
129
- on draft records, which are then published.
130
- """,
131
- "can_delete": """
132
- Grants users the ability to delete records, often restricted
133
- to owners, curators, or specific roles, and dependent on the record's
134
- state (e.g., draft). For published records, the deletion is performed
135
- via a specialized request, not directly.
136
- """,
137
- "can_new_version": """
138
- Allows users to create a new version of a record. In NRP,
139
- this is not used directly but always via a request, which is mostly
140
- auto-approved.
141
- """,
142
- "can_edit": """
143
- Grants users the ability to modify the metadata of a record. In NRP, this
144
- is not used directly but always via a request, which is mostly auto-approved.
145
- """,
146
- "can_manage": """
147
- Grants users the ability to manage records. Currently it is used just
148
- for reindexing records with latest version first (reindex_latest_first)
149
- service call, not mapped to REST API.
150
- """,
151
- "can_manage_record_access": """
152
- Grants users the ability to manage record access.
153
- """,
154
- # draft records
155
- "can_read_draft": """
156
- Enables users to view or access draft records, typically equivalent to
157
- the general 'can_read' permission but specific to drafts.
158
- """,
159
- "can_delete_draft": """
160
- Allows users to delete draft records, typically equivalent to the general
161
- 'can_delete' permission but specific to drafts.
162
- """,
163
- "can_update_draft": """
164
- Allows users to update draft records. It is typically granted to record
165
- owner, but can be restricted by the record status (such as records submitted
166
- to review being locked).
167
- """,
168
- "can_publish": """
169
- Grants users the ability to publish records, making them publicly
170
- available or finalizing their state. In NRP repositories, this is
171
- not used directly but always via a request.
172
- """,
173
- # files
174
- "can_read_files": """
175
- Grants users the ability to view or access file metadata associated with records,
176
- with access dependent on the record's state and the user's role.
177
- """,
178
- "can_create_files": """
179
- Enables users to create new files within published records in the repository.
180
- Normally disabled as files are created in draft records and then published.
181
- """,
182
- "can_delete_files": """
183
- Enables users to delete files associated with published records in the repository.
184
- Normally disabled as files can not be deleted from published records.
185
- """,
186
- "can_update_files": """
187
- Enables users to update or modify files within published records in the repository.
188
- Normally disabled as files are updated in draft records and then published.
189
- """,
190
- "can_commit_files": """
191
- Allows users to finalize file upload to published records in the repository.
192
- Normally disabled as files are uploaded to draft records and then published.
193
- """,
194
- "can_get_content_files": """
195
- Allows users to access or retrieve the content of files on records published
196
- in the repository, with access depending on the record's state and the user's role.
197
- """,
198
- "can_manage_files": """
199
- Grants users the ability to manage files (that is, change if the files are
200
- required on the record or not).
201
- """,
202
- "can_read_deleted_files": """
203
- Allows users to view or access files associated with deleted records,
204
- often restricted to specific conditions.
205
- """,
206
- "can_set_content_files": """
207
- Enables users to upload files to published records. Normally disabled as files
208
- are uploaded to draft records and then published.
209
- """,
210
- # draft files
211
- "can_draft_read_files": """
212
- Allows users to view or access file metadata associated with draft records,
213
- typically equivalent to the general 'can_read_files' permission but specific
214
- to drafts.
215
- """,
216
- "can_draft_create_files": """
217
- Allows users to create files specifically for draft records.
218
- """,
219
- "can_draft_get_content_files": """
220
- Allows users to access or retrieve the content of files on draft records.
221
- """,
222
- "can_draft_set_content_files": """
223
- Allows users to upload files to draft records.
224
- """,
225
- "can_draft_commit_files": """
226
- Allows users to finalize file upload to draft records.
227
- """,
228
- "can_draft_update_files": """
229
- Allows users to update or modify files within draft records.
230
- """,
231
- "can_draft_delete_files": """
232
- Allows users to delete files associated with draft records.
233
- """,
234
- # misc
235
- "can_create_or_update_many": """
236
- Allows bulk creation or updating of multiple records or files.
237
- Not used at the moment.
238
- """,
239
- }