mirror of
https://github.com/Cian-H/invenio-config-iform.git
synced 2025-12-23 05:21:57 +00:00
Compare commits
121 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 672f686d1a | |||
| 59c3ac5bc2 | |||
| 1e75799497 | |||
| fec9dd75c7 | |||
| 2ae8ab6926 | |||
| e24e1f2cbc | |||
| e3465637f9 | |||
| f7a4ab0939 | |||
| a7ffce1f43 | |||
| 3b1526d4d8 | |||
| fd4f97fd41 | |||
| c91ff83bb5 | |||
| c22f4f4d02 | |||
| 919cd3e4bd | |||
| 4fad1ced08 | |||
| 3bb38a95eb | |||
| 36f9b91cc1 | |||
| 3013095bdd | |||
| 6e84ea0446 | |||
| 529fe17d24 | |||
| 0fd2466b49 | |||
| 8f5c1e36a5 | |||
| 1992a4cee0 | |||
| 40ed1aa4f9 | |||
| 51f11bd910 | |||
| f4c8cbea03 | |||
| 56f7739ae4 | |||
| f2bcb03cd0 | |||
| 9646985e7c | |||
| b514df9d48 | |||
| e1d975dc98 | |||
| d4f6efe5a2 | |||
| 9b7aa9a217 | |||
| a0da4cf05f | |||
| 84595fa54f | |||
| 2cf44242fa | |||
| 899b391e29 | |||
| 610ea83652 | |||
| 28aa1eb9a3 | |||
| 98f37fc6d7 | |||
| 7c938751e6 | |||
| 7bd474a247 | |||
| 8582c8ce23 | |||
| 3ba2169591 | |||
| 3e566699c6 | |||
| 811bf6514d | |||
| 668ae1e34c | |||
| 60085e90ab | |||
| cb836a1d6d | |||
| 5fea611ab4 | |||
| e8df1e4541 | |||
| 069bb11033 | |||
| cd35917894 | |||
| 302ff471fd | |||
| e2e6a32c08 | |||
| 32f0c0af61 | |||
| d26e8cae6f | |||
| f537f0e383 | |||
| 3e82144fd3 | |||
| b925eaa678 | |||
| 5b2eb94994 | |||
| 7c7a281a5f | |||
| 8e3b48ab52 | |||
|
|
8746d704a1 | ||
|
|
a7b474bb78 | ||
| 969b16fe4a | |||
| d452fca79e | |||
| 2069f0826d | |||
| 98893598f8 | |||
| 4e20d6a5fe | |||
| 58a7e2f3a8 | |||
| 5665b01979 | |||
| b6cbd03f9c | |||
|
|
04ca3f5661 | ||
|
|
5d84b08e26 | ||
|
|
5e4fcca0ed | ||
|
|
c934a4952b | ||
|
|
c91d056a56 | ||
|
|
583a67d0cf | ||
|
|
760363b4a5 | ||
|
|
52fb93cc43 | ||
|
|
41db3186df | ||
|
|
20bdff0b79 | ||
|
|
99705d7a25 | ||
|
|
d4df756ebf | ||
|
|
a10dccba22 | ||
|
|
8b84077e83 | ||
|
|
08d745d367 | ||
|
|
bf62abff3f | ||
|
|
40a47ed36d | ||
|
|
129b331603 | ||
|
|
328abd1306 | ||
|
|
7ce124cdb9 | ||
|
|
75d78cf09a | ||
|
|
2e5fbcb4f9 | ||
|
|
4c4279965a | ||
|
|
0ee0df4ee1 | ||
|
|
8df08c09bf | ||
|
|
3a508ac3f0 | ||
|
|
087cafa3ae | ||
|
|
14e9e0557a | ||
|
|
8669f5dcda | ||
|
|
62256b346f | ||
|
|
4a8b02ec4a | ||
|
|
8a592e3fdf | ||
|
|
42d5e2db05 | ||
|
|
3db870784b | ||
|
|
73bc8b4575 | ||
|
|
7fd5a7df3f | ||
|
|
79fe24511a | ||
|
|
5b7a1718fc | ||
|
|
9192107e99 | ||
|
|
c43c36ece3 | ||
|
|
3acbaf65ef | ||
|
|
408bdc47b1 | ||
|
|
6c6138b682 | ||
|
|
cc2c462057 | ||
|
|
3f2cf9f800 | ||
|
|
db0c7a4e21 | ||
|
|
91464bbd7c | ||
|
|
d7fe2926c7 |
@@ -2,7 +2,7 @@
|
|||||||
#
|
#
|
||||||
# Copyright (C) 2020 Mojib Wali.
|
# Copyright (C) 2020 Mojib Wali.
|
||||||
#
|
#
|
||||||
# invenio-config-tugraz is free software; you can redistribute it and/or
|
# invenio-config-iform is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the MIT License; see LICENSE file for more
|
# modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
# details.
|
# details.
|
||||||
|
|
||||||
@@ -15,15 +15,6 @@ insert_final_newline = true
|
|||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
|
|
||||||
# Python files
|
|
||||||
[*.py]
|
|
||||||
indent_size = 4
|
|
||||||
# isort plugin configuration
|
|
||||||
known_first_party = invenio_config_tugraz
|
|
||||||
multi_line_output = 2
|
|
||||||
default_section = THIRDPARTY
|
|
||||||
skip = .eggs
|
|
||||||
|
|
||||||
# RST files (used by sphinx)
|
# RST files (used by sphinx)
|
||||||
[*.rst]
|
[*.rst]
|
||||||
indent_size = 4
|
indent_size = 4
|
||||||
|
|||||||
5
.envrc
Normal file
5
.envrc
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
export DIRENV_WARN_TIMEOUT=20s
|
||||||
|
|
||||||
|
eval "$(devenv direnvrc)"
|
||||||
|
|
||||||
|
use devenv
|
||||||
1
.git-blame-ignore-revs
Normal file
1
.git-blame-ignore-revs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
766b2cafae4dc74393b103389e6978eca5a9cfd2
|
||||||
29
.github/dependabot.yml
vendored
Normal file
29
.github/dependabot.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "uv"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
day: "monday"
|
||||||
|
time: "04:00"
|
||||||
|
open-pull-requests-limit: 8
|
||||||
|
allow:
|
||||||
|
- dependency-type: "all"
|
||||||
|
reviewers:
|
||||||
|
- "Cian-H"
|
||||||
|
assignees:
|
||||||
|
- "Cian-H"
|
||||||
|
commit-message:
|
||||||
|
prefix: "uv-deps"
|
||||||
|
prefix-development: "uv-deps-dev"
|
||||||
|
include: "scope"
|
||||||
|
|
||||||
|
- package-ecosystem: "github-actions"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
|
day: "monday"
|
||||||
|
time: "04:00"
|
||||||
|
open-pull-requests-limit: 5
|
||||||
|
commit-message:
|
||||||
|
prefix: "ci"
|
||||||
26
.github/workflows/publish.yml
vendored
Normal file
26
.github/workflows/publish.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
name: Publish to PyPI
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_run:
|
||||||
|
workflows:
|
||||||
|
- Auto Version Tag
|
||||||
|
types:
|
||||||
|
- completed
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
environment: release
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Set up uv
|
||||||
|
uses: astral-sh/setup-uv@v6
|
||||||
|
with:
|
||||||
|
python-version: "${{ matrix.python-version }}"
|
||||||
|
enable-cache: true
|
||||||
|
cache-dependency-glob: |
|
||||||
|
pyproject.toml
|
||||||
|
- name: Build package
|
||||||
|
run: uv build
|
||||||
|
- name: Publish to PyPI
|
||||||
|
run: uv publish --token ${{ secrets.PYPI_API_TOKEN }}
|
||||||
26
.github/workflows/pypi-publish.yml
vendored
26
.github/workflows/pypi-publish.yml
vendored
@@ -1,26 +0,0 @@
|
|||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- v*
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-n-publish:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v2
|
|
||||||
- name: Set up Python 3.7
|
|
||||||
uses: actions/setup-python@v2
|
|
||||||
with:
|
|
||||||
python-version: 3.7
|
|
||||||
- name: Install dependencies
|
|
||||||
run: |
|
|
||||||
python -m pip install --upgrade pip
|
|
||||||
pip install setuptools wheel
|
|
||||||
- name: Build package
|
|
||||||
run: |
|
|
||||||
python setup.py compile_catalog sdist bdist_wheel
|
|
||||||
- name: pypi-publish
|
|
||||||
uses: pypa/gh-action-pypi-publish@v1.3.1
|
|
||||||
with:
|
|
||||||
user: __token__
|
|
||||||
password: ${{ secrets.pypi_password }}
|
|
||||||
20
.github/workflows/tagging.yml
vendored
Normal file
20
.github/workflows/tagging.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
name: Auto Version Tag
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_run:
|
||||||
|
workflows:
|
||||||
|
- Tests
|
||||||
|
types:
|
||||||
|
- completed
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
tag:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
- name: Version tag
|
||||||
|
uses: Jorricks/action-python-autotagging@1.0.1
|
||||||
|
with:
|
||||||
|
token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
path: invenio_config_iform/__about__.py
|
||||||
|
variable: __version__
|
||||||
135
.github/workflows/tests.yml
vendored
135
.github/workflows/tests.yml
vendored
@@ -1,87 +1,92 @@
|
|||||||
name: CI
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2025 I-Form Advanced Manufacturing Research Centre.
|
||||||
|
#
|
||||||
|
# invenio-theme-iform is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
|
# details.
|
||||||
|
|
||||||
|
name: Tests
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: master
|
branches:
|
||||||
|
- master
|
||||||
pull_request:
|
pull_request:
|
||||||
branches: master
|
branches:
|
||||||
schedule:
|
- master
|
||||||
# * is a special character in YAML so you have to quote this string
|
|
||||||
- cron: '0 3 * * 6'
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
reason:
|
reason:
|
||||||
description: 'Reason'
|
description: "Reason"
|
||||||
required: false
|
required: false
|
||||||
default: 'Manual trigger'
|
default: "Manual trigger"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
Tests:
|
create-strategy:
|
||||||
runs-on: ubuntu-20.04
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
python-version: [3.6, 3.7, 3.8, 3.9]
|
|
||||||
requirements-level: [min, pypi]
|
|
||||||
db-service: [postgresql12]
|
|
||||||
search-service: [elasticsearch7]
|
|
||||||
exclude:
|
|
||||||
- python-version: 3.6
|
|
||||||
requirements-level: pypi
|
|
||||||
|
|
||||||
- python-version: 3.7
|
outputs:
|
||||||
requirements-level: min
|
matrix: ${{ steps.requirements.outputs.matrix }}
|
||||||
|
|
||||||
- python-version: 3.8
|
|
||||||
requirements-level: min
|
|
||||||
|
|
||||||
- python-version: 3.9
|
|
||||||
requirements-level: min
|
|
||||||
|
|
||||||
- db-service: postgresql12
|
|
||||||
requirements-level: min
|
|
||||||
|
|
||||||
- search-service: elasticsearch7
|
|
||||||
requirements-level: min
|
|
||||||
|
|
||||||
include:
|
|
||||||
|
|
||||||
- db-service: postgresql12
|
|
||||||
DB_EXTRAS: "postgresql"
|
|
||||||
|
|
||||||
|
|
||||||
- search-service: elasticsearch7
|
|
||||||
SEARCH_EXTRAS: "elasticsearch7"
|
|
||||||
|
|
||||||
env:
|
|
||||||
DB: ${{ matrix.db-service }}
|
|
||||||
SEARCH: ${{ matrix.search-service }}
|
|
||||||
EXTRAS: all,${{ matrix.DB_EXTRAS }},${{ matrix.SEARCH_EXTRAS }}
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python-version }}
|
- name: requirements
|
||||||
uses: actions/setup-python@v2
|
id: requirements
|
||||||
with:
|
|
||||||
python-version: ${{ matrix.python-version }}
|
|
||||||
|
|
||||||
- name: Generate dependencies
|
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip setuptools py wheel requirements-builder
|
# Define a simple matrix with your Python version
|
||||||
requirements-builder -e "$EXTRAS" --level=${{ matrix.requirements-level }} setup.py > .${{ matrix.requirements-level }}-${{ matrix.python-version }}-requirements.txt
|
# Since we're using pyproject.toml with Python 3.12 requirement
|
||||||
- name: Cache pip
|
echo "matrix={\"include\": [{\"python-version\": \"3.12\"}]}" >> $GITHUB_OUTPUT
|
||||||
uses: actions/cache@v2
|
|
||||||
|
# Print the matrix for debugging
|
||||||
|
echo "-------------------"
|
||||||
|
echo "Matrix: {\"include\": [{\"python-version\": \"3.12\"}]}"
|
||||||
|
echo "-------------------"
|
||||||
|
|
||||||
|
tests:
|
||||||
|
needs: create-strategy
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: Test (Python ${{matrix.python-version}})
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix: ${{ fromJson(needs.create-strategy.outputs.matrix) }}
|
||||||
|
|
||||||
|
# Simplified environment without service variables
|
||||||
|
env:
|
||||||
|
PYTHON_VERSION: ${{ matrix.python-version }}
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up uv
|
||||||
|
uses: astral-sh/setup-uv@v6
|
||||||
with:
|
with:
|
||||||
path: ~/.cache/pip
|
python-version: "${{ matrix.python-version }}"
|
||||||
key: ${{ runner.os }}-pip-${{ hashFiles('.${{ matrix.requirements-level }}-${{ matrix.python-version }}-requirements.txt') }}
|
enable-cache: true
|
||||||
|
cache-dependency-glob: |
|
||||||
|
pyproject.toml
|
||||||
|
cache-suffix: ${{ matrix.python-version }}
|
||||||
|
|
||||||
|
- name: Show configuration
|
||||||
|
run: |
|
||||||
|
uv --version
|
||||||
|
uv run python --version
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
pip install -r .${{ matrix.requirements-level }}-${{ matrix.python-version }}-requirements.txt
|
uv sync --group tests
|
||||||
pip install ".[$EXTRAS]"
|
|
||||||
pip freeze
|
|
||||||
docker --version
|
|
||||||
docker-compose --version
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
|
env:
|
||||||
|
PYTEST_ADDOPTS: "--cov-report=lcov"
|
||||||
run: |
|
run: |
|
||||||
./run-tests.sh
|
uv run test
|
||||||
|
|
||||||
|
- name: Upload coverage to Coveralls
|
||||||
|
uses: coverallsapp/github-action@master
|
||||||
|
with:
|
||||||
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
path-to-lcov: coverage.lcov
|
||||||
|
|||||||
10
.gitignore
vendored
10
.gitignore
vendored
@@ -60,3 +60,13 @@ target/
|
|||||||
|
|
||||||
# Vim swapfiles
|
# Vim swapfiles
|
||||||
.*.sw?
|
.*.sw?
|
||||||
|
|
||||||
|
# Devenv
|
||||||
|
.devenv*
|
||||||
|
devenv.local.nix
|
||||||
|
|
||||||
|
# direnv
|
||||||
|
.direnv
|
||||||
|
|
||||||
|
# python version lock
|
||||||
|
.python-version
|
||||||
|
|||||||
24
.pre-commit-config.yaml
Normal file
24
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
repos:
|
||||||
|
- repo: local
|
||||||
|
hooks:
|
||||||
|
- id: check-version-increment
|
||||||
|
name: Check Version Increment
|
||||||
|
entry: python scripts/hooks/pre-push/check_version_increment.py
|
||||||
|
language: system
|
||||||
|
pass_filenames: false
|
||||||
|
stages: [pre-push]
|
||||||
|
|
||||||
|
- id: tests
|
||||||
|
name: Run Python Tests
|
||||||
|
entry: uv run test
|
||||||
|
language: system
|
||||||
|
pass_filenames: false
|
||||||
|
stages: [pre-push]
|
||||||
|
|
||||||
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
|
rev: v0.11.9
|
||||||
|
hooks:
|
||||||
|
- id: ruff
|
||||||
|
stages: [pre-push]
|
||||||
|
- id: ruff-format
|
||||||
|
stages: [pre-push]
|
||||||
20
.readthedocs.yaml
Normal file
20
.readthedocs.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# Read the Docs configuration file
|
||||||
|
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
||||||
|
|
||||||
|
# Required
|
||||||
|
version: 2
|
||||||
|
|
||||||
|
# Set the OS, Python version, and other tools you might need
|
||||||
|
build:
|
||||||
|
os: ubuntu-24.04
|
||||||
|
tools:
|
||||||
|
python: "3.13"
|
||||||
|
jobs:
|
||||||
|
pre_create_environment:
|
||||||
|
- asdf plugin add uv
|
||||||
|
- asdf install uv latest
|
||||||
|
- asdf global uv latest
|
||||||
|
create_environment:
|
||||||
|
- uv sync --group docs
|
||||||
|
install:
|
||||||
|
- uv run python -m sphinx -T -d docs/_build/doctrees -D language=en docs $READTHEDOCS_OUTPUT/html
|
||||||
33
.tx/config
33
.tx/config
@@ -1,33 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Copyright (C) 2020 Mojib Wali.
|
|
||||||
#
|
|
||||||
# invenio-config-tugraz is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
||||||
# details.
|
|
||||||
|
|
||||||
# TODO: Transifex integration
|
|
||||||
#
|
|
||||||
# 1) Create message catalog:
|
|
||||||
# $ python setup.py extract_messages
|
|
||||||
# $ python setup.py init_catalog -l <lang>
|
|
||||||
# $ python setup.py compile_catalog
|
|
||||||
# 2) Ensure project has been created on Transifex under the inveniosoftware
|
|
||||||
# organisation.
|
|
||||||
# 3) Install the transifex-client
|
|
||||||
# $ pip install transifex-client
|
|
||||||
# 4) Push source (.pot) and translations (.po) to Transifex
|
|
||||||
# $ tx push -s -t
|
|
||||||
# 5) Pull translations for a single language from Transifex
|
|
||||||
# $ tx pull -l <lang>
|
|
||||||
# 6) Pull translations for all languages from Transifex
|
|
||||||
# $ tx pull -a
|
|
||||||
|
|
||||||
[main]
|
|
||||||
host = https://www.transifex.com
|
|
||||||
|
|
||||||
[invenio.invenio-config-tugraz-messages]
|
|
||||||
file_filter = invenio_config_tugraz/translations/<lang>/LC_MESSAGES/messages.po
|
|
||||||
source_file = invenio_config_tugraz/translations/messages.pot
|
|
||||||
source_lang = en
|
|
||||||
type = PO
|
|
||||||
@@ -1,13 +1,15 @@
|
|||||||
..
|
..
|
||||||
Copyright (C) 2020 Mojib Wali.
|
Copyright (C) 2020 Mojib Wali.
|
||||||
|
|
||||||
invenio-config-tugraz is free software; you can redistribute it and/or
|
invenio-config-iform is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the MIT License; see LICENSE file for more
|
modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
details.
|
details.
|
||||||
|
|
||||||
Authors
|
Authors
|
||||||
=======
|
=======
|
||||||
|
|
||||||
invenio module that adds tugraz configs.
|
invenio module that adds I-Form configs.
|
||||||
|
|
||||||
- Mojib Wali <mojib.wali@tugraz.at>
|
- Cian Hughes <cian.hughes@dcu.ie>
|
||||||
|
|
||||||
|
Forked from https://github.com/tu-graz-library/invenio-theme-tugraz
|
||||||
|
|||||||
89
CHANGES.rst
89
CHANGES.rst
@@ -1,12 +1,97 @@
|
|||||||
..
|
..
|
||||||
Copyright (C) 2020 - 2021 Graz University of Technology.
|
Copyright (C) 2020 - 2022 Graz University of Technology.
|
||||||
|
|
||||||
invenio-config-tugraz is free software; you can redistribute it and/or
|
invenio-config-iform is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the MIT License; see LICENSE file for more
|
modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
details.
|
details.
|
||||||
|
|
||||||
Changes
|
Changes
|
||||||
=======
|
=======
|
||||||
|
|
||||||
|
Version v0.12.5 (release 2024-07-29)
|
||||||
|
|
||||||
|
- fix: permission for ip
|
||||||
|
|
||||||
|
|
||||||
|
Version v0.12.3 (release 2024-07-25)
|
||||||
|
|
||||||
|
- fix(iform_authenticated): missmatch of role name
|
||||||
|
|
||||||
|
|
||||||
|
Version v0.12.2 (release 2024-07-19)
|
||||||
|
|
||||||
|
- setup: introduce ruff
|
||||||
|
- perm: implement single-ip and ip-network
|
||||||
|
- utils: add invenio_saml-compatible account-setup
|
||||||
|
- add new permission-policy, add new role
|
||||||
|
- fix deprecated `before_app_first_request`
|
||||||
|
- setup: add support for python3.11 and 3.12
|
||||||
|
|
||||||
|
|
||||||
|
Version v0.12.1 (release 2024-03-08)
|
||||||
|
|
||||||
|
- setup: remove upper limit of rdm-records
|
||||||
|
|
||||||
|
|
||||||
|
Version v0.12.0 (release 2023-11-10)
|
||||||
|
|
||||||
|
- setup: remove python3.8 support
|
||||||
|
- global: make it compatible with v12
|
||||||
|
|
||||||
|
|
||||||
|
Version v0.11.0 (release 2023-04-20)
|
||||||
|
|
||||||
|
- global: make package compatible with v11
|
||||||
|
|
||||||
|
|
||||||
|
Version v0.10.4 (release 2023-02-10)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Version v0.10.2 (release 2023-02-02)
|
||||||
|
|
||||||
|
- change version name
|
||||||
|
- footer: update guid
|
||||||
|
|
||||||
|
|
||||||
|
Version v0.10.1 (release 2022-11-17)
|
||||||
|
|
||||||
|
- global: add function
|
||||||
|
|
||||||
|
Version 0.10.0 (released 2022-10-13)
|
||||||
|
|
||||||
|
- global: migrate to v10 (#101)
|
||||||
|
|
||||||
|
Version 0.9.1 (released 2022-05-30)
|
||||||
|
|
||||||
|
- ci(publish): ping babel version (#99)
|
||||||
|
|
||||||
|
Version 0.9.0 (released 2022-05-30)
|
||||||
|
|
||||||
|
- config: adds new introduced configs v9
|
||||||
|
- dep: compatible to v9 rdm
|
||||||
|
- config: add deposit form quota variable (#91)
|
||||||
|
- migrate setup py to cfg (#94)
|
||||||
|
- fix: update email welcome template with SITE_UI_URL (#93)
|
||||||
|
|
||||||
|
Version 0.8.4 (released 2022-03-11)
|
||||||
|
|
||||||
|
- config: use gettext
|
||||||
|
|
||||||
|
Version 0.8.3 (released 2022-03-10)
|
||||||
|
|
||||||
|
- config: fix comment & import
|
||||||
|
|
||||||
|
Version 0.8.2 (released 2022-03-03)
|
||||||
|
|
||||||
|
- config: new introduced to v8 of invenioRDM
|
||||||
|
|
||||||
|
Version 0.8.1 (released 2022-02-28)
|
||||||
|
|
||||||
|
- config: set samesite cookie to strict
|
||||||
|
- dep: bump in base dependencies
|
||||||
|
|
||||||
Version 0.8.0 (released 2022-02-09)
|
Version 0.8.0 (released 2022-02-09)
|
||||||
|
|
||||||
- dep: bump rdm-records version
|
- dep: bump rdm-records version
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ Types of Contributions
|
|||||||
Report Bugs
|
Report Bugs
|
||||||
~~~~~~~~~~~
|
~~~~~~~~~~~
|
||||||
|
|
||||||
Report bugs at https://github.com/tu-graz-library/invenio-config-tugraz/issues.
|
Report bugs at https://github.com/Cian-H/invenio-config-iform/issues.
|
||||||
|
|
||||||
If you are reporting a bug, please include:
|
If you are reporting a bug, please include:
|
||||||
|
|
||||||
@@ -33,15 +33,15 @@ is open to whoever wants to implement it.
|
|||||||
Write Documentation
|
Write Documentation
|
||||||
~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
invenio-config-tugraz could always use more documentation, whether as part of the
|
invenio-config-iform could always use more documentation, whether as part of the
|
||||||
official invenio-config-tugraz docs, in docstrings, or even on the web in blog posts,
|
official invenio-config-iform docs, in docstrings, or even on the web in blog posts,
|
||||||
articles, and such.
|
articles, and such.
|
||||||
|
|
||||||
Submit Feedback
|
Submit Feedback
|
||||||
~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
The best way to send feedback is to file an issue at
|
The best way to send feedback is to file an issue at
|
||||||
https://github.com/tu-graz-library/invenio-config-tugraz/issues.
|
https://github.com/Cian-H/invenio-config-iform/issues.
|
||||||
|
|
||||||
If you are proposing a feature:
|
If you are proposing a feature:
|
||||||
|
|
||||||
@@ -53,14 +53,14 @@ If you are proposing a feature:
|
|||||||
Get Started!
|
Get Started!
|
||||||
------------
|
------------
|
||||||
|
|
||||||
Ready to contribute? Here's how to set up `invenio-config-tugraz` for local development.
|
Ready to contribute? Here's how to set up `invenio-config-iform` for local development.
|
||||||
|
|
||||||
1. Fork the `https://github.com/https://github.com/mb-` repo on GitHub.
|
1. Fork the `https://github.com/https://github.com/mb-` repo on GitHub.
|
||||||
2. Clone your fork locally:
|
2. Clone your fork locally:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ git clone git@github.com:your_name_here/invenio-config-tugraz.git
|
$ git clone git@github.com:your_name_here/invenio-config-iform.git
|
||||||
|
|
||||||
3. Install your local copy into a virtualenv. Assuming you have
|
3. Install your local copy into a virtualenv. Assuming you have
|
||||||
virtualenvwrapper installed, this is how you set up your fork for local
|
virtualenvwrapper installed, this is how you set up your fork for local
|
||||||
@@ -68,8 +68,8 @@ Ready to contribute? Here's how to set up `invenio-config-tugraz` for local deve
|
|||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ mkvirtualenv invenio-config-tugraz
|
$ mkvirtualenv invenio-config-iform
|
||||||
$ cd invenio-config-tugraz/
|
$ cd invenio-config-iform/
|
||||||
$ pip install -e .[all]
|
$ pip install -e .[all]
|
||||||
|
|
||||||
4. Create a branch for local development:
|
4. Create a branch for local development:
|
||||||
@@ -114,5 +114,5 @@ Before you submit a pull request, check that it meets these guidelines:
|
|||||||
2. If the pull request adds functionality, the docs should be updated. Put
|
2. If the pull request adds functionality, the docs should be updated. Put
|
||||||
your new functionality into a function with a docstring.
|
your new functionality into a function with a docstring.
|
||||||
3. The pull request should work for Python 3.6 and 3.7. Check
|
3. The pull request should work for Python 3.6 and 3.7. Check
|
||||||
https://github.com/github/tu-graz-library/invenio-config-tugraz//actions?query=event%3Apull_request
|
https://github.com/github/Cian-H/invenio-config-iform//actions?query=event%3Apull_request
|
||||||
and make sure that the tests pass for all supported Python versions.
|
and make sure that the tests pass for all supported Python versions.
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
Installation
|
Installation
|
||||||
============
|
============
|
||||||
|
|
||||||
invenio-config-tugraz is on PyPI so all you need is:
|
invenio-config-iform is on PyPI so all you need is:
|
||||||
|
|
||||||
.. code-block:: console
|
.. code-block:: console
|
||||||
|
|
||||||
$ pip install invenio-config-tugraz
|
$ pip install invenio-config-iform
|
||||||
|
|||||||
54
MANIFEST.in
54
MANIFEST.in
@@ -1,54 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Copyright (C) 2020 Mojib Wali.
|
|
||||||
#
|
|
||||||
# invenio-config-tugraz is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
||||||
# details.
|
|
||||||
|
|
||||||
# TODO: Generate this manifest file by running the following commands:
|
|
||||||
# (please sort the lines in this file after running below commands)
|
|
||||||
#
|
|
||||||
# git init
|
|
||||||
# git add -A
|
|
||||||
# pip install -e .[all]
|
|
||||||
# check-manifest -u
|
|
||||||
|
|
||||||
include .dockerignore
|
|
||||||
include .editorconfig
|
|
||||||
include .tx/config
|
|
||||||
prune docs/_build
|
|
||||||
recursive-include invenio_config_tugraz/translations *.po *.pot *.mo
|
|
||||||
|
|
||||||
# added by check_manifest.py
|
|
||||||
include *.md
|
|
||||||
include *.rst
|
|
||||||
include *.sh
|
|
||||||
include *.txt
|
|
||||||
include *.rst
|
|
||||||
include LICENSE
|
|
||||||
include babel.ini
|
|
||||||
include pytest.ini
|
|
||||||
recursive-include docs *.bat
|
|
||||||
recursive-include docs *.py
|
|
||||||
recursive-include docs *.rst
|
|
||||||
recursive-include docs *.txt
|
|
||||||
recursive-include docs Makefile
|
|
||||||
recursive-include tests *.py
|
|
||||||
|
|
||||||
|
|
||||||
# added by check_manifest.py
|
|
||||||
recursive-include invenio_config_tugraz *.crt
|
|
||||||
recursive-include invenio_config_tugraz *.json
|
|
||||||
recursive-include invenio_config_tugraz *.key
|
|
||||||
recursive-include invenio_config_tugraz *.xml
|
|
||||||
recursive-include invenio_config_tugraz *.gitkeep
|
|
||||||
recursive-include invenio_config_tugraz *.txt
|
|
||||||
recursive-include invenio_config_tugraz *.html
|
|
||||||
|
|
||||||
|
|
||||||
# added by check-manifest
|
|
||||||
recursive-include invenio_config_tugraz *.csv
|
|
||||||
|
|
||||||
# added by check-manifest
|
|
||||||
recursive-include invenio_config_tugraz *.pdf
|
|
||||||
42
README.rst
42
README.rst
@@ -1,45 +1,47 @@
|
|||||||
..
|
..
|
||||||
Copyright (C) 2020-2021 Graz University of Technology.
|
Copyright (C) 2020-2021 Graz University of Technology.
|
||||||
|
|
||||||
invenio-config-tugraz is free software; you can redistribute it and/or
|
invenio-config-iform is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the MIT License; see LICENSE file for more
|
modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
details.
|
details.
|
||||||
|
|
||||||
=======================
|
=======================
|
||||||
invenio-config-tugraz
|
invenio-config-iform
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
.. image:: https://github.com/tu-graz-library/invenio-config-tugraz/workflows/CI/badge.svg
|
.. image:: https://github.com/Cian-H/invenio-config-iform/workflows/CI/badge.svg
|
||||||
:target: https://github.com/tu-graz-library/invenio-config-tugraz/actions
|
:target: https://github.com/Cian-H/invenio-config-iform/actions
|
||||||
|
|
||||||
.. image:: https://img.shields.io/pypi/dm/invenio-config-tugraz.svg
|
.. image:: https://img.shields.io/pypi/dm/invenio-config-iform.svg
|
||||||
:target: https://pypi.python.org/pypi/invenio-config-tugraz
|
:target: https://pypi.python.org/pypi/invenio-config-iform
|
||||||
|
|
||||||
.. image:: https://img.shields.io/github/tag/tu-graz-library/invenio-config-tugraz.svg
|
.. image:: https://img.shields.io/github/tag/Cian-H/invenio-config-iform.svg
|
||||||
:target: https://github.com/mb-wali/invenio-config-tugraz/releases
|
:target: https://github.com/Cian-H/invenio-config-iform/releases
|
||||||
|
|
||||||
.. image:: https://img.shields.io/github/license/tu-graz-library/invenio-config-tugraz.svg
|
.. image:: https://img.shields.io/github/license/Cian-H/invenio-config-iform.svg
|
||||||
:target: https://github.com/mb-wali/invenio-config-tugraz/blob/master/LICENSE
|
:target: https://github.com/Cian-H/invenio-config-iform/blob/master/LICENSE
|
||||||
|
|
||||||
.. image:: https://readthedocs.org/projects/invenio-config-tugraz/badge/?version=latest
|
.. image:: https://readthedocs.org/projects/invenio-config-iform/badge/?version=latest
|
||||||
:target: https://invenio-config-tugraz.readthedocs.io/en/latest/?badge=latest
|
:target: https://invenio-config-iform.readthedocs.io/en/latest/?badge=latest
|
||||||
|
|
||||||
.. image:: https://img.shields.io/coveralls/mb-wali/invenio-config-tugraz.svg
|
.. image:: https://coveralls.io/repos/github/Cian-H/invenio-config-iform/badge.svg?branch=master
|
||||||
:target: https://coveralls.io/r/mb-wali/invenio-config-tugraz
|
:target: https://coveralls.io/github/Cian-H/invenio-config-iform?branch=master
|
||||||
|
|
||||||
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
|
.. image:: https://img.shields.io/badge/code%20style-Ruff-D7FF64.svg
|
||||||
:target: https://github.com/psf/black
|
:target: https://github.com/astral-sh/ruff
|
||||||
|
|
||||||
invenio module that adds tugraz configs.
|
invenio module that adds I-Form configs.
|
||||||
|
|
||||||
Override configs from diffrent invenio modules to meet TU Graz requirement:
|
Override configs from invenio modules with I-Form configurations:
|
||||||
|
|
||||||
* Invenio-App
|
* Invenio-App
|
||||||
* Invenio-Mail
|
* Invenio-Mail
|
||||||
* Invenio-shibboleth
|
* Invenio-shibboleth
|
||||||
* Invenio-accounts
|
* Invenio-accounts
|
||||||
* Flask-security
|
* Flask-security
|
||||||
* Defined routes for TUG
|
* Defined routes for I-Form
|
||||||
|
|
||||||
Further documentation is available on
|
Further documentation is available on
|
||||||
https://invenio-config-tugraz.readthedocs.io/
|
https://invenio-config-iform.readthedocs.io/
|
||||||
|
|
||||||
|
Forked from https://github.com/tu-graz-library/invenio-config-tugraz
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#
|
#
|
||||||
# Copyright (C) 2020 Mojib Wali.
|
# Copyright (C) 2020 Mojib Wali.
|
||||||
#
|
#
|
||||||
# invenio-config-tugraz is free software; you can redistribute it and/or
|
# invenio-config-iform is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the MIT License; see LICENSE file for more
|
# modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
# details.
|
# details.
|
||||||
|
|
||||||
@@ -15,7 +15,6 @@ encoding = utf-8
|
|||||||
|
|
||||||
[jinja2: **/templates/**.*]
|
[jinja2: **/templates/**.*]
|
||||||
encoding = utf-8
|
encoding = utf-8
|
||||||
extensions = jinja2.ext.autoescape, jinja2.ext.with_
|
|
||||||
|
|
||||||
# Extraction from JavaScript files
|
# Extraction from JavaScript files
|
||||||
|
|
||||||
|
|||||||
103
devenv.lock
Normal file
103
devenv.lock
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"devenv": {
|
||||||
|
"locked": {
|
||||||
|
"dir": "src/modules",
|
||||||
|
"lastModified": 1746707904,
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "devenv",
|
||||||
|
"rev": "fada79d97f2066c444766d039b0a62affd3e3cab",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"dir": "src/modules",
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "devenv",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-compat": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1733328505,
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "edolstra",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"git-hooks": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-compat": "flake-compat",
|
||||||
|
"gitignore": "gitignore",
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1746537231,
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "git-hooks.nix",
|
||||||
|
"rev": "fa466640195d38ec97cf0493d6d6882bc4d14969",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "git-hooks.nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gitignore": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"git-hooks",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1709087332,
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "gitignore.nix",
|
||||||
|
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "gitignore.nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1745934659,
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "devenv-nixpkgs",
|
||||||
|
"rev": "fbc071e5c11e23fba50037de37268e3d8a1858eb",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "cachix",
|
||||||
|
"ref": "rolling",
|
||||||
|
"repo": "devenv-nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"devenv": "devenv",
|
||||||
|
"git-hooks": "git-hooks",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"pre-commit-hooks": [
|
||||||
|
"git-hooks"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
19
devenv.nix
Normal file
19
devenv.nix
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
inputs,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
packages = [
|
||||||
|
pkgs.git
|
||||||
|
pkgs.act
|
||||||
|
];
|
||||||
|
|
||||||
|
languages.python = {
|
||||||
|
enable = true;
|
||||||
|
uv = {
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
4
devenv.yaml
Normal file
4
devenv.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# yaml-language-server: $schema=https://devenv.sh/devenv.schema.json
|
||||||
|
inputs:
|
||||||
|
nixpkgs:
|
||||||
|
url: github:cachix/devenv-nixpkgs/rolling
|
||||||
@@ -87,9 +87,9 @@ qthelp:
|
|||||||
@echo
|
@echo
|
||||||
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||||
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||||
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/invenio-config-tugraz.qhcp"
|
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/invenio-config-iform.qhcp"
|
||||||
@echo "To view the help file:"
|
@echo "To view the help file:"
|
||||||
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/invenio-config-tugraz.qhc"
|
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/invenio-config-iform.qhc"
|
||||||
|
|
||||||
applehelp:
|
applehelp:
|
||||||
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
|
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
|
||||||
@@ -104,8 +104,8 @@ devhelp:
|
|||||||
@echo
|
@echo
|
||||||
@echo "Build finished."
|
@echo "Build finished."
|
||||||
@echo "To view the help file:"
|
@echo "To view the help file:"
|
||||||
@echo "# mkdir -p $$HOME/.local/share/devhelp/invenio-config-tugraz"
|
@echo "# mkdir -p $$HOME/.local/share/devhelp/invenio-config-iform"
|
||||||
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/invenio-config-tugraz"
|
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/invenio-config-iform"
|
||||||
@echo "# devhelp"
|
@echo "# devhelp"
|
||||||
|
|
||||||
epub:
|
epub:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
..
|
..
|
||||||
Copyright (C) 2020 Mojib Wali.
|
Copyright (C) 2020 Mojib Wali.
|
||||||
|
|
||||||
invenio-config-tugraz is free software; you can redistribute it and/or
|
invenio-config-iform is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the MIT License; see LICENSE file for more
|
modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
details.
|
details.
|
||||||
|
|
||||||
@@ -9,5 +9,5 @@
|
|||||||
API Docs
|
API Docs
|
||||||
========
|
========
|
||||||
|
|
||||||
.. automodule:: invenio_config_tugraz.ext
|
.. automodule:: invenio_config_iform.ext
|
||||||
:members:
|
:members:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
..
|
..
|
||||||
Copyright (C) 2020 Mojib Wali.
|
Copyright (C) 2020 Mojib Wali.
|
||||||
|
|
||||||
invenio-config-tugraz is free software; you can redistribute it and/or
|
invenio-config-iform is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the MIT License; see LICENSE file for more
|
modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
details.
|
details.
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
..
|
..
|
||||||
Copyright (C) 2020 Mojib Wali.
|
Copyright (C) 2020 Mojib Wali.
|
||||||
|
|
||||||
invenio-config-tugraz is free software; you can redistribute it and/or
|
invenio-config-iform is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the MIT License; see LICENSE file for more
|
modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
details.
|
details.
|
||||||
|
|
||||||
|
|||||||
63
docs/conf.py
63
docs/conf.py
@@ -2,13 +2,13 @@
|
|||||||
#
|
#
|
||||||
# Copyright (C) 2020 Mojib Wali.
|
# Copyright (C) 2020 Mojib Wali.
|
||||||
#
|
#
|
||||||
# invenio-config-tugraz is free software; you can redistribute it and/or
|
# invenio-config-iform is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the MIT License; see LICENSE file for more
|
# modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
# details.
|
# details.
|
||||||
|
|
||||||
"""Sphinx configuration."""
|
"""Sphinx configuration."""
|
||||||
|
|
||||||
import os
|
from invenio_config_iform import __version__
|
||||||
|
|
||||||
# import sphinx.environment
|
# import sphinx.environment
|
||||||
|
|
||||||
@@ -46,9 +46,9 @@ source_suffix = ".rst"
|
|||||||
master_doc = "index"
|
master_doc = "index"
|
||||||
|
|
||||||
# General information about the project.
|
# General information about the project.
|
||||||
project = u"invenio-config-tugraz"
|
project = "invenio-config-iform"
|
||||||
copyright = u"2020, Mojib Wali"
|
copyright = "2025, I-Form"
|
||||||
author = u"Mojib Wali"
|
author = "I-Form"
|
||||||
|
|
||||||
# The version info for the project you're documenting, acts as replacement for
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
# |version| and |release|, also used in various other places throughout the
|
# |version| and |release|, also used in various other places throughout the
|
||||||
@@ -56,26 +56,15 @@ author = u"Mojib Wali"
|
|||||||
#
|
#
|
||||||
# The short X.Y version.
|
# The short X.Y version.
|
||||||
|
|
||||||
# Get the version string. Cannot be done with import!
|
|
||||||
g = {}
|
|
||||||
with open(
|
|
||||||
os.path.join(
|
|
||||||
os.path.dirname(__file__), "..", "invenio_config_tugraz", "version.py"
|
|
||||||
),
|
|
||||||
"rt",
|
|
||||||
) as fp:
|
|
||||||
exec(fp.read(), g)
|
|
||||||
version = g["__version__"]
|
|
||||||
|
|
||||||
# The full version, including alpha/beta/rc tags.
|
# The full version, including alpha/beta/rc tags.
|
||||||
release = version
|
release = __version__
|
||||||
|
|
||||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
# for a list of supported languages.
|
# for a list of supported languages.
|
||||||
#
|
#
|
||||||
# This is also used if you do content translation via gettext catalogs.
|
# This is also used if you do content translation via gettext catalogs.
|
||||||
# Usually you set "language" from the command line for these cases.
|
# Usually you set "language" from the command line for these cases.
|
||||||
language = None
|
language = "en"
|
||||||
|
|
||||||
# There are two options for replacing |today|: either, you set today to some
|
# There are two options for replacing |today|: either, you set today to some
|
||||||
# non-false value, then it is used:
|
# non-false value, then it is used:
|
||||||
@@ -119,15 +108,15 @@ todo_include_todos = False
|
|||||||
html_theme = "alabaster"
|
html_theme = "alabaster"
|
||||||
|
|
||||||
html_theme_options = {
|
html_theme_options = {
|
||||||
"description": "invenio module that adds tugraz configs.",
|
"description": "invenio module that adds iform configs.",
|
||||||
"github_user": "TU Graz",
|
"github_user": "Cian-H",
|
||||||
"github_repo": "invenio-config-tugraz",
|
"github_repo": "invenio-config-iform",
|
||||||
"github_button": False,
|
"github_button": True,
|
||||||
"github_banner": True,
|
"github_banner": False,
|
||||||
"show_powered_by": False,
|
"show_powered_by": False,
|
||||||
"extra_nav_links": {
|
"extra_nav_links": {
|
||||||
"invenio-config-tugraz@GitHub": "https://github.com/tu-graz-library/invenio-config-tugraz",
|
"invenio-config-iform@Github": "https://github.com/Cian-H/invenio-config-iform",
|
||||||
"invenio-config-tugraz@PyPI": "https://pypi.python.org/pypi/invenio-config-tugraz/",
|
"invenio-config-iform@PyPI": "https://pypi.python.org/pypi/invenio-config-iform/",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,7 +221,7 @@ html_sidebars = {
|
|||||||
# html_search_scorer = 'scorer.js'
|
# html_search_scorer = 'scorer.js'
|
||||||
|
|
||||||
# Output file base name for HTML help builder.
|
# Output file base name for HTML help builder.
|
||||||
htmlhelp_basename = "invenio-config-tugraz_namedoc"
|
htmlhelp_basename = "invenio-config-iform_namedoc"
|
||||||
|
|
||||||
# -- Options for LaTeX output ---------------------------------------------
|
# -- Options for LaTeX output ---------------------------------------------
|
||||||
|
|
||||||
@@ -253,9 +242,9 @@ latex_elements = {
|
|||||||
latex_documents = [
|
latex_documents = [
|
||||||
(
|
(
|
||||||
master_doc,
|
master_doc,
|
||||||
"invenio-config-tugraz.tex",
|
"invenio-config-iform.tex",
|
||||||
u"invenio-config-tugraz Documentation",
|
"invenio-config-iform Documentation",
|
||||||
u"Mojib Wali",
|
"I-Form",
|
||||||
"manual",
|
"manual",
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
@@ -288,8 +277,8 @@ latex_documents = [
|
|||||||
man_pages = [
|
man_pages = [
|
||||||
(
|
(
|
||||||
master_doc,
|
master_doc,
|
||||||
"invenio-config-tugraz",
|
"invenio-config-iform",
|
||||||
u"invenio-config-tugraz Documentation",
|
"invenio-config-iform Documentation",
|
||||||
[author],
|
[author],
|
||||||
1,
|
1,
|
||||||
)
|
)
|
||||||
@@ -307,11 +296,11 @@ man_pages = [
|
|||||||
texinfo_documents = [
|
texinfo_documents = [
|
||||||
(
|
(
|
||||||
master_doc,
|
master_doc,
|
||||||
"invenio-config-tugraz",
|
"invenio-config-iform",
|
||||||
u"invenio-config-tugraz Documentation",
|
"invenio-config-iform Documentation",
|
||||||
author,
|
author,
|
||||||
"invenio-config-tugraz",
|
"invenio-config-iform",
|
||||||
"invenio module that adds tugraz configs.",
|
"invenio module that adds iform configs.",
|
||||||
"Miscellaneous",
|
"Miscellaneous",
|
||||||
),
|
),
|
||||||
]
|
]
|
||||||
@@ -332,8 +321,8 @@ texinfo_documents = [
|
|||||||
# Example configuration for intersphinx: refer to the Python standard library.
|
# Example configuration for intersphinx: refer to the Python standard library.
|
||||||
intersphinx_mapping = {
|
intersphinx_mapping = {
|
||||||
"python": ("https://docs.python.org/", None),
|
"python": ("https://docs.python.org/", None),
|
||||||
'flask': ('https://flask.palletsprojects.com/', None),
|
"flask": ("https://flask.palletsprojects.com/", None),
|
||||||
'werkzeug': ('https://werkzeug.palletsprojects.com/', None),
|
"werkzeug": ("https://werkzeug.palletsprojects.com/", None),
|
||||||
# TODO: Configure external documentation references, eg:
|
# TODO: Configure external documentation references, eg:
|
||||||
# 'Flask-Admin': ('https://flask-admin.readthedocs.io/en/latest/', None),
|
# 'Flask-Admin': ('https://flask-admin.readthedocs.io/en/latest/', None),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
..
|
..
|
||||||
Copyright (C) 2020 Mojib Wali.
|
Copyright (C) 2020 Mojib Wali.
|
||||||
|
|
||||||
invenio-config-tugraz is free software; you can redistribute it and/or
|
invenio-config-iform is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the MIT License; see LICENSE file for more
|
modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
details.
|
details.
|
||||||
|
|
||||||
@@ -9,5 +9,5 @@
|
|||||||
Configuration
|
Configuration
|
||||||
=============
|
=============
|
||||||
|
|
||||||
.. automodule:: invenio_config_tugraz.config
|
.. automodule:: invenio_config_iform.config
|
||||||
:members:
|
:members:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
..
|
..
|
||||||
Copyright (C) 2020 Mojib Wali.
|
Copyright (C) 2020 Mojib Wali.
|
||||||
|
|
||||||
invenio-config-tugraz is free software; you can redistribute it and/or
|
invenio-config-iform is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the MIT License; see LICENSE file for more
|
modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
details.
|
details.
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
..
|
..
|
||||||
Copyright (C) 2020 Mojib Wali.
|
Copyright (C) 2020 Mojib Wali.
|
||||||
|
|
||||||
invenio-config-tugraz is free software; you can redistribute it and/or
|
invenio-config-iform is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the MIT License; see LICENSE file for more
|
modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
details.
|
details.
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ User's Guide
|
|||||||
------------
|
------------
|
||||||
|
|
||||||
This part of the documentation will show you how to get started in using
|
This part of the documentation will show you how to get started in using
|
||||||
invenio-config-tugraz.
|
invenio-config-iform.
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
:maxdepth: 2
|
:maxdepth: 2
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
..
|
..
|
||||||
Copyright (C) 2020 Mojib Wali.
|
Copyright (C) 2020 Mojib Wali.
|
||||||
|
|
||||||
invenio-config-tugraz is free software; you can redistribute it and/or
|
invenio-config-iform is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the MIT License; see LICENSE file for more
|
modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
details.
|
details.
|
||||||
|
|
||||||
|
|||||||
@@ -127,9 +127,9 @@ if "%1" == "qthelp" (
|
|||||||
echo.
|
echo.
|
||||||
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
echo.Build finished; now you can run "qcollectiongenerator" with the ^
|
||||||
.qhcp project file in %BUILDDIR%/qthelp, like this:
|
.qhcp project file in %BUILDDIR%/qthelp, like this:
|
||||||
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\invenio-config-tugraz.qhcp
|
echo.^> qcollectiongenerator %BUILDDIR%\qthelp\invenio-config-iform.qhcp
|
||||||
echo.To view the help file:
|
echo.To view the help file:
|
||||||
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\invenio-config-tugraz.ghc
|
echo.^> assistant -collectionFile %BUILDDIR%\qthelp\invenio-config-iform.ghc
|
||||||
goto end
|
goto end
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
-e .[docs,tests]
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
..
|
..
|
||||||
Copyright (C) 2020 Mojib Wali.
|
Copyright (C) 2020 Mojib Wali.
|
||||||
|
|
||||||
invenio-config-tugraz is free software; you can redistribute it and/or
|
invenio-config-iform is free software; you can redistribute it and/or
|
||||||
modify it under the terms of the MIT License; see LICENSE file for more
|
modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
details.
|
details.
|
||||||
|
|
||||||
@@ -9,4 +9,4 @@
|
|||||||
Usage
|
Usage
|
||||||
=====
|
=====
|
||||||
|
|
||||||
.. automodule:: invenio_config_tugraz
|
.. automodule:: invenio_config_iform
|
||||||
|
|||||||
11
invenio_config_iform/__about__.py
Normal file
11
invenio_config_iform/__about__.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2025 I-Form Advanced Manufacturing Research Centre.
|
||||||
|
#
|
||||||
|
# invenio-config-iform is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
|
# details.
|
||||||
|
|
||||||
|
"""Metadata for this python module."""
|
||||||
|
|
||||||
|
__version__ = "2025.5.20.21"
|
||||||
19
invenio_config_iform/__init__.py
Normal file
19
invenio_config_iform/__init__.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2020-2024 Graz University of Technology.
|
||||||
|
#
|
||||||
|
# invenio-config-iform is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
|
# details.
|
||||||
|
|
||||||
|
"""invenio module that adds I-Form configs."""
|
||||||
|
|
||||||
|
from .__about__ import __version__
|
||||||
|
from .ext import InvenioConfigIform
|
||||||
|
from .utils import get_identity_from_user_by_email
|
||||||
|
|
||||||
|
__all__ = (
|
||||||
|
"InvenioConfigIform",
|
||||||
|
"__version__",
|
||||||
|
"get_identity_from_user_by_email",
|
||||||
|
)
|
||||||
@@ -1,36 +1,37 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (C) 2020-2021 Graz University of Technology.
|
# Copyright (C) 2020-2024 Graz University of Technology.
|
||||||
#
|
#
|
||||||
# invenio-config-tugraz is free software; you can redistribute it and/or
|
# invenio-config-iform is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the MIT License; see LICENSE file for more
|
# modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
# details.
|
# details.
|
||||||
|
|
||||||
"""invenio module that adds tugraz configs."""
|
"""invenio module that adds I-Form configs."""
|
||||||
|
|
||||||
from os.path import abspath, dirname, join
|
from invenio_i18n import gettext as _
|
||||||
|
|
||||||
from flask_babelex import gettext as _
|
CONFIG_IFORM_SHIBBOLETH = False
|
||||||
|
|
||||||
INVENIO_CONFIG_TUGRAZ_SHIBBOLETH = False
|
|
||||||
"""Set True if SAML is configured"""
|
"""Set True if SAML is configured"""
|
||||||
|
|
||||||
INVENIO_CONFIG_TUGRAZ_SINGLE_IP = []
|
CONFIG_IFORM_SINGLE_IPS = []
|
||||||
"""Allows access to users whose IP address is listed.
|
"""Allows access to users whose IP address is listed.
|
||||||
|
|
||||||
INVENIO_CONFIG_TUGRAZ_SINGLE_IP =
|
INVENIO_CONFIG_IFORM_SINGLE_IPS =
|
||||||
["127.0.0.1", "127.0.0.2"]
|
["127.0.0.1", "127.0.0.2"]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
INVENIO_CONFIG_TUGRAZ_IP_RANGES = []
|
CONFIG_IFORM_IP_RANGES = []
|
||||||
"""Allows access to users whose range of IP address is listed.
|
"""Allows access to users whose range of IP address is listed.
|
||||||
|
|
||||||
INVENIO_CONFIG_TUGRAZ_IP_RANGES =
|
INVENIO_CONFIG_IFORM_IP_RANGES =
|
||||||
[["127.0.0.2", "127.0.0.99"], ["127.0.1.3", "127.0.1.5"]]
|
[["127.0.0.2", "127.0.0.99"], ["127.0.1.3", "127.0.1.5"]]
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
CONFIG_IFORM_IP_NETWORK = ""
|
||||||
|
"""Allows access to users who are in the IP network."""
|
||||||
|
|
||||||
CONFIG_TUGRAZ_ROUTES = {
|
|
||||||
|
CONFIG_IFORM_ROUTES = {
|
||||||
"guide": "/guide",
|
"guide": "/guide",
|
||||||
"terms": "/terms",
|
"terms": "/terms",
|
||||||
"gdpr": "/gdpr",
|
"gdpr": "/gdpr",
|
||||||
@@ -180,6 +181,9 @@ SECURITY_CONFIRMABLE = False
|
|||||||
Instead user will get a welcome email.
|
Instead user will get a welcome email.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
SECURITY_LOGIN_WITHOUT_CONFIRMATION = False
|
||||||
|
"""Require users to confirm email before being able to login."""
|
||||||
|
|
||||||
# Flask-Security
|
# Flask-Security
|
||||||
# =============
|
# =============
|
||||||
# See https://pythonhosted.org/Flask-Security/configuration.html
|
# See https://pythonhosted.org/Flask-Security/configuration.html
|
||||||
@@ -197,7 +201,7 @@ If False, you won't be able to login via the web UI.
|
|||||||
|
|
||||||
Instead if you have a overriden template somewhere in your config.py:
|
Instead if you have a overriden template somewhere in your config.py:
|
||||||
like this:
|
like this:
|
||||||
SECURITY_LOGIN_USER_TEMPLATE = 'invenio_theme_tugraz/accounts/login.html'
|
SECURITY_LOGIN_USER_TEMPLATE = 'invenio_theme_iform/accounts/login.html'
|
||||||
then you can remove this condition from header_login.htm:
|
then you can remove this condition from header_login.htm:
|
||||||
{%- if config.ACCOUNTS %}
|
{%- if config.ACCOUNTS %}
|
||||||
to render your overriden login.html
|
to render your overriden login.html
|
||||||
@@ -216,8 +220,8 @@ RECAPTCHA_PRIVATE_KEY = None
|
|||||||
# See:
|
# See:
|
||||||
# https://invenio-records-permissions.readthedocs.io/en/latest/configuration.html
|
# https://invenio-records-permissions.readthedocs.io/en/latest/configuration.html
|
||||||
# Uncomment these to enable overriding RDM permissions
|
# Uncomment these to enable overriding RDM permissions
|
||||||
# from .rdm_permissions import TUGRAZRDMRecordServiceConfig
|
# from .rdm_permissions import IformRDMRecordServiceConfig
|
||||||
# RDM_RECORDS_BIBLIOGRAPHIC_SERVICE_CONFIG = TUGRAZRDMRecordServiceConfig
|
# RDM_RECORDS_BIBLIOGRAPHIC_SERVICE_CONFIG = IformRDMRecordServiceConfig
|
||||||
"""Access control configuration for records."""
|
"""Access control configuration for records."""
|
||||||
|
|
||||||
# invenio-rdm-records
|
# invenio-rdm-records
|
||||||
@@ -239,6 +243,13 @@ will be generated randomly.
|
|||||||
DATACITE_FORMAT = "{prefix}/{id}"
|
DATACITE_FORMAT = "{prefix}/{id}"
|
||||||
"""Customize the generated DOI string."""
|
"""Customize the generated DOI string."""
|
||||||
|
|
||||||
|
DATACITE_DATACENTER_SYMBOL = ""
|
||||||
|
""""The OAI-PMH server's metadata format oai_datacite
|
||||||
|
that allows you to harvest record from InvenioRDM in DataCite XML needs
|
||||||
|
to be configured with your DataCite data center symbol.
|
||||||
|
This is only required if you want your records to be harvestable in DataCite XML format.
|
||||||
|
"""
|
||||||
|
|
||||||
# Invenio-app-rdm
|
# Invenio-app-rdm
|
||||||
# =========================
|
# =========================
|
||||||
# See https://github.com/inveniosoftware/invenio-app-rdm/blob/master/invenio_app_rdm/config.py
|
# See https://github.com/inveniosoftware/invenio-app-rdm/blob/master/invenio_app_rdm/config.py
|
||||||
@@ -253,6 +264,28 @@ If the value is callable, its return value will be used for the field
|
|||||||
(e.g. lambda/function for dynamic calculation of values).
|
(e.g. lambda/function for dynamic calculation of values).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
APP_RDM_DEPOSIT_FORM_AUTOCOMPLETE_NAMES = "off"
|
||||||
|
"""Behavior for autocomplete names search field for creators/contributors.
|
||||||
|
|
||||||
|
Available options:
|
||||||
|
|
||||||
|
- ``search`` (default): Show search field and form always.
|
||||||
|
- ``search_only``: Only show search field. Form displayed after selection or
|
||||||
|
explicit "manual" entry.
|
||||||
|
- ``off``: Only show person form (no search field).
|
||||||
|
"""
|
||||||
|
|
||||||
|
APP_RDM_DEPOSIT_FORM_QUOTA = {
|
||||||
|
"maxFiles": 100,
|
||||||
|
# Easiest way to set this to a certain amount is to start from 1 Gb
|
||||||
|
# and go from there:
|
||||||
|
# 1 Gb: 10 ** 9
|
||||||
|
# 50 Gb: 10 ** 9 * 50
|
||||||
|
# 100 Mb: 10 ** 9 * 0.1
|
||||||
|
"maxStorage": 10**9 * 10,
|
||||||
|
}
|
||||||
|
"""Deposit file upload quota """
|
||||||
|
|
||||||
SQLALCHEMY_ECHO = False
|
SQLALCHEMY_ECHO = False
|
||||||
"""Enable to see all SQL queries."""
|
"""Enable to see all SQL queries."""
|
||||||
|
|
||||||
@@ -324,6 +357,10 @@ RATELIMIT_AUTHENTICATED_USER = "25000 per hour;1000 per minute"
|
|||||||
RATELIMIT_GUEST_USER = "5000 per hour;500 per minute"
|
RATELIMIT_GUEST_USER = "5000 per hour;500 per minute"
|
||||||
"""Increase defaults for guest users."""
|
"""Increase defaults for guest users."""
|
||||||
|
|
||||||
|
SESSION_COOKIE_SAMESITE = "Strict"
|
||||||
|
"""Sets cookie with the samesite flag to 'Strict' by default."""
|
||||||
|
|
||||||
|
|
||||||
# OAI-PMH
|
# OAI-PMH
|
||||||
# =======
|
# =======
|
||||||
# See https://github.com/inveniosoftware/invenio-oaiserver/blob/master/invenio_oaiserver/config.py
|
# See https://github.com/inveniosoftware/invenio-oaiserver/blob/master/invenio_oaiserver/config.py
|
||||||
@@ -332,7 +369,7 @@ OAISERVER_ID_PREFIX = "repository.tugraz.at"
|
|||||||
"""The prefix that will be applied to the generated OAI-PMH ids."""
|
"""The prefix that will be applied to the generated OAI-PMH ids."""
|
||||||
|
|
||||||
OAISERVER_ADMIN_EMAILS = [
|
OAISERVER_ADMIN_EMAILS = [
|
||||||
'oai@repository.tugraz.at',
|
"oai@repository.tugraz.at",
|
||||||
]
|
]
|
||||||
"""The e-mail addresses of administrators of the repository.
|
"""The e-mail addresses of administrators of the repository.
|
||||||
|
|
||||||
14
invenio_config_iform/custom_fields/__init__.py
Normal file
14
invenio_config_iform/custom_fields/__init__.py
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2024 Graz University of Technology.
|
||||||
|
#
|
||||||
|
# invenio-config-iform is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
|
# details.
|
||||||
|
|
||||||
|
"""Custom fields."""
|
||||||
|
|
||||||
|
from invenio_records_resources.services.custom_fields import BooleanCF
|
||||||
|
|
||||||
|
ip_network = BooleanCF(name="ip_network")
|
||||||
|
single_ip = BooleanCF(name="single_ip")
|
||||||
61
invenio_config_iform/ext.py
Normal file
61
invenio_config_iform/ext.py
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2020-2024 Graz University of Technology.
|
||||||
|
#
|
||||||
|
# invenio-config-iform is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
|
# details.
|
||||||
|
|
||||||
|
"""invenio module that adds I-Form configs."""
|
||||||
|
|
||||||
|
from flask import Flask
|
||||||
|
|
||||||
|
from . import config
|
||||||
|
from .custom_fields import ip_network, single_ip
|
||||||
|
|
||||||
|
|
||||||
|
class InvenioConfigIform:
|
||||||
|
"""invenio-config-iform extension."""
|
||||||
|
|
||||||
|
def __init__(self, app: Flask = None) -> None:
|
||||||
|
"""Extension initialization."""
|
||||||
|
if app:
|
||||||
|
self.init_app(app)
|
||||||
|
|
||||||
|
def init_app(self, app: Flask) -> None:
|
||||||
|
"""Flask application initialization."""
|
||||||
|
self.init_config(app)
|
||||||
|
self.add_custom_fields(app)
|
||||||
|
app.extensions["invenio-config-iform"] = self
|
||||||
|
|
||||||
|
def init_config(self, app: Flask) -> None:
|
||||||
|
"""Initialize configuration."""
|
||||||
|
for k in dir(config):
|
||||||
|
if k.startswith("INVENIO_CONFIG_IFORM_"):
|
||||||
|
app.config.setdefault(k, getattr(config, k))
|
||||||
|
|
||||||
|
def add_custom_fields(self, app: Flask) -> None:
|
||||||
|
"""Add custom fields."""
|
||||||
|
app.config.setdefault("RDM_CUSTOM_FIELDS", [])
|
||||||
|
app.config["RDM_CUSTOM_FIELDS"].append(ip_network)
|
||||||
|
app.config["RDM_CUSTOM_FIELDS"].append(single_ip)
|
||||||
|
|
||||||
|
|
||||||
|
def finalize_app(app: Flask) -> None:
|
||||||
|
"""Finalize app."""
|
||||||
|
rank_blueprint_higher(app)
|
||||||
|
|
||||||
|
|
||||||
|
def rank_blueprint_higher(app: Flask) -> None:
|
||||||
|
"""Rank this module's blueprint higher than blueprint of security module.
|
||||||
|
|
||||||
|
Needed in order to overwrite email templates.
|
||||||
|
|
||||||
|
Since the blueprints are in a dict and the order of insertion is
|
||||||
|
retained, popping and reinserting all items (except ours), ensures
|
||||||
|
our blueprint will be in front.
|
||||||
|
"""
|
||||||
|
bps = app.blueprints
|
||||||
|
for blueprint_name in list(bps.keys()):
|
||||||
|
if blueprint_name != "invenio_config_iform":
|
||||||
|
bps.update({blueprint_name: bps.pop(blueprint_name)})
|
||||||
13
invenio_config_iform/permissions/__init__.py
Normal file
13
invenio_config_iform/permissions/__init__.py
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2024 Graz University of Technology.
|
||||||
|
#
|
||||||
|
# invenio-config-iform is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
|
# details.
|
||||||
|
|
||||||
|
"""Permission-policies and roles, based on `flask-principal`."""
|
||||||
|
|
||||||
|
from .policies import IformRDMRecordPermissionPolicy
|
||||||
|
|
||||||
|
__all__ = ("IformRDMRecordPermissionPolicy",)
|
||||||
195
invenio_config_iform/permissions/generators.py
Normal file
195
invenio_config_iform/permissions/generators.py
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2020-2024 Graz University of Technology.
|
||||||
|
#
|
||||||
|
# invenio-config-iform is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
|
# details.
|
||||||
|
|
||||||
|
r"""Permission generators for permission policies.
|
||||||
|
|
||||||
|
invenio's permissions build on
|
||||||
|
`flask-principal <https://pythonhosted.org/Flask-Principal>`_ .
|
||||||
|
|
||||||
|
In `flask-principal`, an action's `Need`s are checked
|
||||||
|
against current user's `Need`s to determine permissions.
|
||||||
|
|
||||||
|
For example, the action of deleting a record is only
|
||||||
|
permitted to users with `Need(method='role', value='admin')`.
|
||||||
|
|
||||||
|
Not all `Need`s can be known before the app is running.
|
||||||
|
For example, permissions for reading a record depend on whether
|
||||||
|
the record is public/private, so the set of `Need`s necessary
|
||||||
|
for reading a record must be computed dynamically at runtime.
|
||||||
|
This is the use case for
|
||||||
|
invenio's :py:class:`~invenio_records_permissions.generators.Generator`:
|
||||||
|
it generates `Need`s necessary for an action at runtime.
|
||||||
|
|
||||||
|
A `Generator` object defines 3 methods in addition to its constructor:
|
||||||
|
|
||||||
|
- ``needs(self, **kwargs)``: returns `Need`s, one of which a provider is
|
||||||
|
required to have to be allowed
|
||||||
|
- ``excludes(self, **kwargs)``: returns a list of `Need`s disallowing any
|
||||||
|
provider of a single one
|
||||||
|
- ``query_filter(self, **kwargs)``: returns a query filter to enable retrieval
|
||||||
|
of records
|
||||||
|
|
||||||
|
The ``needs`` and ``excludes`` methods specify access conditions from
|
||||||
|
the point-of-view of the object-of-concern; whereas, the ``query_filter``
|
||||||
|
method specifies those from the actor's point-of-view in search scenarios.
|
||||||
|
|
||||||
|
.. Note::
|
||||||
|
|
||||||
|
Exclusion has priority over inclusion. If a `Need` is returned by both
|
||||||
|
``needs`` and ``excludes``, providers of that `Need` will be **excluded**.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from ipaddress import ip_address, ip_network
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from flask import current_app, request
|
||||||
|
from flask_principal import Need
|
||||||
|
from invenio_access.permissions import any_user
|
||||||
|
from invenio_records_permissions.generators import Generator
|
||||||
|
from invenio_search.engine import dsl
|
||||||
|
|
||||||
|
from .roles import iform_authenticated_user
|
||||||
|
|
||||||
|
|
||||||
|
class RecordSingleIP(Generator):
|
||||||
|
"""Allowed any user with accessing with the IP."""
|
||||||
|
|
||||||
|
def needs(self, record: dict | None = None, **__: dict) -> list[Need]:
|
||||||
|
"""Set of Needs granting permission. Enabling Needs."""
|
||||||
|
if record is None:
|
||||||
|
return []
|
||||||
|
|
||||||
|
# if record has singleip, and the ip of the user matches the allowed ip
|
||||||
|
if record.get("custom_fields", {}).get("single_ip", False) and self.check_permission():
|
||||||
|
return [any_user]
|
||||||
|
|
||||||
|
# non of the above - return empty
|
||||||
|
return []
|
||||||
|
|
||||||
|
def excludes(self, **kwargs: dict) -> list[Need]:
|
||||||
|
"""Set of Needs denying permission. Preventing Needs.
|
||||||
|
|
||||||
|
If ANY of the Needs are matched, permission is revoked.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
``_load_permissions()`` method from `Permission
|
||||||
|
<https://invenio-access.readthedocs.io/en/latest/api.html
|
||||||
|
#invenio_access.permissions.Permission>`_ adds by default the
|
||||||
|
``superuser_access`` Need (if tied to a User or Role) for us.
|
||||||
|
|
||||||
|
It also expands ActionNeeds into the Users/Roles that
|
||||||
|
provide them.
|
||||||
|
|
||||||
|
If the same Need is returned by `needs` and `excludes`, then that
|
||||||
|
Need provider is disallowed.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if kwargs["record"]["custom_fields"]["single_ip"] and not self.check_permission():
|
||||||
|
return [any_user]
|
||||||
|
|
||||||
|
except KeyError:
|
||||||
|
return []
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
|
def query_filter(self, *_: dict, **__: dict) -> Any: # noqa: ANN401
|
||||||
|
"""Filter for singleip records."""
|
||||||
|
if not self.check_permission():
|
||||||
|
# If user ip is not on the list, and If the record contains 'singleip' will not be seen
|
||||||
|
return ~dsl.Q("match", **{"custom_fields.single_ip": True})
|
||||||
|
|
||||||
|
# Lists all records
|
||||||
|
return dsl.Q("match_all")
|
||||||
|
|
||||||
|
def check_permission(self) -> bool:
|
||||||
|
"""Check for User IP address in config variable.
|
||||||
|
|
||||||
|
If the user ip is in the configured list return True.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
user_ip = request.remote_addr
|
||||||
|
except RuntimeError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
single_ips = current_app.config["CONFIG_IFORM_SINGLE_IPS"]
|
||||||
|
|
||||||
|
return user_ip in single_ips
|
||||||
|
|
||||||
|
|
||||||
|
class AllowedFromIPNetwork(Generator):
|
||||||
|
"""Allowed from ip range."""
|
||||||
|
|
||||||
|
def needs(self, record: dict | None = None, **__: dict) -> list[Need]:
|
||||||
|
"""Set of Needs granting permission. Enabling Needs."""
|
||||||
|
if record is None:
|
||||||
|
return []
|
||||||
|
|
||||||
|
# if the record has set the ip_range allowance and is in the range
|
||||||
|
if record.get("custom_fields", {}).get("ip_network", False) and self.check_permission():
|
||||||
|
return [any_user]
|
||||||
|
|
||||||
|
# non of the above - return empty
|
||||||
|
return []
|
||||||
|
|
||||||
|
def excludes(self, **kwargs: dict) -> Need:
|
||||||
|
"""Set of Needs denying permission. Preventing Needs.
|
||||||
|
|
||||||
|
If ANY of the Needs are matched, permission is revoked.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
``_load_permissions()`` method from `Permission
|
||||||
|
<https://invenio-access.readthedocs.io/en/latest/api.html
|
||||||
|
#invenio_access.permissions.Permission>`_ adds by default the
|
||||||
|
``superuser_access`` Need (if tied to a User or Role) for us.
|
||||||
|
|
||||||
|
It also expands ActionNeeds into the Users/Roles that
|
||||||
|
provide them.
|
||||||
|
|
||||||
|
If the same Need is returned by `needs` and `excludes`, then that
|
||||||
|
Need provider is disallowed.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
if kwargs["record"]["custom_fields"]["ip_network"] and not self.check_permission():
|
||||||
|
return [any_user]
|
||||||
|
|
||||||
|
except KeyError:
|
||||||
|
return []
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
|
def query_filter(self, *_: dict, **__: dict) -> Any: # noqa: ANN401
|
||||||
|
"""Filter for ip range records."""
|
||||||
|
if not self.check_permission():
|
||||||
|
return ~dsl.Q("match", **{"custom_fields.ip_network": True})
|
||||||
|
|
||||||
|
return dsl.Q("match_all")
|
||||||
|
|
||||||
|
def check_permission(self) -> bool:
|
||||||
|
"""Check for User IP address in the configured network."""
|
||||||
|
try:
|
||||||
|
user_ip = request.remote_addr
|
||||||
|
except RuntimeError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
network = current_app.config["CONFIG_IFORM_IP_NETWORK"]
|
||||||
|
|
||||||
|
try:
|
||||||
|
return ip_address(user_ip) in ip_network(network)
|
||||||
|
except ValueError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class IformAuthenticatedUser(Generator):
|
||||||
|
"""Generates the `iform_authenticated_user` role-need."""
|
||||||
|
|
||||||
|
def needs(self, **__: dict) -> list[Need]:
|
||||||
|
"""Generate needs to be checked against current user identity."""
|
||||||
|
return [iform_authenticated_user]
|
||||||
276
invenio_config_iform/permissions/policies.py
Normal file
276
invenio_config_iform/permissions/policies.py
Normal file
@@ -0,0 +1,276 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2020-2024 Graz University of Technology.
|
||||||
|
# Copyright (C) 2025 I-Form Advanced Manufacturing Research Centre.
|
||||||
|
#
|
||||||
|
# invenio-config-iform is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
|
# details.
|
||||||
|
|
||||||
|
"""I-Form permission-policy for RDMRecordService.
|
||||||
|
|
||||||
|
To use, set config-variable `RDM_PERMISSION_POLICY` to `IformRDMRecordPermissionPolicy`.
|
||||||
|
|
||||||
|
Policies list **what actions** can be done **by whom**
|
||||||
|
over an implied category of objects (typically records). A Policy is
|
||||||
|
instantiated on a per action basis and is a descendant of `Permission
|
||||||
|
<https://invenio-access.readthedocs.io/en/latest/api.html
|
||||||
|
#invenio_access.permissions.Permission>`_ in
|
||||||
|
`invenio-access <https://invenio-access.readthedocs.io>`_ .
|
||||||
|
Generators are used to provide the "by whom" part and the implied category of
|
||||||
|
object.
|
||||||
|
|
||||||
|
Actions are class variables of the form: ``can_<action>`` and the
|
||||||
|
corresponding (dis-)allowed identities are a list of Generator instances.
|
||||||
|
One can define any action as long as it follows that pattern and
|
||||||
|
is verified at the moment it is undertaken.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from invenio_administration.generators import Administration
|
||||||
|
from invenio_communities.generators import CommunityCurators
|
||||||
|
from invenio_rdm_records.services.generators import (
|
||||||
|
AccessGrant,
|
||||||
|
CommunityInclusionReviewers,
|
||||||
|
IfAtLeastOneCommunity,
|
||||||
|
IfDeleted,
|
||||||
|
IfExternalDOIRecord,
|
||||||
|
IfFileIsLocal,
|
||||||
|
IfNewRecord,
|
||||||
|
IfOneCommunity,
|
||||||
|
IfRecordDeleted,
|
||||||
|
IfRestricted,
|
||||||
|
RecordCommunitiesAction,
|
||||||
|
RecordOwners,
|
||||||
|
ResourceAccessToken,
|
||||||
|
SecretLinks,
|
||||||
|
SubmissionReviewer,
|
||||||
|
)
|
||||||
|
from invenio_records_permissions.generators import AnyUser, Disable, IfConfig, SystemProcess
|
||||||
|
from invenio_records_permissions.policies.records import RecordPermissionPolicy
|
||||||
|
from invenio_users_resources.services.permissions import UserManager
|
||||||
|
|
||||||
|
from .generators import AllowedFromIPNetwork, IformAuthenticatedUser, RecordSingleIP
|
||||||
|
|
||||||
|
|
||||||
|
class IformRDMRecordPermissionPolicy(RecordPermissionPolicy):
|
||||||
|
"""Overwrite authenticatedness to mean `iform_authenticated` rather than *signed up*."""
|
||||||
|
|
||||||
|
NEED_LABEL_TO_ACTION = {
|
||||||
|
"bucket-update": "update_files",
|
||||||
|
"bucket-read": "read_files",
|
||||||
|
"object-read": "read_files",
|
||||||
|
}
|
||||||
|
|
||||||
|
#
|
||||||
|
# General permission-groups, to be used below
|
||||||
|
#
|
||||||
|
can_manage = [
|
||||||
|
RecordOwners(),
|
||||||
|
RecordCommunitiesAction("curate"),
|
||||||
|
AccessGrant("manage"),
|
||||||
|
SystemProcess(),
|
||||||
|
]
|
||||||
|
can_manage_internal = [SystemProcess()]
|
||||||
|
can_curate = can_manage + [AccessGrant("edit"), SecretLinks("edit")]
|
||||||
|
can_review = can_curate + [SubmissionReviewer()]
|
||||||
|
can_preview = can_curate + [
|
||||||
|
AccessGrant("preview"),
|
||||||
|
SecretLinks("preview"),
|
||||||
|
SubmissionReviewer(),
|
||||||
|
UserManager,
|
||||||
|
]
|
||||||
|
can_view = can_preview + [
|
||||||
|
AccessGrant("view"),
|
||||||
|
SecretLinks("view"),
|
||||||
|
SubmissionReviewer(),
|
||||||
|
CommunityInclusionReviewers(),
|
||||||
|
RecordCommunitiesAction("view"),
|
||||||
|
AllowedFromIPNetwork(),
|
||||||
|
RecordSingleIP(),
|
||||||
|
]
|
||||||
|
|
||||||
|
can_iform_authenticated = [IformAuthenticatedUser(), SystemProcess()]
|
||||||
|
can_authenticated = can_iform_authenticated
|
||||||
|
can_all = [
|
||||||
|
AnyUser(),
|
||||||
|
SystemProcess(),
|
||||||
|
AllowedFromIPNetwork(),
|
||||||
|
RecordSingleIP(),
|
||||||
|
]
|
||||||
|
|
||||||
|
#
|
||||||
|
# Miscellaneous
|
||||||
|
#
|
||||||
|
# Allow for querying of statistics
|
||||||
|
# - This is currently disabled because it's not needed and could potentially
|
||||||
|
# open up surface for denial of service attacks
|
||||||
|
can_query_stats = [Disable()]
|
||||||
|
|
||||||
|
#
|
||||||
|
# Records - reading and creating
|
||||||
|
#
|
||||||
|
can_search = can_all
|
||||||
|
can_search_revisions = [Administration()]
|
||||||
|
can_read = [IfRestricted("record", then_=can_view, else_=can_all)]
|
||||||
|
|
||||||
|
can_read_deleted = [
|
||||||
|
IfRecordDeleted(then_=[UserManager, SystemProcess()], else_=can_read),
|
||||||
|
]
|
||||||
|
can_read_deleted_files = can_read_deleted
|
||||||
|
can_media_read_deleted_files = can_read_deleted_files
|
||||||
|
can_read_files = [
|
||||||
|
IfRestricted("files", then_=can_view, else_=can_all),
|
||||||
|
ResourceAccessToken("read"),
|
||||||
|
]
|
||||||
|
can_get_content_files = [
|
||||||
|
IfFileIsLocal(then_=can_read_files, else_=[SystemProcess()]),
|
||||||
|
]
|
||||||
|
can_create = can_iform_authenticated
|
||||||
|
|
||||||
|
#
|
||||||
|
# Drafts
|
||||||
|
#
|
||||||
|
can_search_drafts = can_iform_authenticated
|
||||||
|
can_read_draft = can_preview
|
||||||
|
can_draft_read_files = can_preview + [ResourceAccessToken("read")]
|
||||||
|
can_update_draft = can_review
|
||||||
|
can_draft_create_files = can_review
|
||||||
|
can_draft_set_content_files = [
|
||||||
|
IfFileIsLocal(then_=can_review, else_=[SystemProcess()]),
|
||||||
|
]
|
||||||
|
can_draft_get_content_files = [
|
||||||
|
IfFileIsLocal(then_=can_draft_read_files, else_=[SystemProcess()]),
|
||||||
|
]
|
||||||
|
can_draft_commit_files = [IfFileIsLocal(then_=can_review, else_=[SystemProcess()])]
|
||||||
|
can_draft_update_files = can_review
|
||||||
|
can_draft_delete_files = can_review
|
||||||
|
can_manage_files = [
|
||||||
|
IfConfig(
|
||||||
|
"RDM_ALLOW_METADATA_ONLY_RECORDS",
|
||||||
|
then_=[IfNewRecord(then_=can_iform_authenticated, else_=can_review)],
|
||||||
|
else_=[],
|
||||||
|
),
|
||||||
|
]
|
||||||
|
can_manage_record_access = [
|
||||||
|
IfConfig(
|
||||||
|
"RDM_ALLOW_RESTRICTED_RECORDS",
|
||||||
|
then_=[IfNewRecord(then_=can_iform_authenticated, else_=can_review)],
|
||||||
|
else_=[],
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
#
|
||||||
|
# PIDs
|
||||||
|
#
|
||||||
|
can_pid_create = can_review
|
||||||
|
can_pid_register = can_review
|
||||||
|
can_pid_update = can_review
|
||||||
|
can_pid_discard = can_review
|
||||||
|
can_pid_delete = can_review
|
||||||
|
can_pid_manage = [SystemProcess()]
|
||||||
|
|
||||||
|
#
|
||||||
|
# Actions
|
||||||
|
#
|
||||||
|
can_edit = [IfDeleted(then_=[Disable()], else_=can_curate)]
|
||||||
|
can_delete_draft = can_curate
|
||||||
|
can_new_version = [
|
||||||
|
IfConfig(
|
||||||
|
"RDM_ALLOW_EXTERNAL_DOI_VERSIONING",
|
||||||
|
then_=can_curate,
|
||||||
|
else_=[IfExternalDOIRecord(then_=[Disable()], else_=can_curate)],
|
||||||
|
),
|
||||||
|
]
|
||||||
|
can_publish = [
|
||||||
|
IfConfig(
|
||||||
|
"RDM_COMMUNITY_REQUIRED_TO_PUBLISH",
|
||||||
|
then_=[
|
||||||
|
IfAtLeastOneCommunity(
|
||||||
|
then_=can_review,
|
||||||
|
else_=[Administration(), SystemProcess()],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
else_=can_review,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
can_lift_embargo = can_manage
|
||||||
|
|
||||||
|
#
|
||||||
|
# Record communities
|
||||||
|
#
|
||||||
|
can_add_community = can_manage
|
||||||
|
can_remove_community_ = [RecordOwners(), CommunityCurators(), SystemProcess()]
|
||||||
|
can_remove_community = [
|
||||||
|
IfConfig(
|
||||||
|
"RDM_COMMUNITY_REQUIRED_TO_PUBLISH",
|
||||||
|
then_=[
|
||||||
|
IfOneCommunity(
|
||||||
|
then_=[Administration(), SystemProcess()],
|
||||||
|
else_=can_remove_community_,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
else_=can_remove_community_,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
can_remove_record = [CommunityCurators(), Administration(), SystemProcess()]
|
||||||
|
can_bulk_add = [SystemProcess()]
|
||||||
|
|
||||||
|
#
|
||||||
|
# Media files - draft
|
||||||
|
#
|
||||||
|
can_draft_media_create_files = can_review
|
||||||
|
can_draft_media_read_files = can_review
|
||||||
|
can_draft_media_set_content_files = [
|
||||||
|
IfFileIsLocal(then_=can_review, else_=[SystemProcess()]),
|
||||||
|
]
|
||||||
|
can_draft_media_get_content_files = [
|
||||||
|
IfFileIsLocal(then_=can_preview, else_=[SystemProcess()]),
|
||||||
|
]
|
||||||
|
can_draft_media_commit_files = [
|
||||||
|
IfFileIsLocal(then_=can_preview, else_=[SystemProcess()]),
|
||||||
|
]
|
||||||
|
can_draft_media_delete_files = can_review
|
||||||
|
can_draft_media_update_files = can_review
|
||||||
|
|
||||||
|
#
|
||||||
|
# Media files - record
|
||||||
|
#
|
||||||
|
can_media_read_files = [
|
||||||
|
IfRestricted("record", then_=can_view, else_=can_all),
|
||||||
|
ResourceAccessToken("read"),
|
||||||
|
]
|
||||||
|
can_media_get_content_files = [
|
||||||
|
IfFileIsLocal(then_=can_read, else_=[SystemProcess()]),
|
||||||
|
]
|
||||||
|
can_media_create_files = [Disable()]
|
||||||
|
can_media_set_content_files = [Disable()]
|
||||||
|
can_media_commit_files = [Disable()]
|
||||||
|
can_media_update_files = [Disable()]
|
||||||
|
can_media_delete_files = [Disable()]
|
||||||
|
|
||||||
|
#
|
||||||
|
# Record deletetion
|
||||||
|
#
|
||||||
|
can_delete = [Administration(), SystemProcess()]
|
||||||
|
can_delete_files = [SystemProcess()]
|
||||||
|
can_purge = [SystemProcess()]
|
||||||
|
|
||||||
|
#
|
||||||
|
# Quotas for records/users
|
||||||
|
#
|
||||||
|
can_manage_quota = [UserManager, SystemProcess()]
|
||||||
|
|
||||||
|
#
|
||||||
|
# Disabled
|
||||||
|
#
|
||||||
|
# - Records/files are updated/deleted via drafts so we don't support
|
||||||
|
# using below actions.
|
||||||
|
can_update = [Disable()]
|
||||||
|
can_create_files = [Disable()]
|
||||||
|
can_set_content_files = [Disable()]
|
||||||
|
can_commit_files = [Disable()]
|
||||||
|
can_update_files = [Disable()]
|
||||||
|
|
||||||
|
# Used to hide at the moment the `parent.is_verified` field. It should be set to
|
||||||
|
# correct permissions based on which the field will be exposed only to moderators
|
||||||
|
can_moderate = [SystemProcess()]
|
||||||
21
invenio_config_iform/permissions/roles.py
Normal file
21
invenio_config_iform/permissions/roles.py
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2024 Graz University of Technology.
|
||||||
|
#
|
||||||
|
# invenio-config-iform is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
|
# details.
|
||||||
|
|
||||||
|
"""`RoleNeed`s for permission policies.
|
||||||
|
|
||||||
|
To use these roles, add them to the database via:
|
||||||
|
`$ invenio roles create iform_authenticated --description "..."`
|
||||||
|
then add roles to users via:
|
||||||
|
`$ invenio roles add user@email.com iform_authenticated`
|
||||||
|
"""
|
||||||
|
|
||||||
|
from flask_principal import RoleNeed
|
||||||
|
|
||||||
|
# using `flask_principal.RoleNeed`` instead of `invenio_access.SystemRoleNeed`,
|
||||||
|
# because these roles are assigned by an admin rather than automatically by the system
|
||||||
|
iform_authenticated_user = RoleNeed("iform_authenticated")
|
||||||
Binary file not shown.
Binary file not shown.
@@ -4,10 +4,10 @@
|
|||||||
|
|
||||||
{{ _('To help you get started, here are some useful links:') }}
|
{{ _('To help you get started, here are some useful links:') }}
|
||||||
|
|
||||||
- {{ _('Guidelines:')}} {{ _('Repository Guide')}} ({{ _('how to upload files')}}) (https://{{ config.SITE_HOSTNAME }}{{ url_for('invenio_config_tugraz.guide') }})
|
- {{ _('Guidelines:')}} {{ _('Repository Guide')}} ({{ _('how to upload files')}}) ({{ config.SITE_UI_URL }}{{ url_for('invenio_config_iform.guide') }})
|
||||||
- {{ _('Search Guide')}} (https://{{ config.SITE_HOSTNAME }}{{url_for('invenio_app_rdm.help_search')}})
|
- {{ _('Search Guide')}} ({{ config.SITE_UI_URL }}{{url_for('invenio_app_rdm.help_search')}})
|
||||||
- {{ _('Terms And Conditions') }} (https://{{ config.SITE_HOSTNAME }}{{ url_for('invenio_config_tugraz.terms') }})
|
- {{ _('Terms And Conditions') }} ({{ config.SITE_UI_URL }}{{ url_for('invenio_config_iform.terms') }})
|
||||||
- {{ _('Data Protection Rights')}} (https://{{ config.SITE_HOSTNAME }}{{ url_for('invenio_config_tugraz.gdpr') }})
|
- {{ _('Data Protection Rights')}} ({{ config.SITE_UI_URL }}{{ url_for('invenio_config_iform.gdpr') }})
|
||||||
{% if security.confirmable %}
|
{% if security.confirmable %}
|
||||||
{{ _('You can confirm your email through the link below:') }}
|
{{ _('You can confirm your email through the link below:') }}
|
||||||
{{ confirmation_link }}">
|
{{ confirmation_link }}">
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
# German translations for invenio-config-tugraz.
|
# German translations for invenio-config-iform.
|
||||||
# Copyright (C) 2021 Graz University of Technology
|
# Copyright (C) 2021 Graz University of Technology
|
||||||
# This file is distributed under the same license as the
|
# This file is distributed under the same license as the
|
||||||
# invenio-config-tugraz project.
|
# invenio-config-iform project.
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2021.
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2021.
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: invenio-config-tugraz 0.5.5\n"
|
"Project-Id-Version: invenio-config-iform 0.5.5\n"
|
||||||
"Report-Msgid-Bugs-To: mojib.wali@tugraz.at\n"
|
"Report-Msgid-Bugs-To: mojib.wali@tugraz.at\n"
|
||||||
"POT-Creation-Date: 2021-04-27 15:30+0200\n"
|
"POT-Creation-Date: 2021-04-27 15:30+0200\n"
|
||||||
"PO-Revision-Date: 2021-04-22 11:57+0200\n"
|
"PO-Revision-Date: 2021-04-22 11:57+0200\n"
|
||||||
@@ -19,53 +19,53 @@ msgstr ""
|
|||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Generated-By: Babel 2.9.0\n"
|
"Generated-By: Babel 2.9.0\n"
|
||||||
|
|
||||||
#: invenio_config_tugraz/config.py:87
|
#: invenio_config_iform/config.py:87
|
||||||
msgid "Welcome to TU Graz Repository!"
|
msgid "Welcome to TU Graz Repository!"
|
||||||
msgstr "Willkommen im TU Graz Repository!"
|
msgstr "Willkommen im TU Graz Repository!"
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:1
|
#: invenio_config_iform/templates/security/email/welcome.txt:1
|
||||||
msgid "Dear user,"
|
msgid "Dear user,"
|
||||||
msgstr "Lieber Nutzer,"
|
msgstr "Lieber Nutzer,"
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:3
|
#: invenio_config_iform/templates/security/email/welcome.txt:3
|
||||||
msgid "Welcome to the Repository of TU Graz!"
|
msgid "Welcome to the Repository of TU Graz!"
|
||||||
msgstr "Willkommen im TU Graz Repository!"
|
msgstr "Willkommen im TU Graz Repository!"
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:5
|
#: invenio_config_iform/templates/security/email/welcome.txt:5
|
||||||
msgid "To help you get started, here are some useful links:"
|
msgid "To help you get started, here are some useful links:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Um Ihnen den Einstieg zu erleichtern, finden Sie hier einige nützliche "
|
"Um Ihnen den Einstieg zu erleichtern, finden Sie hier einige nützliche "
|
||||||
"Links:"
|
"Links:"
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:7
|
#: invenio_config_iform/templates/security/email/welcome.txt:7
|
||||||
msgid "Guidelines:"
|
msgid "Guidelines:"
|
||||||
msgstr "Leitfaden:"
|
msgstr "Leitfaden:"
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:7
|
#: invenio_config_iform/templates/security/email/welcome.txt:7
|
||||||
msgid "Repository Guide"
|
msgid "Repository Guide"
|
||||||
msgstr "Handbuch"
|
msgstr "Handbuch"
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:7
|
#: invenio_config_iform/templates/security/email/welcome.txt:7
|
||||||
msgid "how to upload files"
|
msgid "how to upload files"
|
||||||
msgstr "wie man Dateien hochlädt"
|
msgstr "wie man Dateien hochlädt"
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:8
|
#: invenio_config_iform/templates/security/email/welcome.txt:8
|
||||||
msgid "Search Guide"
|
msgid "Search Guide"
|
||||||
msgstr "Suchanleitung"
|
msgstr "Suchanleitung"
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:9
|
#: invenio_config_iform/templates/security/email/welcome.txt:9
|
||||||
msgid "Terms And Conditions"
|
msgid "Terms And Conditions"
|
||||||
msgstr "Nutzungsbedingungen"
|
msgstr "Nutzungsbedingungen"
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:10
|
#: invenio_config_iform/templates/security/email/welcome.txt:10
|
||||||
msgid "Data Protection Rights"
|
msgid "Data Protection Rights"
|
||||||
msgstr "Datenschutzerklärung"
|
msgstr "Datenschutzerklärung"
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:13
|
#: invenio_config_iform/templates/security/email/welcome.txt:13
|
||||||
msgid "You can confirm your email through the link below:"
|
msgid "You can confirm your email through the link below:"
|
||||||
msgstr "Sie können Ihre E-Mail über den folgenden Link bestätigen:"
|
msgstr "Sie können Ihre E-Mail über den folgenden Link bestätigen:"
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:16
|
#: invenio_config_iform/templates/security/email/welcome.txt:16
|
||||||
msgid ""
|
msgid ""
|
||||||
"If you require any assistance please do not hesitate to contact us at "
|
"If you require any assistance please do not hesitate to contact us at "
|
||||||
"repository-support@tugraz.at."
|
"repository-support@tugraz.at."
|
||||||
@@ -73,11 +73,10 @@ msgstr ""
|
|||||||
"Wenn Sie Hilfe benötigen, zögern Sie bitte nicht, uns unter repository-"
|
"Wenn Sie Hilfe benötigen, zögern Sie bitte nicht, uns unter repository-"
|
||||||
"support@tugraz.at zu kontaktieren."
|
"support@tugraz.at zu kontaktieren."
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:18
|
#: invenio_config_iform/templates/security/email/welcome.txt:18
|
||||||
msgid "Best regards,"
|
msgid "Best regards,"
|
||||||
msgstr "Mit freundlichen Grüßen,"
|
msgstr "Mit freundlichen Grüßen,"
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:19
|
#: invenio_config_iform/templates/security/email/welcome.txt:19
|
||||||
msgid "TU Graz Repository Team"
|
msgid "TU Graz Repository Team"
|
||||||
msgstr "TU Graz Repository Team"
|
msgstr "TU Graz Repository Team"
|
||||||
|
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
# Translations template for invenio-config-tugraz.
|
# Translations template for invenio-config-iform.
|
||||||
# Copyright (C) 2021 Graz University of Technology
|
# Copyright (C) 2021 Graz University of Technology
|
||||||
# This file is distributed under the same license as the
|
# This file is distributed under the same license as the
|
||||||
# invenio-config-tugraz project.
|
# invenio-config-iform project.
|
||||||
# FIRST AUTHOR <EMAIL@ADDRESS>, 2021.
|
# FIRST AUTHOR <EMAIL@ADDRESS>, 2021.
|
||||||
#
|
#
|
||||||
#, fuzzy
|
#, fuzzy
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: invenio-config-tugraz 0.5.5\n"
|
"Project-Id-Version: invenio-config-iform 0.5.5\n"
|
||||||
"Report-Msgid-Bugs-To: mojib.wali@tugraz.at\n"
|
"Report-Msgid-Bugs-To: mojib.wali@tugraz.at\n"
|
||||||
"POT-Creation-Date: 2021-04-27 15:30+0200\n"
|
"POT-Creation-Date: 2021-04-27 15:30+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
@@ -18,61 +18,60 @@ msgstr ""
|
|||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Generated-By: Babel 2.9.0\n"
|
"Generated-By: Babel 2.9.0\n"
|
||||||
|
|
||||||
#: invenio_config_tugraz/config.py:87
|
#: invenio_config_iform/config.py:87
|
||||||
msgid "Welcome to TU Graz Repository!"
|
msgid "Welcome to TU Graz Repository!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:1
|
#: invenio_config_iform/templates/security/email/welcome.txt:1
|
||||||
msgid "Dear user,"
|
msgid "Dear user,"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:3
|
#: invenio_config_iform/templates/security/email/welcome.txt:3
|
||||||
msgid "Welcome to the Repository of TU Graz!"
|
msgid "Welcome to the Repository of TU Graz!"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:5
|
#: invenio_config_iform/templates/security/email/welcome.txt:5
|
||||||
msgid "To help you get started, here are some useful links:"
|
msgid "To help you get started, here are some useful links:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:7
|
#: invenio_config_iform/templates/security/email/welcome.txt:7
|
||||||
msgid "Guidelines:"
|
msgid "Guidelines:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:7
|
#: invenio_config_iform/templates/security/email/welcome.txt:7
|
||||||
msgid "Repository Guide"
|
msgid "Repository Guide"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:7
|
#: invenio_config_iform/templates/security/email/welcome.txt:7
|
||||||
msgid "how to upload files"
|
msgid "how to upload files"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:8
|
#: invenio_config_iform/templates/security/email/welcome.txt:8
|
||||||
msgid "Search Guide"
|
msgid "Search Guide"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:9
|
#: invenio_config_iform/templates/security/email/welcome.txt:9
|
||||||
msgid "Terms And Conditions"
|
msgid "Terms And Conditions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:10
|
#: invenio_config_iform/templates/security/email/welcome.txt:10
|
||||||
msgid "Data Protection Rights"
|
msgid "Data Protection Rights"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:13
|
#: invenio_config_iform/templates/security/email/welcome.txt:13
|
||||||
msgid "You can confirm your email through the link below:"
|
msgid "You can confirm your email through the link below:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:16
|
#: invenio_config_iform/templates/security/email/welcome.txt:16
|
||||||
msgid ""
|
msgid ""
|
||||||
"If you require any assistance please do not hesitate to contact us at "
|
"If you require any assistance please do not hesitate to contact us at "
|
||||||
"repository-support@tugraz.at."
|
"repository-support@tugraz.at."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:18
|
#: invenio_config_iform/templates/security/email/welcome.txt:18
|
||||||
msgid "Best regards,"
|
msgid "Best regards,"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: invenio_config_tugraz/templates/security/email/welcome.txt:19
|
#: invenio_config_iform/templates/security/email/welcome.txt:19
|
||||||
msgid "TU Graz Repository Team"
|
msgid "TU Graz Repository Team"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
73
invenio_config_iform/utils.py
Normal file
73
invenio_config_iform/utils.py
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2022-2024 Graz University of Technology.
|
||||||
|
#
|
||||||
|
# invenio-config-iform is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
|
# details.
|
||||||
|
|
||||||
|
"""Utils file."""
|
||||||
|
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
from flask_principal import Identity
|
||||||
|
from invenio_access import any_user
|
||||||
|
from invenio_access.utils import get_identity
|
||||||
|
from invenio_accounts import current_accounts
|
||||||
|
|
||||||
|
|
||||||
|
def get_identity_from_user_by_email(email: str | None = None) -> Identity:
|
||||||
|
"""Get the user specified via email or ID."""
|
||||||
|
warnings.warn("deprecated", DeprecationWarning, stacklevel=2)
|
||||||
|
|
||||||
|
if email is None:
|
||||||
|
msg = "the email has to be set to get a identity"
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
user = current_accounts.datastore.get_user(email)
|
||||||
|
|
||||||
|
if user is None:
|
||||||
|
msg = f"user with {email} not found"
|
||||||
|
raise LookupError(msg)
|
||||||
|
|
||||||
|
identity = get_identity(user)
|
||||||
|
|
||||||
|
# TODO: this is a temporary solution. this should be done with data from the db
|
||||||
|
identity.provides.add(any_user)
|
||||||
|
|
||||||
|
return identity
|
||||||
|
|
||||||
|
|
||||||
|
def iform_account_setup_extension(user, account_info) -> None: # noqa: ANN001, ARG001
|
||||||
|
"""Add iform_authenticated role to user after SAML-login was acknowledged.
|
||||||
|
|
||||||
|
To use, have `acs_handler_factory` call invenio_saml's `default_account_setup` first,
|
||||||
|
then this function second.
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
# invenio.cfg
|
||||||
|
from invenio_saml.handlers import default_account_setup, acs_handler_factory
|
||||||
|
|
||||||
|
def iform_account_setup(user, account_info):
|
||||||
|
# links external `account_info` with our database's `user` for future logins
|
||||||
|
default_account_setup(user, account_info)
|
||||||
|
iform_account_setup_extension(user, account_info)
|
||||||
|
|
||||||
|
SSO_SAML_IDPS = {
|
||||||
|
"my-iform-idp": {
|
||||||
|
...
|
||||||
|
"acs_handler": acs_handler_factory(
|
||||||
|
"my-iform-idp", account_setup=iform_account_setup
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
For this to work, the role iform_authenticated must have been created
|
||||||
|
(e.g. via `invenio roles create iform_authenticated`).
|
||||||
|
"""
|
||||||
|
user_email = account_info["user"]["email"]
|
||||||
|
|
||||||
|
# NOTE: `datastore.commit`ing will be done by acs_handler that calls this func
|
||||||
|
# NOTE: this is a No-Op when user_email already has role iform_authenticated
|
||||||
|
current_accounts.datastore.add_role_to_user(user_email, "iform_authenticated")
|
||||||
67
invenio_config_iform/views.py
Normal file
67
invenio_config_iform/views.py
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2020-2024 Graz University of Technology.
|
||||||
|
#
|
||||||
|
# invenio-config-iform is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
|
# details.
|
||||||
|
|
||||||
|
"""Invenio module for I-Form config."""
|
||||||
|
|
||||||
|
from flask import Blueprint, Flask, redirect, url_for
|
||||||
|
from invenio_i18n import get_locale
|
||||||
|
from werkzeug.wrappers import Response as BaseResponse
|
||||||
|
|
||||||
|
|
||||||
|
def ui_blueprint(app: Flask) -> Blueprint:
|
||||||
|
"""Blueprint for the routes and resources provided by invenio-config-iform."""
|
||||||
|
routes = app.config.get("CONFIG_IFORM_ROUTES")
|
||||||
|
|
||||||
|
blueprint = Blueprint(
|
||||||
|
"invenio_config_iform",
|
||||||
|
__name__,
|
||||||
|
template_folder="templates",
|
||||||
|
static_folder="static",
|
||||||
|
)
|
||||||
|
|
||||||
|
blueprint.add_url_rule(routes["guide"], view_func=guide)
|
||||||
|
blueprint.add_url_rule(routes["terms"], view_func=terms)
|
||||||
|
blueprint.add_url_rule(routes["gdpr"], view_func=gdpr)
|
||||||
|
|
||||||
|
return blueprint
|
||||||
|
|
||||||
|
|
||||||
|
def guide() -> BaseResponse:
|
||||||
|
"""I-Form_Repository_Guide."""
|
||||||
|
locale = get_locale()
|
||||||
|
return redirect(
|
||||||
|
url_for(
|
||||||
|
"static",
|
||||||
|
filename=f"documents/I-Form_Repository_Guide_02.1_{locale}.pdf",
|
||||||
|
_external=True,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def terms() -> BaseResponse:
|
||||||
|
"""Terms_And_Conditions."""
|
||||||
|
locale = get_locale()
|
||||||
|
return redirect(
|
||||||
|
url_for(
|
||||||
|
"static",
|
||||||
|
filename=f"documents/I-Form_Repository_Terms_And_Conditions_{locale}.pdf",
|
||||||
|
_external=True,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def gdpr() -> BaseResponse:
|
||||||
|
"""General_Data_Protection_Rights."""
|
||||||
|
locale = get_locale()
|
||||||
|
return redirect(
|
||||||
|
url_for(
|
||||||
|
"static",
|
||||||
|
filename=f"documents/I-Form_Repository_General_Data_Protection_Rights_{locale}.pdf",
|
||||||
|
_external=True,
|
||||||
|
),
|
||||||
|
)
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Copyright (C) 2020 Mojib Wali.
|
|
||||||
#
|
|
||||||
# invenio-config-tugraz is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
||||||
# details.
|
|
||||||
|
|
||||||
"""invenio module that adds tugraz configs."""
|
|
||||||
|
|
||||||
from .ext import InvenioConfigTugraz
|
|
||||||
from .generators import RecordIp
|
|
||||||
from .version import __version__
|
|
||||||
|
|
||||||
__all__ = ("__version__", "InvenioConfigTugraz", "RecordIp")
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Copyright (C) 2020-2021 Graz University of Technology.
|
|
||||||
#
|
|
||||||
# invenio-config-tugraz is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
||||||
# details.
|
|
||||||
|
|
||||||
"""
|
|
||||||
Records permission policies.
|
|
||||||
|
|
||||||
Default policies for records:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
# Read access given to everyone.
|
|
||||||
can_search = [AnyUser()]
|
|
||||||
# Create action given to no one (Not even superusers) bc Deposits should
|
|
||||||
# be used.
|
|
||||||
can_create = [Disable()]
|
|
||||||
# Read access given to everyone if public record/files and owners always.
|
|
||||||
can_read = [AnyUserIfPublic(), RecordOwners()]
|
|
||||||
# Update access given to record owners.
|
|
||||||
can_update = [RecordOwners()]
|
|
||||||
# Delete access given to admins only.
|
|
||||||
can_delete = [Admin()]
|
|
||||||
# Associated files permissions (which are really bucket permissions)
|
|
||||||
can_read_files = [AnyUserIfPublic(), RecordOwners()]
|
|
||||||
can_update_files = [RecordOwners()]
|
|
||||||
|
|
||||||
How to override default policies for records.
|
|
||||||
|
|
||||||
Using Custom Generator for a policy:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from invenio_rdm_records.permissions import RDMRecordPermissionPolicy
|
|
||||||
from invenio_config_tugraz.generators import RecordIp
|
|
||||||
|
|
||||||
class TUGRAZPermissionPolicy(RDMRecordPermissionPolicy):
|
|
||||||
|
|
||||||
# Delete access given to RecordIp only.
|
|
||||||
|
|
||||||
can_delete = [RecordIp()]
|
|
||||||
|
|
||||||
RECORDS_PERMISSIONS_RECORD_POLICY = TUGRAZPermissionPolicy
|
|
||||||
|
|
||||||
|
|
||||||
Permissions for Invenio records.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# from invenio_records_permissions.generators import (
|
|
||||||
# Admin,
|
|
||||||
# AnyUser,
|
|
||||||
# AnyUserIfPublic,
|
|
||||||
# RecordOwners,
|
|
||||||
# )
|
|
||||||
# from invenio_records_permissions.policies.base import BasePermissionPolicy
|
|
||||||
|
|
||||||
# from .generators import RecordIp
|
|
||||||
|
|
||||||
|
|
||||||
# class TUGRAZPermissionPolicy(BasePermissionPolicy):
|
|
||||||
# """Access control configuration for records.
|
|
||||||
|
|
||||||
# This overrides the /api/records endpoint.
|
|
||||||
|
|
||||||
# """
|
|
||||||
|
|
||||||
# # Read access to API given to everyone.
|
|
||||||
# can_search = [AnyUser(), RecordIp()]
|
|
||||||
|
|
||||||
# # Read access given to everyone if public record/files and owners always.
|
|
||||||
# can_read = [AnyUserIfPublic(), RecordOwners(), RecordIp()]
|
|
||||||
|
|
||||||
# # Create action given to no one (Not even superusers) bc Deposits should
|
|
||||||
# # be used.
|
|
||||||
# can_create = [AnyUser()]
|
|
||||||
|
|
||||||
# # Update access given to record owners.
|
|
||||||
# can_update = [RecordOwners()]
|
|
||||||
|
|
||||||
# # Delete access given to admins only.
|
|
||||||
# can_delete = [Admin()]
|
|
||||||
|
|
||||||
# # Associated files permissions (which are really bucket permissions)
|
|
||||||
# can_read_files = [AnyUserIfPublic(), RecordOwners()]
|
|
||||||
# can_update_files = [RecordOwners()]
|
|
||||||
@@ -1,32 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Copyright (C) 2020 Mojib Wali.
|
|
||||||
#
|
|
||||||
# invenio-config-tugraz is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
||||||
# details.
|
|
||||||
|
|
||||||
"""invenio module that adds tugraz configs."""
|
|
||||||
from flask import Blueprint
|
|
||||||
|
|
||||||
from . import config
|
|
||||||
|
|
||||||
|
|
||||||
class InvenioConfigTugraz(object):
|
|
||||||
"""invenio-config-tugraz extension."""
|
|
||||||
|
|
||||||
def __init__(self, app=None):
|
|
||||||
"""Extension initialization."""
|
|
||||||
if app:
|
|
||||||
self.init_app(app)
|
|
||||||
|
|
||||||
def init_app(self, app):
|
|
||||||
"""Flask application initialization."""
|
|
||||||
self.init_config(app)
|
|
||||||
app.extensions["invenio-config-tugraz"] = self
|
|
||||||
|
|
||||||
def init_config(self, app):
|
|
||||||
"""Initialize configuration."""
|
|
||||||
for k in dir(config):
|
|
||||||
if k.startswith("INVENIO_CONFIG_TUGRAZ_"):
|
|
||||||
app.config.setdefault(k, getattr(config, k))
|
|
||||||
@@ -1,223 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Copyright (C) 2020-2021 Graz University of Technology.
|
|
||||||
#
|
|
||||||
# invenio-config-tugraz is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
||||||
# details.
|
|
||||||
|
|
||||||
r"""Permission generators and policies for Invenio records.
|
|
||||||
|
|
||||||
Invenio-records-permissions provides a means to fully customize access control
|
|
||||||
for Invenio records. It does so by defining and providing three layers of
|
|
||||||
permission constructs that build on each other:
|
|
||||||
Generators and Policies. You can extend or override them for maximum
|
|
||||||
control. Thankfully we provide default ones that cover most cases.
|
|
||||||
|
|
||||||
Invenio-records-permissions conveniently structures (and relies on)
|
|
||||||
functionalities from
|
|
||||||
`invenio-access <https://invenio-access.readthedocs.io>`_ and
|
|
||||||
`flask-principal <https://pythonhosted.org/Flask-Principal>`_ .
|
|
||||||
|
|
||||||
|
|
||||||
Generators
|
|
||||||
----------
|
|
||||||
|
|
||||||
Generators are the lowest level of abstraction provided by
|
|
||||||
invenio-records-permissions. A
|
|
||||||
:py:class:`~invenio_records_permissions.generators.Generator` represents
|
|
||||||
identities via
|
|
||||||
`Needs <https://invenio-access.readthedocs.io/en/latest/api.html#needs>`_ that
|
|
||||||
are allowed or disallowed to act on a kind of object. A Generator does not
|
|
||||||
specify the action, but it does specify who is allowed and the kind of object
|
|
||||||
of concern (typically records). Generators *generate* required and forbidden
|
|
||||||
Needs at the object-of-concern level and *generate* query filters
|
|
||||||
at the search-for-objects-of-concern level.
|
|
||||||
|
|
||||||
A Generator object defines 3 methods in addition to its constructor:
|
|
||||||
|
|
||||||
- ``needs(self, **kwargs)``: returns Needs, one of which a provider is
|
|
||||||
required to have to be allowed
|
|
||||||
- ``excludes(self, **kwargs)``: returns a list of Needs disallowing any
|
|
||||||
provider of a single one
|
|
||||||
- ``query_filter(self, **kwargs)``: returns a query filter to enable retrieval
|
|
||||||
of records
|
|
||||||
|
|
||||||
The ``needs`` and ``excludes`` methods specify access conditions from
|
|
||||||
the point-of-view of the object-of-concern; whereas, the ``query_filter``
|
|
||||||
method specifies those from the actor's point-of-view in search scenarios.
|
|
||||||
|
|
||||||
A simple example of a Generator is the provided
|
|
||||||
:py:class:`~invenio_records_permissions.generators.RecordOwners` Generator:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from flask_principal import UserNeed
|
|
||||||
|
|
||||||
|
|
||||||
class RecordOwners(Generator):
|
|
||||||
'''Allows record owners.'''
|
|
||||||
|
|
||||||
def needs(self, record=None, **kwargs):
|
|
||||||
'''Enabling Needs.'''
|
|
||||||
return [UserNeed(owner) for owner in record.get('owners', [])]
|
|
||||||
|
|
||||||
def query_filter(self, record=None, **kwargs):
|
|
||||||
'''Filters for current identity as owner.'''
|
|
||||||
# NOTE: implementation subject to change until permissions metadata
|
|
||||||
# settled
|
|
||||||
provides = g.identity.provides
|
|
||||||
for need in provides:
|
|
||||||
if need.method == 'id':
|
|
||||||
return Q('term', owners=need.value)
|
|
||||||
return []
|
|
||||||
|
|
||||||
``RecordOwners`` allows any identity providing a `UserNeed
|
|
||||||
<https://pythonhosted.org/Flask-Principal/#flask_principal.UserNeed>`_
|
|
||||||
of value found in the ``owners`` metadata of a record. The
|
|
||||||
``query_filter(self, **kwargs)``
|
|
||||||
method outputs a query that returns all owned records of the current user.
|
|
||||||
Not included in the above, because it doesn't apply to ``RecordOwners``, is
|
|
||||||
the ``excludes(self, **kwargs)`` method.
|
|
||||||
|
|
||||||
.. Note::
|
|
||||||
|
|
||||||
Exclusion has priority over inclusion. If a Need is returned by both
|
|
||||||
``needs`` and ``excludes``, providers of that Need will be **excluded**.
|
|
||||||
|
|
||||||
If implementation of Generators seems daunting, fear not! A collection of
|
|
||||||
them has already been implemented in
|
|
||||||
:py:mod:`~invenio_records_permissions.generators`
|
|
||||||
and they cover most cases you may have.
|
|
||||||
|
|
||||||
To fully understand how they work, we have to show where Generators are used.
|
|
||||||
That is in the Policies.
|
|
||||||
|
|
||||||
|
|
||||||
Policies
|
|
||||||
--------
|
|
||||||
|
|
||||||
Classes inheriting from
|
|
||||||
:py:class:`~invenio_records_permissions.policies.base.BasePermissionPolicy` are
|
|
||||||
referred to as Policies. They list **what actions** can be done **by whom**
|
|
||||||
over an implied category of objects (typically records). A Policy is
|
|
||||||
instantiated on a per action basis and is a descendant of `Permission
|
|
||||||
<https://invenio-access.readthedocs.io/en/latest/api.html
|
|
||||||
#invenio_access.permissions.Permission>`_ in
|
|
||||||
`invenio-access <https://invenio-access.readthedocs.io>`_ .
|
|
||||||
Generators are used to provide the "by whom" part and the implied category of
|
|
||||||
object.
|
|
||||||
|
|
||||||
Here is an example of a custom record Policy:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from invenio_records_permissions.generators import AnyUser, RecordOwners, \
|
|
||||||
SuperUser
|
|
||||||
from invenio_records_permissions.policies.base import BasePermissionPolicy
|
|
||||||
|
|
||||||
class ExampleRecordPermissionPolicy(BasePermissionPolicy):
|
|
||||||
can_create = [AnyUser()]
|
|
||||||
can_search = [AnyUser()]
|
|
||||||
can_read = [AnyUser()]
|
|
||||||
can_update = [RecordOwners()]
|
|
||||||
can_foo_bar = [SuperUser()]
|
|
||||||
|
|
||||||
The actions are class variables of the form: ``can_<action>`` and the
|
|
||||||
corresponding (dis-)allowed identities are a list of Generator instances.
|
|
||||||
One can define any action as long as it follows that pattern and
|
|
||||||
is verified at the moment it is undertaken.
|
|
||||||
|
|
||||||
In the example above, any user can create, list and read records, but only
|
|
||||||
a record's owner can edit it and only super users can perform the "foo_bar"
|
|
||||||
action.
|
|
||||||
|
|
||||||
We recommend you extend the provided
|
|
||||||
:py:class:`invenio_records_permissions.policies.records.RecordPermissionPolicy`
|
|
||||||
to customize record permissions for your instance.
|
|
||||||
This way you benefit from sane defaults.
|
|
||||||
|
|
||||||
After you have defined your own Policy, set it in your configuration:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
RECORDS_PERMISSIONS_RECORD_POLICY = (
|
|
||||||
'module.to.ExampleRecordPermissionPolicy'
|
|
||||||
)
|
|
||||||
|
|
||||||
The succinct encoding of the permissions for your instance gives you
|
|
||||||
- one central location where your permissions are defined
|
|
||||||
- exact control
|
|
||||||
- great flexibility by defining your own actions, generators and policies
|
|
||||||
"""
|
|
||||||
|
|
||||||
from elasticsearch_dsl.query import Q
|
|
||||||
from flask import current_app, request
|
|
||||||
from invenio_access.permissions import any_user, superuser_access
|
|
||||||
from invenio_records_permissions.generators import Generator
|
|
||||||
|
|
||||||
|
|
||||||
class RecordIp(Generator):
|
|
||||||
"""Allowed any user with accessing with the IP."""
|
|
||||||
|
|
||||||
def needs(self, record=None, **kwargs):
|
|
||||||
"""Enabling Needs, Set of Needs granting permission."""
|
|
||||||
if record is None:
|
|
||||||
return []
|
|
||||||
|
|
||||||
# check if singleip is in the records restriction
|
|
||||||
is_single_ip = record.get("access", {}).get("access_right") == "singleip"
|
|
||||||
|
|
||||||
# check if the user ip is on list
|
|
||||||
visible = self.check_permission()
|
|
||||||
|
|
||||||
if not is_single_ip:
|
|
||||||
# if record does not have singleip - return any_user
|
|
||||||
return [any_user]
|
|
||||||
# if record has singleip, then check the ip of user - if ip user is on list - return any_user
|
|
||||||
elif visible:
|
|
||||||
return [any_user]
|
|
||||||
else:
|
|
||||||
# non of the above - return empty
|
|
||||||
return []
|
|
||||||
|
|
||||||
def excludes(self, **kwargs):
|
|
||||||
"""Preventing Needs, Set of Needs denying permission.
|
|
||||||
|
|
||||||
If ANY of the Needs are matched, permission is revoked.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
``_load_permissions()`` method from `Permission
|
|
||||||
<https://invenio-access.readthedocs.io/en/latest/api.html
|
|
||||||
#invenio_access.permissions.Permission>`_ adds by default the
|
|
||||||
``superuser_access`` Need (if tied to a User or Role) for us.
|
|
||||||
|
|
||||||
It also expands ActionNeeds into the Users/Roles that
|
|
||||||
provide them.
|
|
||||||
|
|
||||||
If the same Need is returned by `needs` and `excludes`, then that
|
|
||||||
Need provider is disallowed.
|
|
||||||
"""
|
|
||||||
return []
|
|
||||||
|
|
||||||
def query_filter(self, *args, **kwargs):
|
|
||||||
"""Filters for singleip records."""
|
|
||||||
# check if the user ip is on list
|
|
||||||
visible = self.check_permission()
|
|
||||||
|
|
||||||
if not visible:
|
|
||||||
# If user ip is not on the list, and If the record contains 'singleip' will not be seen
|
|
||||||
return ~Q("match", **{"access.access_right": "singleip"})
|
|
||||||
|
|
||||||
# Lists all records
|
|
||||||
return Q("match_all")
|
|
||||||
|
|
||||||
def check_permission(self):
|
|
||||||
"""Check for User IP address in config variable."""
|
|
||||||
# Get user IP
|
|
||||||
user_ip = request.remote_addr
|
|
||||||
# Checks if the user IP is among single IPs
|
|
||||||
if user_ip in current_app.config["INVENIO_CONFIG_TUGRAZ_SINGLE_IP"]:
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
@@ -1,86 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Copyright (C) 2020-2021 Graz University of Technology.
|
|
||||||
#
|
|
||||||
# invenio-config-tugraz is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
||||||
# details.
|
|
||||||
|
|
||||||
"""
|
|
||||||
Records permission policies.
|
|
||||||
|
|
||||||
Default policies for records:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
# Read access given to everyone.
|
|
||||||
can_search = [AnyUser()]
|
|
||||||
# Create action given to no one (Not even superusers) bc Deposits should
|
|
||||||
# be used.
|
|
||||||
can_create = [Disable()]
|
|
||||||
# Read access given to everyone if public record/files and owners always.
|
|
||||||
can_read = [AnyUserIfPublic(), RecordOwners()]
|
|
||||||
# Update access given to record owners.
|
|
||||||
can_update = [RecordOwners()]
|
|
||||||
# Delete access given to admins only.
|
|
||||||
can_delete = [Admin()]
|
|
||||||
# Associated files permissions (which are really bucket permissions)
|
|
||||||
can_read_files = [AnyUserIfPublic(), RecordOwners()]
|
|
||||||
can_update_files = [RecordOwners()]
|
|
||||||
|
|
||||||
How to override default policies for rdm-records.
|
|
||||||
|
|
||||||
Using Custom Generator for a policy:
|
|
||||||
|
|
||||||
.. code-block:: python
|
|
||||||
|
|
||||||
from invenio_rdm_records.services import (
|
|
||||||
BibliographicRecordServiceConfig,
|
|
||||||
RDMRecordPermissionPolicy,
|
|
||||||
)
|
|
||||||
|
|
||||||
from invenio_config_tugraz.generators import RecordIp
|
|
||||||
|
|
||||||
class TUGRAZPermissionPolicy(RDMRecordPermissionPolicy):
|
|
||||||
|
|
||||||
# Create access given to SuperUser only.
|
|
||||||
|
|
||||||
can_create = [SuperUser()]
|
|
||||||
|
|
||||||
RDM_RECORDS_BIBLIOGRAPHIC_SERVICE_CONFIG = TUGRAZBibliographicRecordServiceConfig
|
|
||||||
|
|
||||||
|
|
||||||
Permissions for Invenio (RDM) Records.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# from invenio_rdm_records.services import RDMRecordPermissionPolicy
|
|
||||||
# from invenio_rdm_records.services.config import RDMRecordServiceConfig
|
|
||||||
# from invenio_rdm_records.services.generators import IfDraft, IfRestricted, RecordOwners
|
|
||||||
# from invenio_records_permissions.generators import (
|
|
||||||
# Admin,
|
|
||||||
# AnyUser,
|
|
||||||
# AuthenticatedUser,
|
|
||||||
# Disable,
|
|
||||||
# SuperUser,
|
|
||||||
# SystemProcess,
|
|
||||||
# )
|
|
||||||
|
|
||||||
|
|
||||||
# class TUGRAZPermissionPolicy(RDMRecordPermissionPolicy):
|
|
||||||
# """Access control configuration for rdm records.
|
|
||||||
|
|
||||||
# This overrides the origin:
|
|
||||||
# https://github.com/inveniosoftware/invenio-rdm-records/blob/master/invenio_rdm_records/services/permissions.py.
|
|
||||||
# Access control configuration for records.
|
|
||||||
# Note that even if the array is empty, the invenio_access Permission class
|
|
||||||
# always adds the ``superuser-access``, so admins will always be allowed.
|
|
||||||
# - Create action given to everyone for now.
|
|
||||||
# - Read access given to everyone if public record and given to owners
|
|
||||||
# always. (inherited)
|
|
||||||
# - Update access given to record owners. (inherited)
|
|
||||||
# - Delete access given to admins only. (inherited)
|
|
||||||
# """
|
|
||||||
|
|
||||||
|
|
||||||
# class TUGRAZRDMRecordServiceConfig(RDMRecordServiceConfig):
|
|
||||||
# """Overriding BibliographicRecordServiceConfig."""
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Copyright (C) 2020-2021 Graz University of Technology.
|
|
||||||
#
|
|
||||||
# invenio-config-tugraz is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
||||||
# details.
|
|
||||||
|
|
||||||
"""Version information for invenio-config-tugraz.
|
|
||||||
|
|
||||||
This file is imported by ``invenio_config_tugraz.__init__``,
|
|
||||||
and parsed by ``setup.py``.
|
|
||||||
"""
|
|
||||||
|
|
||||||
__version__ = "0.8.0"
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Copyright (C) 2020-2021 Graz University of Technology.
|
|
||||||
#
|
|
||||||
# invenio-config-tugraz is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
||||||
# details.
|
|
||||||
|
|
||||||
"""invenio module for TUGRAZ config."""
|
|
||||||
|
|
||||||
from os import environ
|
|
||||||
from typing import Dict
|
|
||||||
|
|
||||||
from elasticsearch_dsl.utils import AttrDict
|
|
||||||
from flask import Blueprint, current_app, redirect, url_for
|
|
||||||
from flask_babelex import get_locale
|
|
||||||
|
|
||||||
|
|
||||||
def ui_blueprint(app):
|
|
||||||
"""Blueprint for the routes and resources provided by invenio-config-tugraz."""
|
|
||||||
routes = app.config.get("CONFIG_TUGRAZ_ROUTES")
|
|
||||||
|
|
||||||
blueprint = Blueprint(
|
|
||||||
"invenio_config_tugraz",
|
|
||||||
__name__,
|
|
||||||
template_folder="templates",
|
|
||||||
static_folder="static",
|
|
||||||
)
|
|
||||||
|
|
||||||
blueprint.add_url_rule(routes["guide"], view_func=guide)
|
|
||||||
blueprint.add_url_rule(routes["terms"], view_func=terms)
|
|
||||||
blueprint.add_url_rule(routes["gdpr"], view_func=gdpr)
|
|
||||||
|
|
||||||
@blueprint.before_app_first_request
|
|
||||||
def rank_higher():
|
|
||||||
"""Rank this modules blueprint higher than blueprint of security module.
|
|
||||||
|
|
||||||
Needed in order to overwrite email templates.
|
|
||||||
|
|
||||||
Since the blueprints are in a dict and the order of insertion is
|
|
||||||
retained, popping and reinserting all items (except ours), ensures
|
|
||||||
our blueprint will be in front.
|
|
||||||
"""
|
|
||||||
bps = current_app.blueprints
|
|
||||||
for blueprint_name in list(bps.keys()):
|
|
||||||
if blueprint_name != "invenio_config_tugraz":
|
|
||||||
bps.update({blueprint_name: bps.pop(blueprint_name)})
|
|
||||||
|
|
||||||
return blueprint
|
|
||||||
|
|
||||||
|
|
||||||
def guide():
|
|
||||||
"""TUGraz_Repository_Guide."""
|
|
||||||
locale = get_locale()
|
|
||||||
return redirect(url_for('static',
|
|
||||||
filename=f'documents/TUGraz_Repository_Guide_02_{locale}.pdf',
|
|
||||||
_external=True))
|
|
||||||
|
|
||||||
|
|
||||||
def terms():
|
|
||||||
"""Terms_And_Conditions."""
|
|
||||||
locale = get_locale()
|
|
||||||
return redirect(url_for('static',
|
|
||||||
filename=f'documents/TUGraz_Repository_Terms_And_Conditions_{locale}.pdf',
|
|
||||||
_external=True))
|
|
||||||
|
|
||||||
|
|
||||||
def gdpr():
|
|
||||||
"""General_Data_Protection_Rights."""
|
|
||||||
locale = get_locale()
|
|
||||||
return redirect(url_for('static',
|
|
||||||
filename=f'documents/TUGraz_Repository_General_Data_Protection_Rights_{locale}.pdf',
|
|
||||||
_external=True))
|
|
||||||
135
pyproject.toml
Normal file
135
pyproject.toml
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
[project]
|
||||||
|
name = "invenio-config-iform"
|
||||||
|
dynamic = ["version"]
|
||||||
|
description = "Invenio module that adds I-Form configs."
|
||||||
|
readme = { file = "README.rst", content-type = "text/x-rst" }
|
||||||
|
license = "MIT"
|
||||||
|
authors = [
|
||||||
|
{ name = "I-Form Advanced Research Manufacturing Research Centre", email = "cian.hughes@dcu.ie" },
|
||||||
|
]
|
||||||
|
keywords = ["invenio", "config", "I-Form"]
|
||||||
|
classifiers = [
|
||||||
|
"Environment :: Web Environment",
|
||||||
|
"Intended Audience :: Developers",
|
||||||
|
"Operating System :: OS Independent",
|
||||||
|
"Programming Language :: Python",
|
||||||
|
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
|
||||||
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
||||||
|
"Programming Language :: Python :: 3.10",
|
||||||
|
"Programming Language :: Python :: 3.11",
|
||||||
|
"Programming Language :: Python :: 3.12",
|
||||||
|
"Programming Language :: Python :: 3.13",
|
||||||
|
"Development Status :: 3 - Alpha",
|
||||||
|
]
|
||||||
|
requires-python = ">=3.10,<3.14"
|
||||||
|
dependencies = [
|
||||||
|
"invenio-cache>=1.1.1",
|
||||||
|
"invenio-i18n>=2.0.0",
|
||||||
|
"invenio-rdm-records>=4.0.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[project.urls]
|
||||||
|
Homepage = "https://github.com/Cian-H/invenio-config-iform"
|
||||||
|
Issues = "https://github.com/Cian-H/invenio-config-iform/issues"
|
||||||
|
|
||||||
|
[project.scripts]
|
||||||
|
test-docs = "scripts.test_docs:main"
|
||||||
|
test-code = "pytest:console_main"
|
||||||
|
test = "scripts.test:main"
|
||||||
|
|
||||||
|
[project.entry-points."invenio_base.apps"]
|
||||||
|
invenio_config_iform = "invenio_config_iform:InvenioConfigIform"
|
||||||
|
|
||||||
|
[project.entry-points."invenio_base.blueprints"]
|
||||||
|
invenio_config_iform = "invenio_config_iform.views:ui_blueprint"
|
||||||
|
|
||||||
|
[project.entry-points."invenio_i18n.translations"]
|
||||||
|
messages = "invenio_config_iform"
|
||||||
|
|
||||||
|
[project.entry-points."invenio_config.module"]
|
||||||
|
invenio_config_iform = "invenio_config_iform.config"
|
||||||
|
|
||||||
|
[project.entry-points."invenio_base.finalize_app"]
|
||||||
|
invenio_config_iform = "invenio_config_iform.ext:finalize_app"
|
||||||
|
|
||||||
|
[dependency-groups]
|
||||||
|
dev = [
|
||||||
|
"hatch>=1.14.1",
|
||||||
|
"pre-commit>=4.2.0",
|
||||||
|
"pydocstyle>=6.3.0",
|
||||||
|
"ruff>=0.11.7",
|
||||||
|
]
|
||||||
|
tests = [
|
||||||
|
"invenio-app>=1.5.0",
|
||||||
|
"invenio-search[opensearch2]>=2.1.0",
|
||||||
|
"pytest-invenio>=2.1.0",
|
||||||
|
"pytest-ruff>=0.4.1",
|
||||||
|
"ruff>=0.5.3",
|
||||||
|
"Sphinx>=4.5.0",
|
||||||
|
]
|
||||||
|
docs = [
|
||||||
|
"invenio-app>=1.5.0",
|
||||||
|
"invenio-search[opensearch2]>=2.1.0",
|
||||||
|
"Sphinx>=4.5.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[build-system]
|
||||||
|
requires = ["hatchling", "hatch-calver"]
|
||||||
|
build-backend = "hatchling.build"
|
||||||
|
|
||||||
|
[tool.hatch.version]
|
||||||
|
scheme = "calver"
|
||||||
|
path = "invenio_config_iform/__about__.py"
|
||||||
|
|
||||||
|
[tool.hatch.build]
|
||||||
|
include = ["invenio_config_iform"]
|
||||||
|
exclude = [".venv", "tests/*", "*/tests/*", "*.rst", "run-tests.sh"]
|
||||||
|
|
||||||
|
# Testing configuration
|
||||||
|
[tool.pytest]
|
||||||
|
addopts = "--ruff --ruff-format --pydocstyle --doctest-glob=\"*.rst\" --doctest-modules --cov=invenio_config_iform --cov-report=term-missing tests invenio_config_iform"
|
||||||
|
testpaths = ["tests", "invenio_config_iform"]
|
||||||
|
live_server_scope = "module"
|
||||||
|
|
||||||
|
[tool.pytest.ini_options]
|
||||||
|
addopts = "--ruff --ruff-format --pydocstyle --doctest-glob=\"*.rst\" --doctest-modules --cov=invenio_config_iform --cov-report=term-missing tests invenio_config_iform"
|
||||||
|
testpaths = ["tests", "invenio_config_iform"]
|
||||||
|
live_server_scope = "module"
|
||||||
|
|
||||||
|
# Code style tools configuration
|
||||||
|
[tool.ruff]
|
||||||
|
line-length = 100
|
||||||
|
target-version = "py313"
|
||||||
|
exclude = ["docs"]
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
select = ["ALL"]
|
||||||
|
ignore = [
|
||||||
|
"D203",
|
||||||
|
"D211",
|
||||||
|
"D212",
|
||||||
|
"D213",
|
||||||
|
"E501",
|
||||||
|
"ERA001",
|
||||||
|
"FA102",
|
||||||
|
"FIX002",
|
||||||
|
"INP001",
|
||||||
|
"RUF005",
|
||||||
|
"RUF012",
|
||||||
|
"S101",
|
||||||
|
"TD002",
|
||||||
|
"TD003",
|
||||||
|
"UP009",
|
||||||
|
]
|
||||||
|
|
||||||
|
[tool.ruff.lint.isort]
|
||||||
|
force-sort-within-sections = true
|
||||||
|
lines-after-imports = -1
|
||||||
|
|
||||||
|
[tool.ruff.format]
|
||||||
|
quote-style = "double"
|
||||||
|
indent-style = "space"
|
||||||
|
line-ending = "auto"
|
||||||
|
|
||||||
|
[tool.pydocstyle]
|
||||||
|
add_ignore = ["D401"]
|
||||||
12
pytest.ini
12
pytest.ini
@@ -1,12 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Copyright (C) 2020 Mojib Wali.
|
|
||||||
#
|
|
||||||
# invenio-config-tugraz is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
||||||
# details.
|
|
||||||
|
|
||||||
[pytest]
|
|
||||||
addopts = --isort --pydocstyle --pycodestyle --doctest-glob="*.rst" --doctest-modules --cov=invenio_config_tugraz --cov-report=term-missing tests invenio_config_tugraz
|
|
||||||
testpaths = tests invenio_config_tugraz
|
|
||||||
live_server_scope = module
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Copyright (C) 2020 Mojib Wali.
|
|
||||||
#
|
|
||||||
# invenio-config-tugraz is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
||||||
# details.
|
|
||||||
#
|
|
||||||
# TODO: Add development versions of some important dependencies here to get a
|
|
||||||
# warning when there are breaking upstream changes, e.g.:
|
|
||||||
#
|
|
||||||
# -e git+git://github.com/mitsuhiko/werkzeug.git#egg=Werkzeug
|
|
||||||
# -e git+git://github.com/mitsuhiko/jinja2.git#egg=Jinja2
|
|
||||||
33
run-tests.sh
33
run-tests.sh
@@ -1,33 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Copyright (C) 2019-2020 CERN.
|
|
||||||
# Copyright (C) 2019-2020 Northwestern University.
|
|
||||||
# Copyright (C) 2020 Graz University of Technology.
|
|
||||||
#
|
|
||||||
# invenio-config-tugraz is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
||||||
# details.
|
|
||||||
|
|
||||||
|
|
||||||
# Quit on errors
|
|
||||||
set -o errexit
|
|
||||||
|
|
||||||
# Quit on unbound symbols
|
|
||||||
set -o nounset
|
|
||||||
|
|
||||||
# Always bring down docker services
|
|
||||||
|
|
||||||
function cleanup() {
|
|
||||||
eval "$(docker-services-cli down --env)"
|
|
||||||
}
|
|
||||||
trap cleanup EXIT
|
|
||||||
|
|
||||||
|
|
||||||
python -m check_manifest --ignore ".*-requirements.txt"
|
|
||||||
python -m sphinx.cmd.build -qnN docs docs/_build/html
|
|
||||||
eval "$(docker-services-cli up --db ${DB:-postgresql} --search ${SEARCH:-elasticsearch} --cache ${CACHE:-redis} --env)"
|
|
||||||
python -m pytest
|
|
||||||
tests_exit_code=$?
|
|
||||||
python -m sphinx.cmd.build -qnN -b doctest docs docs/_build/doctest
|
|
||||||
exit "$tests_exit_code"
|
|
||||||
126
scripts/hooks/pre-push/check_version_increment.py
Executable file
126
scripts/hooks/pre-push/check_version_increment.py
Executable file
@@ -0,0 +1,126 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""A Script for checking that the version number has been incremented between pushes."""
|
||||||
|
|
||||||
|
from pathlib import Path
|
||||||
|
import re
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
import tomllib
|
||||||
|
|
||||||
|
ALLOWED_EXECUTABLES: list[str] = [
|
||||||
|
"git",
|
||||||
|
"uv",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def validate_command(command: str) -> list[str]:
|
||||||
|
"""Validate and guard command calls.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
command (str): the command to be validated.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: the validated command
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FileNotFoundError: if the command was not found
|
||||||
|
|
||||||
|
"""
|
||||||
|
cmd: list[str] = command.split().copy()
|
||||||
|
if cmd[0] not in ALLOWED_EXECUTABLES:
|
||||||
|
msg = f"Command {cmd} is not allowed!"
|
||||||
|
raise PermissionError(msg)
|
||||||
|
call = shutil.which(cmd[0])
|
||||||
|
if not call:
|
||||||
|
msg = f"Command {call} not found!"
|
||||||
|
raise FileNotFoundError(msg)
|
||||||
|
cmd[0] = call
|
||||||
|
if cmd[0] == "uv" and cmd[1] == "run":
|
||||||
|
cmd = [cmd[0], cmd[1], *validate_command("".join(cmd[2:]))]
|
||||||
|
return cmd
|
||||||
|
|
||||||
|
|
||||||
|
def run_command(command: str) -> str:
|
||||||
|
"""Run a command and get its output as a string.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
command (str): The command to run.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The output returned on stdout.
|
||||||
|
|
||||||
|
"""
|
||||||
|
cmd = validate_command(command)
|
||||||
|
return subprocess.run( # noqa: S603
|
||||||
|
cmd,
|
||||||
|
capture_output=True,
|
||||||
|
text=True,
|
||||||
|
check=True,
|
||||||
|
).stdout.strip()
|
||||||
|
|
||||||
|
|
||||||
|
def get_version_file_from_pyproject() -> str:
|
||||||
|
"""Get the path to the version file from the pyproject file.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: the path to the project version file
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
FileNotFoundError: the pyproject file is not found
|
||||||
|
KeyError: the pyproject file does not reference a version file
|
||||||
|
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
with Path("pyproject.toml").open("rb") as f:
|
||||||
|
return tomllib.load(f)["tool"]["hatch"]["version"]["path"]
|
||||||
|
except FileNotFoundError as e:
|
||||||
|
msg = "Project has no pyproject.toml file!"
|
||||||
|
raise FileNotFoundError(msg) from e
|
||||||
|
except KeyError as e:
|
||||||
|
msg = "Attribute `tool.hatch.version.path` not found in pyproject.toml"
|
||||||
|
raise KeyError(msg) from e
|
||||||
|
|
||||||
|
|
||||||
|
def get_remote_version(remote: str, branch: str, version_file: str) -> str:
|
||||||
|
"""Get the version from the repository remote.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
remote (str): The remote to fetch the version string from.
|
||||||
|
branch (str): The branch to fetch the version string from.
|
||||||
|
version_file (str): The file to fetch the version string from.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
str: The version string.
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
AttributeError: NO `__version__` attribute was found in `version_file`.
|
||||||
|
|
||||||
|
"""
|
||||||
|
remote_file = f"{remote}/{branch}:{version_file}"
|
||||||
|
match = re.search(
|
||||||
|
r"__version__\s*=\s*['\"]([^'\"]+)['\"]",
|
||||||
|
run_command(f"git show {remote_file}"),
|
||||||
|
)
|
||||||
|
if match:
|
||||||
|
return match.group(1)
|
||||||
|
msg = f"No `__version__` attribute found in {remote_file}"
|
||||||
|
raise AttributeError(msg)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Entrypoint for this script."""
|
||||||
|
version_file = get_version_file_from_pyproject()
|
||||||
|
branch = run_command("git rev-parse --abbrev-ref HEAD")
|
||||||
|
remote = sys.argv[1] if len(sys.argv) > 1 else "origin"
|
||||||
|
|
||||||
|
current_version = run_command("uv run hatch version")
|
||||||
|
remote_version = get_remote_version(remote, branch, version_file)
|
||||||
|
|
||||||
|
assert current_version != remote_version, (
|
||||||
|
"Version has not been incremented! Please update the version before pushing."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
19
scripts/test.py
Normal file
19
scripts/test.py
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2025 I-Form Advanced Manufacturing Research Centre.
|
||||||
|
#
|
||||||
|
# invenio-config-iform is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
|
# details.
|
||||||
|
|
||||||
|
"""Run all tests for this module consecutively."""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from . import test_docs
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Run tests for this module."""
|
||||||
|
test_docs.main()
|
||||||
|
pytest.console_main()
|
||||||
16
scripts/test_docs.py
Normal file
16
scripts/test_docs.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2025 I-Form Advanced Manufacturing Research Centre.
|
||||||
|
#
|
||||||
|
# invenio-config-iform is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
|
# details.
|
||||||
|
|
||||||
|
"""A script for testing sphinx documentation building."""
|
||||||
|
|
||||||
|
from sphinx.cmd.build import main as build_docs
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
"""Attempt to build documentation."""
|
||||||
|
build_docs(["-nN", "docs", "docs/_build/html"])
|
||||||
56
setup.cfg
56
setup.cfg
@@ -1,56 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Copyright (C) 2020 Mojib Wali.
|
|
||||||
#
|
|
||||||
# invenio-config-tugraz is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
||||||
# details.
|
|
||||||
|
|
||||||
[aliases]
|
|
||||||
test = pytest
|
|
||||||
|
|
||||||
[build_sphinx]
|
|
||||||
source-dir = docs/
|
|
||||||
build-dir = docs/_build
|
|
||||||
all_files = 1
|
|
||||||
|
|
||||||
[bdist_wheel]
|
|
||||||
universal = 1
|
|
||||||
|
|
||||||
[pydocstyle]
|
|
||||||
add_ignore = D401
|
|
||||||
|
|
||||||
[compile_catalog]
|
|
||||||
directory = invenio_config_tugraz/translations/
|
|
||||||
|
|
||||||
[extract_messages]
|
|
||||||
copyright_holder = Graz University of Technology
|
|
||||||
msgid_bugs_address = mojib.wali@tugraz.at
|
|
||||||
mapping-file = babel.ini
|
|
||||||
output-file = invenio_config_tugraz/translations/messages.pot
|
|
||||||
add-comments = NOTE
|
|
||||||
|
|
||||||
[init_catalog]
|
|
||||||
input-file = invenio_config_tugraz/translations/messages.pot
|
|
||||||
output-dir = invenio_config_tugraz/translations/
|
|
||||||
|
|
||||||
[update_catalog]
|
|
||||||
input-file = invenio_config_tugraz/translations/messages.pot
|
|
||||||
output-dir = invenio_config_tugraz/translations/
|
|
||||||
|
|
||||||
[flake8]
|
|
||||||
max-line-length = 88
|
|
||||||
extend-ignore = E203
|
|
||||||
select = C,E,F,W,B,B950
|
|
||||||
ignore = E501
|
|
||||||
|
|
||||||
[isort]
|
|
||||||
multi_line_output = 3
|
|
||||||
include_trailing_comma = True
|
|
||||||
force_grid_wrap = 0
|
|
||||||
use_parentheses = True
|
|
||||||
ensure_newline_before_comments = True
|
|
||||||
line_length = 88
|
|
||||||
|
|
||||||
[pycodestyle]
|
|
||||||
ignore = E203,E501
|
|
||||||
114
setup.py
114
setup.py
@@ -1,114 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Copyright (C) 2020-2021 Graz University of Technology.
|
|
||||||
#
|
|
||||||
# invenio-config-tugraz is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
||||||
# details.
|
|
||||||
|
|
||||||
"""invenio module that adds tugraz configs."""
|
|
||||||
|
|
||||||
import os
|
|
||||||
|
|
||||||
from setuptools import find_packages, setup
|
|
||||||
|
|
||||||
readme = open("README.rst").read()
|
|
||||||
history = open("CHANGES.rst").read()
|
|
||||||
|
|
||||||
tests_require = [
|
|
||||||
"pytest-invenio>=1.4.1",
|
|
||||||
]
|
|
||||||
|
|
||||||
# Should follow invenio-app-rdm
|
|
||||||
invenio_search_version = ">=1.4.1,<1.5.0"
|
|
||||||
invenio_db_version = ">=1.0.9,<1.1.0"
|
|
||||||
|
|
||||||
extras_require = {
|
|
||||||
"elasticsearch7": [f"invenio-search[elasticsearch7]{invenio_search_version}"],
|
|
||||||
"mysql": [f"invenio-db[mysql,versioning]{invenio_db_version}"],
|
|
||||||
"postgresql": [f"invenio-db[postgresql,versioning]{invenio_db_version}"],
|
|
||||||
"sqlite": [f"invenio-db[versioning]{invenio_db_version}"],
|
|
||||||
"docs": [
|
|
||||||
"Sphinx==4.2.0",
|
|
||||||
],
|
|
||||||
"tests": tests_require,
|
|
||||||
}
|
|
||||||
|
|
||||||
extras_require["all"] = []
|
|
||||||
for name, reqs in extras_require.items():
|
|
||||||
if name[0] == ":" or name in (
|
|
||||||
"elasticsearch7",
|
|
||||||
"mysql",
|
|
||||||
"postgresql",
|
|
||||||
"sqlite",
|
|
||||||
):
|
|
||||||
continue
|
|
||||||
extras_require["all"].extend(reqs)
|
|
||||||
|
|
||||||
setup_requires = [
|
|
||||||
"Babel>=2.8,<3",
|
|
||||||
]
|
|
||||||
|
|
||||||
install_requires = [
|
|
||||||
# keep this in sync with invenioRDM release
|
|
||||||
"invenio-rdm-records>=0.34.4,<0.35.0",
|
|
||||||
"invenio-cache>=1.1.0"
|
|
||||||
]
|
|
||||||
|
|
||||||
packages = find_packages()
|
|
||||||
|
|
||||||
|
|
||||||
# Get the version string. Cannot be done with import!
|
|
||||||
g = {}
|
|
||||||
with open(os.path.join("invenio_config_tugraz", "version.py"), "rt") as fp:
|
|
||||||
exec(fp.read(), g)
|
|
||||||
version = g["__version__"]
|
|
||||||
|
|
||||||
setup(
|
|
||||||
name="invenio-config-tugraz",
|
|
||||||
version=version,
|
|
||||||
description=__doc__,
|
|
||||||
long_description=readme + "\n\n" + history,
|
|
||||||
keywords="invenio, config, Tu Graz",
|
|
||||||
license="MIT",
|
|
||||||
author="Mojib Wali",
|
|
||||||
author_email="mb_wali@hotmail.com",
|
|
||||||
url="https://github.com/tu-graz-library/invenio-config-tugraz",
|
|
||||||
packages=packages,
|
|
||||||
zip_safe=False,
|
|
||||||
include_package_data=True,
|
|
||||||
platforms="any",
|
|
||||||
entry_points={
|
|
||||||
"invenio_base.apps": [
|
|
||||||
"invenio_config_tugraz = invenio_config_tugraz:InvenioConfigTugraz",
|
|
||||||
],
|
|
||||||
"invenio_base.blueprints": [
|
|
||||||
"invenio_config_tugraz = invenio_config_tugraz.views:ui_blueprint",
|
|
||||||
],
|
|
||||||
"invenio_i18n.translations": [
|
|
||||||
"messages = invenio_config_tugraz",
|
|
||||||
],
|
|
||||||
"invenio_config.module": [
|
|
||||||
"invenio_config_tugraz = invenio_config_tugraz.config",
|
|
||||||
],
|
|
||||||
},
|
|
||||||
extras_require=extras_require,
|
|
||||||
install_requires=install_requires,
|
|
||||||
setup_requires=setup_requires,
|
|
||||||
tests_require=tests_require,
|
|
||||||
classifiers=[
|
|
||||||
"Environment :: Web Environment",
|
|
||||||
"Intended Audience :: Developers",
|
|
||||||
"License :: OSI Approved :: MIT License",
|
|
||||||
"Operating System :: OS Independent",
|
|
||||||
"Programming Language :: Python",
|
|
||||||
"Topic :: Internet :: WWW/HTTP :: Dynamic Content",
|
|
||||||
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
||||||
"Programming Language :: Python :: 3",
|
|
||||||
"Programming Language :: Python :: 3.6",
|
|
||||||
"Programming Language :: Python :: 3.7",
|
|
||||||
"Programming Language :: Python :: 3.8",
|
|
||||||
"Programming Language :: Python :: 3.9",
|
|
||||||
"Development Status :: 5 - Production/Stable",
|
|
||||||
],
|
|
||||||
)
|
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
#
|
#
|
||||||
# Copyright (C) 2020 Mojib Wali.
|
# Copyright (C) 2020 Mojib Wali.
|
||||||
|
# Copyright (C) 2020-2024 Graz University of Technology.
|
||||||
#
|
#
|
||||||
# invenio-config-tugraz is free software; you can redistribute it and/or
|
# invenio-config-iform is free software; you can redistribute it and/or
|
||||||
# modify it under the terms of the MIT License; see LICENSE file for more
|
# modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
# details.
|
# details.
|
||||||
|
|
||||||
@@ -12,152 +13,20 @@ See https://pytest-invenio.readthedocs.io/ for documentation on which test
|
|||||||
fixtures are available.
|
fixtures are available.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
|
||||||
import shutil
|
|
||||||
import tempfile
|
|
||||||
|
|
||||||
import pytest
|
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
from flask_babelex import Babel
|
import pytest
|
||||||
from invenio_db import InvenioDB, db
|
|
||||||
from sqlalchemy_utils.functions import create_database, database_exists, drop_database
|
|
||||||
|
|
||||||
from invenio_config_tugraz import InvenioConfigTugraz
|
from invenio_config_iform import InvenioConfigIform
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def celery_config():
|
def create_app(instance_path: str) -> Flask:
|
||||||
"""Override pytest-invenio fixture.
|
"""Application factory fixture."""
|
||||||
|
|
||||||
TODO: Remove this fixture if you add Celery support.
|
|
||||||
"""
|
|
||||||
return {}
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture()
|
|
||||||
def create_app(request):
|
|
||||||
"""Basic Flask application."""
|
|
||||||
instance_path = tempfile.mkdtemp()
|
|
||||||
app = Flask("testapp")
|
|
||||||
DB = os.getenv("SQLALCHEMY_DATABASE_URI", "sqlite://")
|
|
||||||
app.config.update(
|
|
||||||
INVENIO_CONFIG_TUGRAZ_SINGLE_IP=["127.0.0.1", "127.0.0.2"],
|
|
||||||
INVENIO_CONFIG_TUGRAZ_IP_RANGES=[
|
|
||||||
["127.0.0.2", "127.0.0.99"],
|
|
||||||
["127.0.1.3", "127.0.1.5"],
|
|
||||||
],
|
|
||||||
SQLALCHEMY_DATABASE_URI=DB,
|
|
||||||
SQLALCHEMY_TRACK_MODIFICATIONS=False,
|
|
||||||
)
|
|
||||||
Babel(app)
|
|
||||||
InvenioConfigTugraz(app)
|
|
||||||
InvenioDB(app)
|
|
||||||
|
|
||||||
with app.app_context():
|
|
||||||
db_url = str(db.engine.url)
|
|
||||||
if db_url != "sqlite://" and not database_exists(db_url):
|
|
||||||
create_database(db_url)
|
|
||||||
db.create_all()
|
|
||||||
|
|
||||||
def teardown():
|
|
||||||
with app.app_context():
|
|
||||||
db_url = str(db.engine.url)
|
|
||||||
db.session.close()
|
|
||||||
if db_url != "sqlite://":
|
|
||||||
drop_database(db_url)
|
|
||||||
shutil.rmtree(instance_path)
|
|
||||||
|
|
||||||
request.addfinalizer(teardown)
|
|
||||||
app.test_request_context().push()
|
|
||||||
|
|
||||||
|
def factory(**config: str) -> Flask:
|
||||||
|
app = Flask("testapp", instance_path=instance_path)
|
||||||
|
app.config.update(**config)
|
||||||
|
InvenioConfigIform(app)
|
||||||
return app
|
return app
|
||||||
|
|
||||||
|
return factory
|
||||||
@pytest.fixture(scope='function')
|
|
||||||
def open_record():
|
|
||||||
"""Open record data as dict coming from the external world."""
|
|
||||||
return {
|
|
||||||
"access": {
|
|
||||||
"metadata": False,
|
|
||||||
"files": False,
|
|
||||||
"owned_by": [1],
|
|
||||||
"access_right": "open"
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"publication_date": "2020-06-01",
|
|
||||||
"resource_type": {
|
|
||||||
"type": "image",
|
|
||||||
"subtype": "image-photo"
|
|
||||||
},
|
|
||||||
# Technically not required
|
|
||||||
"creators": [{
|
|
||||||
"name": "Troy Brown",
|
|
||||||
"type": "personal"
|
|
||||||
}, {
|
|
||||||
"name": "Phillip Lester",
|
|
||||||
"type": "personal",
|
|
||||||
"identifiers": {"orcid": "0000-0002-1825-0097"},
|
|
||||||
"affiliations": [{
|
|
||||||
"name": "Carter-Morris",
|
|
||||||
"identifiers": {"ror": "03yrm5c26"}
|
|
||||||
}]
|
|
||||||
}, {
|
|
||||||
"name": "Steven Williamson",
|
|
||||||
"type": "personal",
|
|
||||||
"identifiers": {"orcid": "0000-0002-1825-0097"},
|
|
||||||
"affiliations": [{
|
|
||||||
"name": "Ritter and Sons",
|
|
||||||
"identifiers": {"ror": "03yrm5c26"}
|
|
||||||
}, {
|
|
||||||
"name": "Montgomery, Bush and Madden",
|
|
||||||
"identifiers": {"ror": "03yrm5c26"}
|
|
||||||
}]
|
|
||||||
}],
|
|
||||||
"title": "A Romans story"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='function')
|
|
||||||
def singleip_record():
|
|
||||||
"""Single Ip record data as dict coming from the external world."""
|
|
||||||
return {
|
|
||||||
"access": {
|
|
||||||
"metadata": False,
|
|
||||||
"files": False,
|
|
||||||
"owned_by": [1],
|
|
||||||
"access_right": "singleip"
|
|
||||||
},
|
|
||||||
"metadata": {
|
|
||||||
"publication_date": "2020-06-01",
|
|
||||||
"resource_type": {
|
|
||||||
"type": "image",
|
|
||||||
"subtype": "image-photo"
|
|
||||||
},
|
|
||||||
# Technically not required
|
|
||||||
"creators": [{
|
|
||||||
"name": "Troy Brown",
|
|
||||||
"type": "personal"
|
|
||||||
}, {
|
|
||||||
"name": "Phillip Lester",
|
|
||||||
"type": "personal",
|
|
||||||
"identifiers": {"orcid": "0000-0002-1825-0097"},
|
|
||||||
"affiliations": [{
|
|
||||||
"name": "Carter-Morris",
|
|
||||||
"identifiers": {"ror": "03yrm5c26"}
|
|
||||||
}]
|
|
||||||
}, {
|
|
||||||
"name": "Steven Williamson",
|
|
||||||
"type": "personal",
|
|
||||||
"identifiers": {"orcid": "0000-0002-1825-0097"},
|
|
||||||
"affiliations": [{
|
|
||||||
"name": "Ritter and Sons",
|
|
||||||
"identifiers": {"ror": "03yrm5c26"}
|
|
||||||
}, {
|
|
||||||
"name": "Montgomery, Bush and Madden",
|
|
||||||
"identifiers": {"ror": "03yrm5c26"}
|
|
||||||
}]
|
|
||||||
}],
|
|
||||||
"title": "A Romans story"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Copyright (C) 2020 Mojib Wali.
|
|
||||||
#
|
|
||||||
# invenio-config-tugraz is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
||||||
# details.
|
|
||||||
|
|
||||||
"""Test Generators."""
|
|
||||||
|
|
||||||
from invenio_access.permissions import any_user
|
|
||||||
|
|
||||||
from invenio_config_tugraz.generators import RecordIp
|
|
||||||
|
|
||||||
|
|
||||||
def test_recordip(create_app, open_record, singleip_record):
|
|
||||||
"""Test Generator RecordIp."""
|
|
||||||
generator = RecordIp()
|
|
||||||
open_record = open_record
|
|
||||||
singleiprec = singleip_record
|
|
||||||
|
|
||||||
assert generator.needs(record=None) == []
|
|
||||||
assert generator.needs(record=open_record) == [any_user]
|
|
||||||
assert generator.needs(record=singleiprec) == []
|
|
||||||
|
|
||||||
assert generator.excludes(record=open_record) == []
|
|
||||||
assert generator.excludes(record=open_record) == []
|
|
||||||
|
|
||||||
assert generator.query_filter().to_dict() == {'bool': {'must_not': [{'match': {'access.access_right': 'singleip'}}]}}
|
|
||||||
33
tests/test_invenio_config_iform.py
Normal file
33
tests/test_invenio_config_iform.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2020-2024 Graz University of Technology.
|
||||||
|
#
|
||||||
|
# invenio-config-iform is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
|
# details.
|
||||||
|
|
||||||
|
"""Module tests."""
|
||||||
|
|
||||||
|
from flask import Flask
|
||||||
|
|
||||||
|
from invenio_config_iform import InvenioConfigIform
|
||||||
|
|
||||||
|
|
||||||
|
def test_version() -> None:
|
||||||
|
"""Test version import."""
|
||||||
|
from invenio_config_iform import __version__
|
||||||
|
|
||||||
|
assert __version__
|
||||||
|
|
||||||
|
|
||||||
|
def test_init() -> None:
|
||||||
|
"""Test extension initialization."""
|
||||||
|
app = Flask("testapp")
|
||||||
|
ext = InvenioConfigIform(app)
|
||||||
|
assert "invenio-config-iform" in app.extensions
|
||||||
|
|
||||||
|
app = Flask("testapp")
|
||||||
|
ext = InvenioConfigIform()
|
||||||
|
assert "invenio-config-iform" not in app.extensions
|
||||||
|
ext.init_app(app)
|
||||||
|
assert "invenio-config-iform" in app.extensions
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
#
|
|
||||||
# Copyright (C) 2020 Mojib Wali.
|
|
||||||
#
|
|
||||||
# invenio-config-tugraz is free software; you can redistribute it and/or
|
|
||||||
# modify it under the terms of the MIT License; see LICENSE file for more
|
|
||||||
# details.
|
|
||||||
|
|
||||||
"""Module tests."""
|
|
||||||
|
|
||||||
from flask import Flask
|
|
||||||
|
|
||||||
from invenio_config_tugraz import InvenioConfigTugraz
|
|
||||||
|
|
||||||
|
|
||||||
def test_version():
|
|
||||||
"""Test version import."""
|
|
||||||
from invenio_config_tugraz import __version__
|
|
||||||
|
|
||||||
assert __version__
|
|
||||||
|
|
||||||
|
|
||||||
def test_init():
|
|
||||||
"""Test extension initialization."""
|
|
||||||
app = Flask("testapp")
|
|
||||||
ext = InvenioConfigTugraz(app)
|
|
||||||
assert "invenio-config-tugraz" in app.extensions
|
|
||||||
|
|
||||||
app = Flask("testapp")
|
|
||||||
ext = InvenioConfigTugraz()
|
|
||||||
assert "invenio-config-tugraz" not in app.extensions
|
|
||||||
ext.init_app(app)
|
|
||||||
assert "invenio-config-tugraz" in app.extensions
|
|
||||||
88
tests/test_policies.py
Normal file
88
tests/test_policies.py
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright (C) 2024 Graz University of Technology.
|
||||||
|
#
|
||||||
|
# invenio-config-iform is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the MIT License; see LICENSE file for more
|
||||||
|
# details.
|
||||||
|
|
||||||
|
"""Tests for permissions-policy."""
|
||||||
|
|
||||||
|
from invenio_rdm_records.services.permissions import RDMRecordPermissionPolicy
|
||||||
|
|
||||||
|
from invenio_config_iform.permissions.policies import IformRDMRecordPermissionPolicy
|
||||||
|
|
||||||
|
ALLOWED_DIFFERENCES = {
|
||||||
|
"can_all",
|
||||||
|
"can_authenticated",
|
||||||
|
"can_create",
|
||||||
|
"can_iform_authenticated",
|
||||||
|
"can_search",
|
||||||
|
"can_search_drafts",
|
||||||
|
"can_view",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def test_policies_synced() -> None:
|
||||||
|
"""Make sure our permission-policy stays synced with invenio's."""
|
||||||
|
iform_cans = {
|
||||||
|
name: getattr(IformRDMRecordPermissionPolicy, name)
|
||||||
|
for name in dir(IformRDMRecordPermissionPolicy)
|
||||||
|
if name.startswith("can_")
|
||||||
|
}
|
||||||
|
rdm_cans = {
|
||||||
|
name: getattr(RDMRecordPermissionPolicy, name)
|
||||||
|
for name in dir(RDMRecordPermissionPolicy)
|
||||||
|
if name.startswith("can_")
|
||||||
|
}
|
||||||
|
|
||||||
|
# check whether same set of `can_<action>`s`
|
||||||
|
if extras := set(iform_cans) - set(rdm_cans) - ALLOWED_DIFFERENCES:
|
||||||
|
msg = f"""
|
||||||
|
I-Form's permission-policy has additional fields over invenio-rdm's:{extras}
|
||||||
|
if this is intentional, add to ALLOWED_DIFFERENCES in test-file
|
||||||
|
otherwise remove extraneous fields from IformRDMRecordPermissionPolicy
|
||||||
|
"""
|
||||||
|
raise KeyError(msg)
|
||||||
|
|
||||||
|
if missing := set(rdm_cans) - set(iform_cans):
|
||||||
|
msg = f"""
|
||||||
|
invenio-rdm's permission-policy has fields unhandled by I-Form's: {missing}
|
||||||
|
if this is intentional, add to ALLOWED_DIFFERENCES
|
||||||
|
otherwise set the corresponding fields in IformRDMRecordPermissionPolicy
|
||||||
|
"""
|
||||||
|
raise KeyError(msg)
|
||||||
|
|
||||||
|
# check whether same permission-generators used for same `can_<action>`
|
||||||
|
for can_name in rdm_cans.keys() & iform_cans.keys():
|
||||||
|
if can_name in ALLOWED_DIFFERENCES:
|
||||||
|
continue
|
||||||
|
|
||||||
|
iform_can = iform_cans[can_name]
|
||||||
|
rdm_can = rdm_cans[can_name]
|
||||||
|
|
||||||
|
# permission-Generators don't implement equality checks for their instances
|
||||||
|
# we can however compare which types (classes) of Generators are used...
|
||||||
|
if {type(gen) for gen in iform_can} != {type(gen) for gen in rdm_can}:
|
||||||
|
msg = f"""
|
||||||
|
permission-policy for `{can_name}` differs between I-Form and invenio-rdm
|
||||||
|
if this is intentional, add to ALLOWED_DIFFERENCES in test-file
|
||||||
|
otherwise fix IformRDMRecordPermissionPolicy
|
||||||
|
"""
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
# check whether same `NEED_LABEL_TO_ACTION`
|
||||||
|
iform_label_to_action = IformRDMRecordPermissionPolicy.NEED_LABEL_TO_ACTION
|
||||||
|
rdm_label_to_action = RDMRecordPermissionPolicy.NEED_LABEL_TO_ACTION
|
||||||
|
|
||||||
|
for label in iform_label_to_action.keys() & rdm_label_to_action.keys():
|
||||||
|
if label in ALLOWED_DIFFERENCES:
|
||||||
|
continue
|
||||||
|
|
||||||
|
if iform_label_to_action.get(label) != rdm_label_to_action.get(label):
|
||||||
|
msg = f"""
|
||||||
|
invenio-rdm's NEED_LABEL_TO_ACTION differs from I-Form's in {label}
|
||||||
|
if this is intentional, add to ALLOWED_DIFFERENCES in test-file
|
||||||
|
otherwise fix IformRDMRecordPermissionPolicy.NEED_LABEL_TO_ACTION
|
||||||
|
"""
|
||||||
|
raise ValueError(msg)
|
||||||
Reference in New Issue
Block a user