Skip to content

Commit

Permalink
Merge branch 'main' into feature/remove-integration-links
Browse files Browse the repository at this point in the history
  • Loading branch information
jonathangreen committed Oct 5, 2023
2 parents 1563020 + 5484028 commit 07834a2
Show file tree
Hide file tree
Showing 248 changed files with 6,473 additions and 11,609 deletions.
17 changes: 11 additions & 6 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,20 @@ repos:
- id: mixed-line-ending

- repo: https://github.com/asottile/pyupgrade
rev: v3.3.2
rev: v3.14.0
hooks:
- id: pyupgrade
args:
- --py38-plus
- --keep-runtime-typing

- repo: https://github.com/MarcoGorelli/absolufy-imports
rev: v0.3.0
hooks:
- id: absolufy-imports

- repo: https://github.com/myint/autoflake
rev: v2.1.1
rev: v2.2.1
hooks:
- id: autoflake
args:
Expand All @@ -34,7 +39,7 @@ repos:
- --ignore-init-module-imports

- repo: https://github.com/psf/black
rev: 22.10.0
rev: 23.9.1
hooks:
- id: black
name: Run black
Expand All @@ -46,20 +51,20 @@ repos:
name: Run isort

- repo: https://github.com/sirosen/check-jsonschema
rev: 0.22.0
rev: 0.27.0
hooks:
- id: check-github-workflows
- id: check-github-actions

- repo: https://github.com/pappasam/toml-sort
rev: v0.23.0
rev: v0.23.1
hooks:
- id: toml-sort
args: []
files: pyproject.toml

- repo: https://github.com/jackdewinter/pymarkdown
rev: v0.9.9
rev: v0.9.13.4
hooks:
- id: pymarkdown
args:
Expand Down
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,29 @@ a storage service, you can set the following environment variables:
- `{key}`: The key of the file.
- `{region}`: The region of the storage service.

#### Logging

The application uses the [Python logging](https://docs.python.org/3/library/logging.html) module for logging. Optionally
logs can be configured to be sent to AWS CloudWatch logs. The following environment variables can be used to configure
the logging:

- `PALACE_LOG_LEVEL`: The log level to use for the application. The default is `INFO`.
- `PALACE_LOG_VERBOSE_LEVEL`: The log level to use for particularly verbose loggers. Keeping these loggers at a
higher log level by default makes it easier to troubleshoot issues. The default is `WARNING`.
- `PALACE_LOG_CLOUDWATCH_ENABLED`: Enable / disable sending logs to CloudWatch. The default is `false`.
- `PALACE_LOG_CLOUDWATCH_REGION`: The AWS region of the CloudWatch logs. This must be set if using CloudWatch logs.
- `PALACE_LOG_CLOUDWATCH_GROUP`: The name of the CloudWatch log group to send logs to. Default is `palace`.
- `PALACE_LOG_CLOUDWATCH_STREAM`: The name of the CloudWatch log stream to send logs to. Default is
`{machine_name}/{program_name}/{logger_name}/{process_id}`. See
[watchtower docs](https://github.com/kislyuk/watchtower#log-stream-naming) for details.
- `PALACE_LOG_CLOUDWATCH_INTERVAL`: The interval in seconds to send logs to CloudWatch. Default is `60`.
- `PALACE_LOG_CLOUDWATCH_CREATE_GROUP`: Whether to create the log group if it does not exist. Default is `true`.
- `PALACE_LOG_CLOUDWATCH_ACCESS_KEY`: The access key to use when sending logs to CloudWatch. This is optional.
- If this key is set it will be passed to boto3 when connecting to CloudWatch.
- If it is not set boto3 will attempt to find credentials as outlined in their
[documentation](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html#configuring-credentials).
- `PALACE_LOG_CLOUDWATCH_SECRET_KEY`: The secret key to use when sending logs to CloudWatch. This is optional.

#### Patron `Basic Token` authentication

Enables/disables patron "basic token" authentication through setting the designated environment variable to any
Expand Down
1 change: 0 additions & 1 deletion api/admin/announcement_list_validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@


class AnnouncementListValidator:

DATE_FORMAT = "%Y-%m-%d"

def __init__(
Expand Down
11 changes: 3 additions & 8 deletions api/admin/config.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import logging
import os
from enum import Enum
from typing import Optional
Expand All @@ -7,18 +6,18 @@
from requests import RequestException

from core.util.http import HTTP, RequestNetworkException
from core.util.log import LoggerMixin


class OperationalMode(str, Enum):
production = "production"
development = "development"


class Configuration:

class Configuration(LoggerMixin):
APP_NAME = "Palace Collection Manager"
PACKAGE_NAME = "@thepalaceproject/circulation-admin"
PACKAGE_VERSION = "1.9.0"
PACKAGE_VERSION = "1.10.0"

STATIC_ASSETS = {
"admin_js": "circulation-admin.js",
Expand Down Expand Up @@ -63,10 +62,6 @@ def operational_mode(cls) -> OperationalMode:
else OperationalMode.production
)

@classmethod
def logger(cls) -> logging.Logger:
return logging.getLogger(f"{cls.__module__}.{cls.__name__}")

@classmethod
def package_name(cls) -> str:
"""Get the effective package name.
Expand Down
2 changes: 0 additions & 2 deletions api/admin/controller/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ def setup_admin_controllers(manager: CirculationManager):
from api.admin.controller.settings import SettingsController
from api.admin.controller.sign_in import SignInController
from api.admin.controller.sitewide_services import (
LoggingServicesController,
SearchServicesController,
SitewideServicesController,
)
Expand Down Expand Up @@ -94,7 +93,6 @@ def setup_admin_controllers(manager: CirculationManager):
IndividualAdminSettingsController(manager)
)
manager.admin_sitewide_services_controller = SitewideServicesController(manager)
manager.admin_logging_services_controller = LoggingServicesController(manager)
manager.admin_search_service_self_tests_controller = (
SearchServiceSelfTestsController(manager)
)
Expand Down
5 changes: 2 additions & 3 deletions api/admin/controller/announcement_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,13 @@

import flask

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

from ..announcement_list_validator import AnnouncementListValidator
from .settings import SettingsController


class AnnouncementSettings(SettingsController):
"""Controller that manages global announcements for all libraries"""
Expand Down
3 changes: 0 additions & 3 deletions api/admin/controller/collection_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,6 @@ def process_get(self):
continue

collection_dict = self.collection_to_dict(collection_object)
[protocol] = [
p for p in protocols if p["name"] == collection_object.protocol
]
if collection_object.integration_configuration:
libraries = self.load_libraries(collection_object, user)
collection_dict["libraries"] = libraries
Expand Down
4 changes: 2 additions & 2 deletions api/admin/controller/individual_admin_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ def append_role(roles, role):
roles = []
show_admin = True
for role in admin.roles:

# System admin sees all
if highest_role.role == AdminRole.SYSTEM_ADMIN:
append_role(roles, role)
Expand Down Expand Up @@ -318,7 +317,8 @@ def look_up_library_for_role(self, role):

def handle_roles(self, admin, roles, settingUp):
"""Compare the admin's existing set of roles against the roles submitted in the form, and,
unless there's a problem with the roles or the permissions, modify the admin's roles accordingly"""
unless there's a problem with the roles or the permissions, modify the admin's roles accordingly
"""

# User = person submitting the form; admin = person who the form is about

Expand Down
5 changes: 2 additions & 3 deletions api/admin/controller/integration_settings.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import json
import logging
from abc import ABC, abstractmethod
from typing import Any, Dict, Generic, List, NamedTuple, Optional, Type, TypeVar

Expand Down Expand Up @@ -28,6 +27,7 @@
)
from core.problem_details import INTERNAL_SERVER_ERROR, INVALID_INPUT
from core.util.cache import memoize
from core.util.log import LoggerMixin
from core.util.problem_detail import ProblemError

T = TypeVar("T", bound=HasIntegrationConfiguration)
Expand All @@ -44,15 +44,14 @@ class ChangedLibrariesTuple(NamedTuple):
removed: List[IntegrationLibraryConfiguration]


class IntegrationSettingsController(ABC, Generic[T]):
class IntegrationSettingsController(ABC, Generic[T], LoggerMixin):
def __init__(
self,
manager: CirculationManager,
registry: Optional[IntegrationRegistry[T]] = None,
):
self._db = manager._db
self.registry = registry or self.default_registry()
self.log = logging.getLogger(f"{self.__module__}.{self.__class__.__name__}")

@abstractmethod
def default_registry(self) -> IntegrationRegistry[T]:
Expand Down
11 changes: 5 additions & 6 deletions api/admin/controller/library_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,12 @@
from PIL.Image import Resampling
from werkzeug.datastructures import FileStorage

from api.admin.announcement_list_validator import AnnouncementListValidator
from api.admin.controller.base import AdminPermissionsControllerMixin
from api.admin.form_data import ProcessFormData
from api.admin.problem_details import *
from api.config import Configuration
from api.controller import CirculationManager
from api.lanes import create_default_lanes
from core.configuration.library import LibrarySettings
from core.model import (
Expand All @@ -29,12 +34,6 @@
from core.model.library import LibraryLogo
from core.util.problem_detail import ProblemDetail, ProblemError

from ...config import Configuration
from ...controller import CirculationManager
from ..announcement_list_validator import AnnouncementListValidator
from ..form_data import ProcessFormData
from .base import AdminPermissionsControllerMixin


class LibrarySettingsController(AdminPermissionsControllerMixin):
def __init__(self, manager: CirculationManager):
Expand Down
4 changes: 2 additions & 2 deletions api/admin/controller/sign_in.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

import logging
from typing import Tuple
from urllib.parse import urlsplit

import flask
from flask import Response, redirect, url_for
from flask_babel import lazy_gettext as _
from werkzeug import Response as WerkzeugResponse
from werkzeug.urls import BaseURL, url_parse

from api.admin.config import Configuration as AdminClientConfig
from api.admin.controller.base import AdminController
Expand Down Expand Up @@ -153,7 +153,7 @@ def _check_redirect(target: str) -> Tuple[bool, str]:
we extract the URL path and forbid redirecting to external
hosts.
"""
redirect_url: BaseURL = url_parse(target)
redirect_url = urlsplit(target)

# If the redirect isn't asking for a particular host, then it's safe.
if redirect_url.netloc in (None, ""):
Expand Down
17 changes: 0 additions & 17 deletions api/admin/controller/sitewide_services.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
UNKNOWN_PROTOCOL,
)
from core.external_search import ExternalSearchIndex
from core.log import CloudwatchLogs, SysLogger
from core.model import ExternalIntegration, get_one_or_create
from core.util.problem_detail import ProblemDetail

Expand Down Expand Up @@ -108,22 +107,6 @@ def validate_form_fields(self, protocols, **fields):
return UNKNOWN_PROTOCOL


class LoggingServicesController(SitewideServicesController):
def process_services(self):
detail = _(
"You tried to create a new logging service, but a logging service is already configured."
)
return self._manage_sitewide_service(
ExternalIntegration.LOGGING_GOAL,
[SysLogger, CloudwatchLogs],
"logging_services",
detail,
)

def process_delete(self, service_id):
return self._delete_integration(service_id, ExternalIntegration.LOGGING_GOAL)


class SearchServicesController(SitewideServicesController):
def __init__(self, manager):
super().__init__(manager)
Expand Down
1 change: 0 additions & 1 deletion api/admin/controller/sitewide_settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ def process_delete(self, key):
return Response(str(_("Deleted")), 200)

def validate_form_fields(self, setting, fields):

MISSING_FIELD_MESSAGES = dict(
key=MISSING_SITEWIDE_SETTING_KEY, value=MISSING_SITEWIDE_SETTING_VALUE
)
Expand Down
9 changes: 6 additions & 3 deletions api/admin/controller/view.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
from __future__ import annotations

from urllib.parse import quote_plus

import flask
from flask import Response, redirect, url_for
from flask_babel import lazy_gettext as _
from werkzeug.urls import url_quote_plus

from api.admin.config import Configuration as AdminClientConfig
from api.admin.controller.base import AdminController
Expand All @@ -25,10 +26,12 @@ def __call__(self, collection, book, path=None):
redirect_url = flask.request.url
if collection:
redirect_url = redirect_url.replace(
collection, url_quote_plus(collection)
collection, quote_plus(collection, safe="()")
)
if book:
redirect_url = redirect_url.replace(book, url_quote_plus(book))
redirect_url = redirect_url.replace(
book, quote_plus(book, safe="()")
)
return redirect(
url_for("admin_sign_in", redirect=redirect_url, _external=True)
)
Expand Down
6 changes: 2 additions & 4 deletions api/admin/controller/work_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
from flask import Response
from flask_babel import lazy_gettext as _

from api.admin.controller.base import AdminPermissionsControllerMixin
from api.admin.problem_details import *
from api.controller import CirculationManagerController
from core.classifier import NO_NUMBER, NO_VALUE, SimplifiedGenreClassifier, genres
from core.feed.acquisition import OPDSAcquisitionFeed
from core.feed.annotator.admin import AdminAnnotator
Expand All @@ -29,12 +31,8 @@
from core.util.datetime_helpers import strptime_utc, utc_now
from core.util.problem_detail import ProblemDetail

from ...controller import CirculationManagerController
from .base import AdminPermissionsControllerMixin


class WorkController(CirculationManagerController, AdminPermissionsControllerMixin):

STAFF_WEIGHT = 1000

def details(self, identifier_type, identifier):
Expand Down
1 change: 0 additions & 1 deletion api/admin/opds.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ def __init__(self, circulation, library, test_mode=False):
def annotate_work_entry(
self, work, active_license_pool, edition, identifier, feed, entry
):

super().annotate_work_entry(
work, active_license_pool, edition, identifier, feed, entry
)
Expand Down
Loading

0 comments on commit 07834a2

Please sign in to comment.