Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge The Palace Circulation v15.0.1 into E-kirjasto #14

Merged
merged 35 commits into from
Feb 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
550e043
Bump actions/cache from 3 to 4 (#1612)
dependabot[bot] Jan 17, 2024
9b1a336
Update version for webpub manifest parser. (#1614)
jonathangreen Jan 17, 2024
3c581d9
Bump tox from 4.12.0 to 4.12.1 (#1613)
dependabot[bot] Jan 17, 2024
ad2082a
Bump pyfakefs from 5.3.2 to 5.3.4 (#1619)
dependabot[bot] Jan 19, 2024
6a49bef
Bump flask from 3.0.0 to 3.0.1 (#1618)
dependabot[bot] Jan 19, 2024
7d34420
Bump types-jsonschema from 4.20.0.20240105 to 4.21.0.20240118 (#1616)
dependabot[bot] Jan 19, 2024
2b086ff
Bump types-psycopg2 from 2.9.21.20240106 to 2.9.21.20240118 (#1615)
dependabot[bot] Jan 19, 2024
24f3f2f
Search integration configured as a service (PP-93) (#1554)
jonathangreen Jan 22, 2024
3e84457
Allow ODL feeds to have open access titles (PP-847) (#1617)
jonathangreen Jan 22, 2024
cb8ec77
Borrow single item feed response respects accept header. (PP-829) (#1…
tdilauro Jan 24, 2024
bcdad08
Correct label for patron auth ID restriction type. (#1624)
tdilauro Jan 25, 2024
5f03f4e
Bump types-pillow from 10.2.0.20240111 to 10.2.0.20240125 (#1629)
dependabot[bot] Jan 26, 2024
a3dd1d4
Bump dorny/paths-filter from 2 to 3 (#1628)
dependabot[bot] Jan 26, 2024
59e4d24
Bump firebase-admin from 6.3.0 to 6.4.0 (#1625)
dependabot[bot] Jan 26, 2024
b595a04
Bump pyopenssl from 23.3.0 to 24.0.0 (#1622)
dependabot[bot] Jan 26, 2024
14faf10
Bump pydantic from 1.10.13 to 1.10.14 (#1620)
dependabot[bot] Jan 26, 2024
56ac3af
Bump pyspellchecker from 0.8.0 to 0.8.1 (#1621)
dependabot[bot] Jan 26, 2024
92f669b
Fix bug in custom list sharing log line. (#1631)
dbernstein Jan 26, 2024
f6397f4
Refactor tests for several of the admin controllers (PP-497) (#1632)
jonathangreen Jan 26, 2024
6b41551
Refactor self test controllers (PP-497) (#1630)
jonathangreen Jan 26, 2024
5e5a17c
Convert metadata services to use integration settings. (#1627)
jonathangreen Jan 26, 2024
b9858ea
Bump levenshtein from 0.23.0 to 0.24.0 (#1640)
dependabot[bot] Jan 29, 2024
e30bca7
Bump pytz from 2023.3.post1 to 2023.4 (#1639)
dependabot[bot] Jan 29, 2024
082bc77
Bump pyinstrument from 4.6.1 to 4.6.2 (#1638)
dependabot[bot] Jan 29, 2024
178f69c
Refactor controller tests to use flask_app_fixture (PP-893) (#1634)
jonathangreen Jan 29, 2024
f39f292
Remove SettingsController from IndividualAdminSettingsController (PP-…
jonathangreen Jan 30, 2024
9e1fc48
Clean up dead code in self tests (PP-893) (#1633)
jonathangreen Jan 30, 2024
24c3461
Remove SettingsController from AnnouncementSettings controller (PP-89…
jonathangreen Jan 30, 2024
409865a
Don't pre-load our configuration settings table cache anymore. (#1641)
jonathangreen Jan 30, 2024
cd2a250
Remove first book auth API (PP-903) 🔥 (#1642)
jonathangreen Jan 30, 2024
448df4f
Bump types-pytz from 2023.3.1.1 to 2023.4.0.20240130 (#1644)
dependabot[bot] Jan 30, 2024
e5a0566
Bump types-pyopenssl from 23.3.0.20240106 to 24.0.0.20240130 (#1643)
dependabot[bot] Jan 30, 2024
78faa48
Relax pre-sharing validation on list entries with no associated work.…
dbernstein Feb 5, 2024
71dd36e
Merge remote-tracking branch 'origin/main' into merge_upstream_v15.0.1
ttuovinen Feb 16, 2024
29a24b3
Merge branch 'main' into merge_upstream_v15.0.1
ttuovinen Feb 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ jobs:
POETRY_VIRTUALENVS_CREATE: false

- name: Restore pre-commit cache
uses: actions/cache@v3
uses: actions/cache@v4
with:
path: ~/.cache/pre-commit
key: pre-commit-${{ runner.os }}-py${{ env.PYTHON_VERSION }}-${{ hashFiles('.pre-commit-config.yaml') }}
Expand Down
45 changes: 10 additions & 35 deletions .github/workflows/test-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ jobs:
# using these changes throughout the rest of the build. If the base image
# build wasn't changed, we don't use it and just rely on scheduled build.
- name: Check if base image was changed by this branch
uses: dorny/paths-filter@v2
uses: dorny/paths-filter@v3
id: changes
with:
filters: |
Expand Down Expand Up @@ -273,18 +273,6 @@ jobs:
matrix:
platform: ["linux/amd64", "linux/arm64"]
image: ["scripts", "webapp"]
env:
POSTGRES_USER: palace_user
POSTGRES_PASSWORD: test
POSTGRES_DB: palace_circulation

services:
postgres:
image: postgres:12
env:
POSTGRES_USER: ${{ env.POSTGRES_USER }}
POSTGRES_PASSWORD: ${{ env.POSTGRES_PASSWORD }}
POSTGRES_DB: ${{ env.POSTGRES_DB }}

steps:
- uses: actions/checkout@v4
Expand All @@ -301,36 +289,23 @@ jobs:
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Build image
uses: docker/build-push-action@v5
with:
context: .
file: ./docker/Dockerfile
tags: test_image
load: true
target: ${{ matrix.image }}
cache-from: type=gha,scope=buildkit-${{ github.run_id }}
platforms: ${{ matrix.platform }}
build-args: |
BASE_IMAGE=${{ needs.docker-image-build.outputs.baseimage }}

- name: Start container
run: >
docker run --rm --name test_container -d --platform ${{ matrix.platform }}
--network ${{job.services.postgres.network}}
-e SIMPLIFIED_PRODUCTION_DATABASE="postgresql://${{ env.POSTGRES_USER }}:${{ env.POSTGRES_PASSWORD }}@postgres:5432/${{ env.POSTGRES_DB }}"
test_image
- name: Build & Start container
run: docker compose up -d --build ${{ matrix.image }}
env:
BUILD_PLATFORM: ${{ matrix.platform }}
BUILD_CACHE_FROM: type=gha,scope=buildkit-${{ github.run_id }}
BUILD_BASE_IMAGE: ${{ needs.docker-image-build.outputs.baseimage }}

- name: Run tests
run: ./docker/ci/test_${{ matrix.image }}.sh test_container
run: ./docker/ci/test_${{ matrix.image }}.sh ${{ matrix.image }}

- name: Output logs
if: failure()
run: docker logs test_container
run: docker logs circulation-${{ matrix.image }}-1

- name: Stop container
if: always()
run: docker stop test_container
run: docker compose down

docker-image-push:
if: false # Disable temporarily
Expand Down
20 changes: 18 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ Elasticsearch is no longer supported.
We recommend that you run OpenSearch with docker using the following docker commands:

```sh
docker run --name opensearch -d --rm -p 9006:9200 -e "discovery.type=single-node" -e "plugins.security.disabled=true" "opensearchproject/opensearch:1"
docker run --name opensearch -d --rm -p 9200:9200 -e "discovery.type=single-node" -e "plugins.security.disabled=true" "opensearchproject/opensearch:1"
docker exec opensearch opensearch-plugin -s install analysis-icu
docker restart opensearch
```
Expand Down Expand Up @@ -165,6 +165,22 @@ To let the application know which database to use, set the `SIMPLIFIED_PRODUCTIO
export SIMPLIFIED_PRODUCTION_DATABASE="postgresql://palace:test@localhost:5432/circ"
```

#### Opensearch

To let the application know which Opensearch instance to use, you can set the following environment variables:

- `PALACE_SEARCH_URL`: The url of the Opensearch instance (**required**).
- `PALACE_SEARCH_INDEX_PREFIX`: The prefix to use for the Opensearch indices. The default is `circulation-works`.
This is useful if you want to use the same Opensearch instance for multiple CM (optional).
- `PALACE_SEARCH_TIMEOUT`: The timeout in seconds to use when connecting to the Opensearch instance. The default is `20`
(optional).
- `PALACE_SEARCH_MAXSIZE`: The maximum size of the connection pool to use when connecting to the Opensearch instance.
(optional).

```sh
export PALACE_SEARCH_URL="http://localhost:9200"
```

#### Storage Service

The application optionally uses a s3 compatible storage service to store files. To configure the application to use
Expand Down Expand Up @@ -656,7 +672,7 @@ If you already have elastic search or postgres running locally, you can run them
following environment variables:

- `SIMPLIFIED_TEST_DATABASE`
- `SIMPLIFIED_TEST_OPENSEARCH`
- `PALACE_TEST_SEARCH_URL`

Make sure the ports and usernames are updated to reflect the local configuration.

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
"""migrate metadata services

Revision ID: 993729d4bf97
Revises: 735bf6ced8b9
Create Date: 2024-01-24 23:51:13.464107+00:00

"""
from alembic import op
from api.integration.registry.metadata import MetadataRegistry
from core.integration.base import HasLibraryIntegrationConfiguration
from core.migration.migrate_external_integration import (
_migrate_external_integration,
_migrate_library_settings,
get_configuration_settings,
get_integrations,
get_library_for_integration,
)
from core.migration.util import pg_update_enum

# revision identifiers, used by Alembic.
revision = "993729d4bf97"
down_revision = "735bf6ced8b9"
branch_labels = None
depends_on = None

METADATA_GOAL = "METADATA_GOAL"
old_goals_enum = ["PATRON_AUTH_GOAL", "LICENSE_GOAL", "DISCOVERY_GOAL", "CATALOG_GOAL"]
new_goals_enum = old_goals_enum + [METADATA_GOAL]


def upgrade() -> None:
# Add the new enum value to our goals enum
pg_update_enum(
op,
"integration_configurations",
"goal",
"goals",
old_goals_enum,
new_goals_enum,
)

# Migrate the existing metadata services to integration configurations
connection = op.get_bind()
registry = MetadataRegistry()
integrations = get_integrations(connection, "metadata")
for integration in integrations:
_id, protocol, name = integration
protocol_class = registry[protocol]

(
settings_dict,
libraries_settings,
self_test_result,
) = get_configuration_settings(connection, integration)

updated_protocol = registry.get_protocol(protocol_class)
if updated_protocol is None:
raise RuntimeError(f"Unknown metadata service '{protocol}'")
integration_configuration_id = _migrate_external_integration(
connection,
integration.name,
updated_protocol,
protocol_class,
METADATA_GOAL,
settings_dict,
self_test_result,
)

integration_libraries = get_library_for_integration(connection, _id)
for library in integration_libraries:
if issubclass(protocol_class, HasLibraryIntegrationConfiguration):
_migrate_library_settings(
connection,
integration_configuration_id,
library.library_id,
libraries_settings[library.library_id],
protocol_class,
)
else:
raise RuntimeError(
f"Protocol not expected to have library settings '{protocol}'"
)


def downgrade() -> None:
# Remove the new enum value from our goals enum.
pg_update_enum(
op,
"integration_configurations",
"goal",
"goals",
new_goals_enum,
old_goals_enum,
)
2 changes: 1 addition & 1 deletion api/admin/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ class OperationalMode(str, Enum):
class Configuration(LoggerMixin):
APP_NAME = "E-kirjasto Collection Manager"
PACKAGE_NAME = "@natlibfi/ekirjasto-circulation-admin"
PACKAGE_VERSION = "0.0.1"
PACKAGE_VERSION = "0.0.1-post.8"

STATIC_ASSETS = {
"admin_js": "circulation-admin.js",
Expand Down
36 changes: 2 additions & 34 deletions api/admin/controller/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ def setup_admin_controllers(manager: CirculationManager):
from api.admin.controller.admin_search import AdminSearchController
from api.admin.controller.announcement_service import AnnouncementSettings
from api.admin.controller.catalog_services import CatalogServicesController
from api.admin.controller.collection_self_tests import CollectionSelfTestsController
from api.admin.controller.collection_settings import CollectionSettingsController
from api.admin.controller.custom_lists import CustomListsController
from api.admin.controller.dashboard import DashboardController
Expand All @@ -27,26 +26,11 @@ def setup_admin_controllers(manager: CirculationManager):
)
from api.admin.controller.lanes import LanesController
from api.admin.controller.library_settings import LibrarySettingsController
from api.admin.controller.metadata_service_self_tests import (
MetadataServiceSelfTestsController,
)
from api.admin.controller.metadata_services import MetadataServicesController
from api.admin.controller.patron import PatronController
from api.admin.controller.patron_auth_service_self_tests import (
PatronAuthServiceSelfTestsController,
)
from api.admin.controller.patron_auth_services import PatronAuthServicesController
from api.admin.controller.reset_password import ResetPasswordController
from api.admin.controller.search_service_self_tests import (
SearchServiceSelfTestsController,
)
from api.admin.controller.self_tests import SelfTestsController
from api.admin.controller.settings import SettingsController
from api.admin.controller.sign_in import SignInController
from api.admin.controller.sitewide_services import (
SearchServicesController,
SitewideServicesController,
)
from api.admin.controller.sitewide_settings import (
SitewideConfigurationSettingsController,
)
Expand All @@ -63,41 +47,25 @@ def setup_admin_controllers(manager: CirculationManager):
manager.admin_custom_lists_controller = CustomListsController(manager)
manager.admin_lanes_controller = LanesController(manager)
manager.admin_dashboard_controller = DashboardController(manager)
manager.admin_settings_controller = SettingsController(manager)
manager.admin_patron_controller = PatronController(manager)
manager.admin_self_tests_controller = SelfTestsController(manager)
manager.admin_discovery_services_controller = DiscoveryServicesController(manager)
manager.admin_discovery_service_library_registrations_controller = (
DiscoveryServiceLibraryRegistrationsController(manager)
)
manager.admin_metadata_services_controller = MetadataServicesController(manager)
manager.admin_metadata_service_self_tests_controller = (
MetadataServiceSelfTestsController(manager)
)
manager.admin_patron_auth_services_controller = PatronAuthServicesController(
manager
)

manager.admin_patron_auth_service_self_tests_controller = (
PatronAuthServiceSelfTestsController(manager._db)
)
manager.admin_collection_settings_controller = CollectionSettingsController(manager)
manager.admin_collection_self_tests_controller = CollectionSelfTestsController(
manager._db
)
manager.admin_sitewide_configuration_settings_controller = (
SitewideConfigurationSettingsController(manager)
)
manager.admin_library_settings_controller = LibrarySettingsController(manager)
manager.admin_individual_admin_settings_controller = (
IndividualAdminSettingsController(manager)
)
manager.admin_sitewide_services_controller = SitewideServicesController(manager)
manager.admin_search_service_self_tests_controller = (
SearchServiceSelfTestsController(manager)
IndividualAdminSettingsController(manager._db)
)
manager.admin_search_services_controller = SearchServicesController(manager)
manager.admin_catalog_services_controller = CatalogServicesController(manager)
manager.admin_announcement_service = AnnouncementSettings(manager)
manager.admin_announcement_service = AnnouncementSettings(manager._db)
manager.admin_search_controller = AdminSearchController(manager)
manager.admin_quicksight_controller = QuickSightController(manager)
7 changes: 5 additions & 2 deletions api/admin/controller/announcement_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,21 @@
from typing import Any

import flask
from sqlalchemy.orm import Session

from api.admin.announcement_list_validator import AnnouncementListValidator
from api.admin.controller.settings import SettingsController
from api.config import Configuration
from core.model.announcements import Announcement
from core.problem_details import INVALID_INPUT
from core.util.problem_detail import ProblemDetail, ProblemError


class AnnouncementSettings(SettingsController):
class AnnouncementSettings:
"""Controller that manages global announcements for all libraries"""

def __init__(self, db: Session) -> None:
self._db = db

def _action(self) -> Callable:
method = flask.request.method.lower()
return getattr(self, method)
Expand Down
41 changes: 0 additions & 41 deletions api/admin/controller/collection_self_tests.py

This file was deleted.

Loading