Skip to content

Commit

Permalink
Merge branch 'main' into 459-systemcard-pilot-ready-maken
Browse files Browse the repository at this point in the history
Signed-off-by: Ravi Meijer <ravi.meijer@rijksoverheid.nl>
  • Loading branch information
ravimeijerrig authored Jan 28, 2025
2 parents b1459d0 + f641ad5 commit 10ec486
Show file tree
Hide file tree
Showing 102 changed files with 2,430 additions and 851 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ jobs:

- name: Upload playwright tracing
if: failure()
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4.6.0
with:
name: playwright-${{ github.sha }}
path: test-results/
Expand All @@ -173,7 +173,7 @@ jobs:

- name: Upload code coverage report
if: matrix.python-version == '3.12'
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4.6.0
with:
name: codecoverage-${{ github.sha }}
path: htmlcov/
Expand Down Expand Up @@ -295,7 +295,7 @@ jobs:
TRIVY_PASSWORD: ${{ secrets.GITHUB_TOKEN }}

- name: Upload SBOM & License
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v4.6.0
with:
name: sbom-licence-${{ github.sha }}.json
path: |
Expand Down
8 changes: 3 additions & 5 deletions amt/api/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,20 @@

from fastapi import HTTPException, Request

from amt.api.utils import SafeDict
from amt.core.exceptions import AMTPermissionDenied


def add_permissions(permissions: dict[str, list[str]]) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
def permission(permissions: dict[str, list[str]]) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
@wraps(func)
async def wrapper(*args: Any, **kwargs: Any) -> Any: # noqa: ANN401
request = kwargs.get("request")
organization_id = kwargs.get("organization_id")
algoritme_id = kwargs.get("algoritme_id")
if not isinstance(request, Request): # todo: change exception to custom exception
raise HTTPException(status_code=400, detail="Request object is missing")

for permission, verbs in permissions.items():
permission = permission.format(organization_id=organization_id)
permission = permission.format(algoritme_id=algoritme_id)
permission = permission.format_map(SafeDict(kwargs))
request_permissions: dict[str, list[str]] = (
request.state.permissions if hasattr(request.state, "permissions") else {}
)
Expand Down
16 changes: 16 additions & 0 deletions amt/api/deps.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,21 @@ def instance(obj: Class, type_string: str) -> bool:
raise TypeError("Unsupported type: " + type_string)


def hasattr_jinja(obj: object, attributes: str) -> bool:
"""
Convenience method that checks whether an object has the given attributes.
:param obj: the object to check
:param attributes: the attributes, seperated by dots, like field1.field2.field3
:return: True if the object has the given attribute and its value is not None, False otherwise
"""
for attribute in attributes.split("."):
if hasattr(obj, attribute) and getattr(obj, attribute) is not None:
obj = getattr(obj, attribute)
else:
return False
return True


templates = LocaleJinja2Templates(
directory="amt/site/templates/", context_processors=[custom_context_processor], undefined=get_undefined_behaviour()
)
Expand All @@ -153,5 +168,6 @@ def instance(obj: Class, type_string: str) -> bool:
templates.env.globals.update(is_editable_resource=is_editable_resource) # pyright: ignore [reportUnknownMemberType]
templates.env.globals.update(replace_digits_in_brackets=replace_digits_in_brackets) # pyright: ignore [reportUnknownMemberType]
templates.env.globals.update(permission=permission) # pyright: ignore [reportUnknownMemberType]
templates.env.globals.update(hasattr=hasattr_jinja) # pyright: ignore [reportUnknownMemberType]
templates.env.tests["permission"] = permission # pyright: ignore [reportUnknownMemberType]
templates.env.add_extension("jinja2_base64_filters.Base64Filters") # pyright: ignore [reportUnknownMemberType]
6 changes: 1 addition & 5 deletions amt/api/editable.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from amt.api.editable_validators import EditableValidator, EditableValidatorMinMaxLength, EditableValidatorSlug
from amt.api.lifecycles import get_localized_lifecycles
from amt.api.routes.shared import UpdateFieldModel, nested_value
from amt.api.utils import SafeDict
from amt.core.exceptions import AMTNotFound
from amt.models import Algorithm, Organization
from amt.models.base import Base
Expand Down Expand Up @@ -198,11 +199,6 @@ def __iter__(self) -> Generator[tuple[str, Any], Any, Any]:
editables = Editables()


class SafeDict(dict[str, str | int]):
def __missing__(self, key: str) -> str:
return "{" + key + "}"


class EditModes(StrEnum):
EDIT = "EDIT"
VIEW = "VIEW"
Expand Down
19 changes: 14 additions & 5 deletions amt/api/forms/measure.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,19 @@
from collections.abc import Sequence
from enum import StrEnum
from gettext import NullTranslations

from amt.models import User
from amt.schema.webform import WebForm, WebFormField, WebFormFieldType, WebFormOption, WebFormTextCloneableField


class MeasureStatusOptions(StrEnum):
TODO = "to do"
IN_PROGRESS = "in progress"
IN_REVIEW = "in review"
DONE = "done"
NOT_IMPLEMENTED = "not implemented"


async def get_measure_form(
id: str,
current_values: dict[str, str | list[str] | list[tuple[str, str]]],
Expand Down Expand Up @@ -47,11 +56,11 @@ async def get_measure_form(
name="measure_state",
label=_("Status"),
options=[
WebFormOption(value="to do", display_value="to do"),
WebFormOption(value="in progress", display_value="in progress"),
WebFormOption(value="in review", display_value="in review"),
WebFormOption(value="done", display_value="done"),
WebFormOption(value="not implemented", display_value="not implemented"),
WebFormOption(value=MeasureStatusOptions.TODO, display_value=_("To do")),
WebFormOption(value=MeasureStatusOptions.IN_PROGRESS, display_value=_("In progress")),
WebFormOption(value=MeasureStatusOptions.IN_REVIEW, display_value=_("In review")),
WebFormOption(value=MeasureStatusOptions.DONE, display_value=_("Done")),
WebFormOption(value=MeasureStatusOptions.NOT_IMPLEMENTED, display_value=_("Not implemented")),
],
default_value=current_values.get("measure_state"),
group="1",
Expand Down
Loading

0 comments on commit 10ec486

Please sign in to comment.