diff --git a/README.md b/README.md index dbb7ddf..dd451fd 100644 --- a/README.md +++ b/README.md @@ -158,6 +158,15 @@ method's name in the UI and defaults to `OIDC`. **NOTE:** Currently, only Keycloak has been tested with this login method. +### Volumes + +Both images declare `/srv/run` to be a volume. It's intended to keep the +service's runtime data, including but not limited to PID files, UNIX sockets +etc. It's recommended to persist this volume. + +Additionally, the `deployment` image declares `/srv/uploads` to be a volume. +It's recommeded to persist this volume. + ## Author _HotPocket_ is developed by [BTHLabs](https://www.bthlabs.pl/). diff --git a/services/backend/Dockerfile b/services/backend/Dockerfile index 70b6fea..f8bfde1 100644 --- a/services/backend/Dockerfile +++ b/services/backend/Dockerfile @@ -27,7 +27,7 @@ COPY --chown=$APP_USER_UID:$APP_USER_GID packages/common/ /srv/packages/common/ COPY --chown=$APP_USER_UID:$APP_USER_GID packages/soa/ /srv/packages/soa/ RUN poetry install --only main,deployment && \ - minify -i --css-precision 0 --js-precision 0 --js-version 2022 hotpocket_backend/apps/ui/static/ui/css/hotpocket-backend*.css hotpocket_backend/apps/ui/static/ui/js/hotpocket*.js && \ + minify -i --css-precision 0 --js-precision 0 --js-version 2022 hotpocket_backend/apps/ui/static/ui/css/hotpocket-backend*.css hotpocket_backend/apps/ui/static/ui/js/hotpocket-backend*.js && \ ./manage.py collectstatic --settings hotpocket_backend.settings.deployment.build --noinput && \ find hotpocket_backend/static/ -name "*.map*" -delete && \ rm -f hotpocket_backend/settings/deployment/build.py && \ diff --git a/services/backend/hotpocket_backend/apps/accounts/admin/__init__.py b/services/backend/hotpocket_backend/apps/accounts/admin/__init__.py index 3dd6ff3..c773b8e 100644 --- a/services/backend/hotpocket_backend/apps/accounts/admin/__init__.py +++ b/services/backend/hotpocket_backend/apps/accounts/admin/__init__.py @@ -1,2 +1,3 @@ from .access_token import AccessToken # noqa: F401 from .account import AccountAdmin # noqa: F401 +from .auth_key import AuthKey # noqa: F401 diff --git a/services/backend/hotpocket_backend/apps/accounts/admin/access_token.py b/services/backend/hotpocket_backend/apps/accounts/admin/access_token.py index a06ee38..95c3b02 100644 --- a/services/backend/hotpocket_backend/apps/accounts/admin/access_token.py +++ b/services/backend/hotpocket_backend/apps/accounts/admin/access_token.py @@ -2,16 +2,41 @@ from __future__ import annotations from django.contrib import admin +from django.utils.translation import gettext_lazy as _ from hotpocket_backend.apps.accounts.models import AccessToken class AccessTokenAdmin(admin.ModelAdmin): - list_display = ('pk', 'account_uuid', 'origin', 'created_at', 'is_active') + list_display = ( + 'pk', 'account_uuid', 'origin', 'created_at', 'render_is_active', + ) search_fields = ('pk', 'account_uuid', 'key', 'origin') + readonly_fields = ( + 'pk', + 'account_uuid', + 'key', + 'origin', + 'meta', + 'created_at', + 'deleted_at', + ) + ordering = ['-created_at'] + + def has_change_permission(self, request, obj=None): + return False def has_delete_permission(self, request, obj=None): return request.user.is_superuser + @admin.display( + description=_('Is Active?'), boolean=True, ordering='-deleted_at', + ) + def render_is_active(self, obj: AccessToken | None = None) -> bool | None: + if obj is None: + return None + + return obj.is_active + admin.site.register(AccessToken, AccessTokenAdmin) diff --git a/services/backend/hotpocket_backend/apps/accounts/admin/account.py b/services/backend/hotpocket_backend/apps/accounts/admin/account.py index 5babe14..6212c1e 100644 --- a/services/backend/hotpocket_backend/apps/accounts/admin/account.py +++ b/services/backend/hotpocket_backend/apps/accounts/admin/account.py @@ -3,15 +3,26 @@ from __future__ import annotations from django.contrib import admin from django.contrib.auth.admin import UserAdmin +from django.utils.translation import gettext_lazy as _ from hotpocket_backend.apps.accounts.models import Account class AccountAdmin(UserAdmin): - list_display = (*UserAdmin.list_display, 'is_active') + list_display = (*UserAdmin.list_display, 'render_is_active') + ordering = ['username'] def has_delete_permission(self, request, obj=None): return request.user.is_superuser + @admin.display( + description=_('Is Active?'), boolean=True, ordering='-is_active', + ) + def render_is_active(self, obj: Account | None = None) -> bool | None: + if obj is None: + return None + + return obj.is_active + admin.site.register(Account, AccountAdmin) diff --git a/services/backend/hotpocket_backend/apps/accounts/admin/auth_key.py b/services/backend/hotpocket_backend/apps/accounts/admin/auth_key.py new file mode 100644 index 0000000..873e1aa --- /dev/null +++ b/services/backend/hotpocket_backend/apps/accounts/admin/auth_key.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +from __future__ import annotations + +from django.contrib import admin +from django.utils.translation import gettext_lazy as _ + +from hotpocket_backend.apps.accounts.models import AuthKey + + +class AuthKeyAdmin(admin.ModelAdmin): + list_display = ( + 'pk', 'account_uuid', 'key', 'created_at', 'consumed_at', 'render_is_active', + ) + search_fields = ('pk', 'account_uuid', 'key') + readonly_fields = ( + 'pk', + 'account_uuid', + 'key', + 'consumed_at', + 'created_at', + 'deleted_at', + ) + ordering = ['-created_at'] + + def has_change_permission(self, request, obj=None): + return False + + def has_delete_permission(self, request, obj=None): + return request.user.is_superuser + + @admin.display( + description=_('Is Active?'), boolean=True, ordering='-deleted_at', + ) + def render_is_active(self, obj: AuthKey | None = None) -> bool | None: + if obj is None: + return None + + return obj.is_active + + +admin.site.register(AuthKey, AuthKeyAdmin) diff --git a/services/backend/hotpocket_backend/apps/saves/admin/__init__.py b/services/backend/hotpocket_backend/apps/saves/admin/__init__.py index acde557..30120fc 100644 --- a/services/backend/hotpocket_backend/apps/saves/admin/__init__.py +++ b/services/backend/hotpocket_backend/apps/saves/admin/__init__.py @@ -1 +1,2 @@ +from . import association # noqa: F401 from . import save # noqa: F401 diff --git a/services/backend/hotpocket_backend/apps/saves/admin/association.py b/services/backend/hotpocket_backend/apps/saves/admin/association.py new file mode 100644 index 0000000..b58285d --- /dev/null +++ b/services/backend/hotpocket_backend/apps/saves/admin/association.py @@ -0,0 +1,51 @@ +# -*- coding: utf-8 -*- +from __future__ import annotations + +from django.contrib import admin +from django.utils.translation import gettext_lazy as _ + +from hotpocket_backend.apps.saves.models import Association + + +class AssociationAdmin(admin.ModelAdmin): + list_display = ( + 'pk', 'account_uuid', 'target', 'created_at', 'render_is_active', + ) + search_fields = ('pk', 'account_uuid') + fields = ( + 'pk', + 'account_uuid', + 'archived_at', + 'starred_at', + 'target_meta', + 'target_title', + 'target_description', + 'created_at', + 'deleted_at', + ) + readonly_fields = ( + 'pk', + 'account_uuid', + 'target_meta', + 'target', + 'archived_at', + 'starred_at', + 'created_at', + 'deleted_at', + ) + ordering = ['-created_at'] + + def has_delete_permission(self, request, obj=None): + return request.user.is_superuser + + @admin.display( + description=_('Is Active?'), boolean=True, ordering='-deleted_at', + ) + def render_is_active(self, obj: Association | None = None) -> bool | None: + if obj is None: + return None + + return obj.is_active + + +admin.site.register(Association, AssociationAdmin) diff --git a/services/backend/hotpocket_backend/apps/saves/admin/save.py b/services/backend/hotpocket_backend/apps/saves/admin/save.py index fc9ff8d..0cb35b7 100644 --- a/services/backend/hotpocket_backend/apps/saves/admin/save.py +++ b/services/backend/hotpocket_backend/apps/saves/admin/save.py @@ -11,6 +11,26 @@ class SaveAdmin(admin.ModelAdmin): list_display = ( 'pk', 'key', 'account_uuid', 'created_at', 'render_is_active', ) + search_fields = ('pk', 'account_uuid', 'url') + fields = ( + 'pk', + 'account_uuid', + 'key', + 'url', + 'title', + 'description', + 'last_processed_at', + 'is_netloc_banned', + 'created_at', + 'deleted_at', + ) + readonly_fields = ( + 'pk', + 'account_uuid', + 'key', + 'created_at', + 'deleted_at', + ) ordering = ['-created_at'] def has_delete_permission(self, request, obj=None): diff --git a/services/backend/hotpocket_backend/apps/ui/static/ui/js/hotpocket-backend.js b/services/backend/hotpocket_backend/apps/ui/static/ui/js/hotpocket-backend.js index 51ba8cc..9e9da05 100644 --- a/services/backend/hotpocket_backend/apps/ui/static/ui/js/hotpocket-backend.js +++ b/services/backend/hotpocket_backend/apps/ui/static/ui/js/hotpocket-backend.js @@ -45,7 +45,6 @@ return null; } onLoad = (event) => { - console.log('HotPocketApp.onLoad()', event); for (let pluginSpec of this.plugins) { if (pluginSpec[1].onLoad) { pluginSpec[1].onLoad(event); diff --git a/services/backend/hotpocket_backend/apps/ui/templates/ui/page.html b/services/backend/hotpocket_backend/apps/ui/templates/ui/page.html index b8cda94..1050747 100644 --- a/services/backend/hotpocket_backend/apps/ui/templates/ui/page.html +++ b/services/backend/hotpocket_backend/apps/ui/templates/ui/page.html @@ -130,6 +130,56 @@ {% translate 'Log out' %} +