Compare commits

..

4 Commits

Author SHA1 Message Date
f68e5b4573 Release v1.0.2
All checks were successful
CI / Checks (push) Successful in 16m8s
2025-08-29 14:15:16 +02:00
db39c38594 BTHLABS-54: Unprocessed save shows Untitled in the card title 2025-08-29 08:23:09 +02:00
38d768a584 BTHLABS-53: Processing task fails for newly created saves 2025-08-29 08:20:53 +02:00
fb39818be3 public -> development 2025-08-20 20:01:12 +00:00
13 changed files with 49 additions and 52 deletions

View File

@ -66,7 +66,7 @@ $ docker run --rm -it \
-e HOTPOCKET_BACKEND_INITIAL_ACCOUNT_USERNAME=hotpocket \ -e HOTPOCKET_BACKEND_INITIAL_ACCOUNT_USERNAME=hotpocket \
-e HOTPOCKET_BACKEND_INITIAL_ACCOUNT_PASSWORD=hotpocketm4st3r \ -e HOTPOCKET_BACKEND_INITIAL_ACCOUNT_PASSWORD=hotpocketm4st3r \
-p 8000:8000 \ -p 8000:8000 \
docker-hosted.nexus.bthlabs.pl/hotpocket/backend:aio-v1.0.1-01 docker-hosted.nexus.bthlabs.pl/hotpocket/backend:aio-v1.0.2-01
``` ```
The command above will set up and start the application. The SQLite file will The command above will set up and start the application. The SQLite file will

View File

@ -1,6 +1,6 @@
services: services:
backend: backend:
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:aio-v1.0.1-01" image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:aio-v1.0.2-01"
environment: environment:
HOTPOCKET_BACKEND_SECRET_KEY: "thisisntright" HOTPOCKET_BACKEND_SECRET_KEY: "thisisntright"
HOTPOCKET_BACKEND_INITIAL_ACCOUNT_USERNAME: "hotpocket" HOTPOCKET_BACKEND_INITIAL_ACCOUNT_USERNAME: "hotpocket"

View File

@ -8,7 +8,7 @@ x-backend-environment: &x-backend-environment
services: services:
webapp: webapp:
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:deployment-v1.0.1-01" image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:deployment-v1.0.2-01"
environment: environment:
<<: *x-backend-environment <<: *x-backend-environment
HOTPOCKET_BACKEND_ALLOWED_HOSTS: "app.staging.hotpocket.bthlab.bthlabs.net" HOTPOCKET_BACKEND_ALLOWED_HOSTS: "app.staging.hotpocket.bthlab.bthlabs.net"
@ -21,7 +21,7 @@ services:
restart: "unless-stopped" restart: "unless-stopped"
admin: admin:
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:deployment-v1.0.1-01" image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:deployment-v1.0.2-01"
environment: environment:
<<: *x-backend-environment <<: *x-backend-environment
HOTPOCKET_BACKEND_APP: "admin" HOTPOCKET_BACKEND_APP: "admin"
@ -35,7 +35,7 @@ services:
restart: "unless-stopped" restart: "unless-stopped"
celery-worker: celery-worker:
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:deployment-v1.0.1-01" image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:deployment-v1.0.2-01"
command: command:
- "/srv/venv/bin/celery" - "/srv/venv/bin/celery"
- "-A" - "-A"
@ -57,7 +57,7 @@ services:
restart: "unless-stopped" restart: "unless-stopped"
celery-beat: celery-beat:
image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:deployment-v1.0.1-01" image: "docker-hosted.nexus.bthlabs.pl/hotpocket/backend:deployment-v1.0.2-01"
command: command:
- "/srv/venv/bin/celery" - "/srv/venv/bin/celery"
- "-A" - "-A"

View File

@ -1,4 +1,4 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import annotations from __future__ import annotations
version = '1.0.1' version = '1.0.2'

View File

@ -2,6 +2,7 @@
from __future__ import annotations from __future__ import annotations
from django.contrib import messages from django.contrib import messages
import django.db
from django.http import HttpRequest, HttpResponse from django.http import HttpRequest, HttpResponse
from django.shortcuts import redirect from django.shortcuts import redirect
from django.urls import reverse from django.urls import reverse
@ -21,15 +22,13 @@ class CreateSaveWorkflow(SaveWorkflow):
url: str, url: str,
force_post_save: bool = False, force_post_save: bool = False,
) -> HttpResponse: ) -> HttpResponse:
save = self.create( with django.db.transaction.atomic():
account.pk, save = self.create(
SaveIn(url=url), account.pk,
) SaveIn(url=url),
)
association = self.associate(account.pk, save) association = self.associate(account.pk, save)
if save.last_processed_at is None:
processing_result = self.schedule_processing(save) # noqa: F841
response = redirect(reverse('ui.associations.browse')) response = redirect(reverse('ui.associations.browse'))
if force_post_save is True or save.is_netloc_banned is True: if force_post_save is True or save.is_netloc_banned is True:
@ -47,4 +46,7 @@ class CreateSaveWorkflow(SaveWorkflow):
response.headers['X-HotPocket-Testing-Save-PK'] = save.pk response.headers['X-HotPocket-Testing-Save-PK'] = save.pk
response.headers['X-HotPocket-Testing-Association-PK'] = association.pk response.headers['X-HotPocket-Testing-Association-PK'] = association.pk
if save.last_processed_at is None:
processing_result = self.schedule_processing(save) # noqa: F841
return response return response

View File

@ -7,7 +7,7 @@
{% if association.title %} {% if association.title %}
{{ association.title }} {{ association.title }}
{% else %} {% else %}
{% translate 'Untitled' %} {{ association.target.url }}
{% endif %} {% endif %}
</a> </a>
</h5> </h5>

View File

@ -4,7 +4,6 @@ from __future__ import annotations
import http import http
import logging import logging
import django.db
from django.http import HttpRequest, HttpResponse from django.http import HttpRequest, HttpResponse
from django.shortcuts import render from django.shortcuts import render
from django.views.decorators.csrf import csrf_exempt from django.views.decorators.csrf import csrf_exempt
@ -21,19 +20,18 @@ def share_sheet(request: HttpRequest) -> HttpResponse:
LOGGER.debug('POST=`%s`', request.POST) LOGGER.debug('POST=`%s`', request.POST)
try: try:
with django.db.transaction.atomic(): assert request.user.is_anonymous is False, 'Login required'
assert request.user.is_anonymous is False, 'Login required' assert 'text' in request.POST, 'Bad request: Missing `text`'
assert 'text' in request.POST, 'Bad request: Missing `text`'
url = request.POST['text'].split('\n')[0].strip() url = request.POST['text'].split('\n')[0].strip()
assert url != '', 'Bad request: Empty `text`' assert url != '', 'Bad request: Empty `text`'
return CreateSaveWorkflow().run( return CreateSaveWorkflow().run(
request=request, request=request,
account=request.user, account=request.user,
url=url, url=url,
force_post_save=True, force_post_save=True,
) )
except Exception as exception: except Exception as exception:
LOGGER.error( LOGGER.error(
'Unhandled exception: %s', 'Unhandled exception: %s',

View File

@ -4,7 +4,6 @@ from __future__ import annotations
import http import http
import logging import logging
import django.db
from django.http import HttpRequest, HttpResponse from django.http import HttpRequest, HttpResponse
from django.shortcuts import render from django.shortcuts import render
@ -19,19 +18,18 @@ def shortcut(request: HttpRequest) -> HttpResponse:
LOGGER.debug('GET=`%s`', request.GET) LOGGER.debug('GET=`%s`', request.GET)
try: try:
with django.db.transaction.atomic(): assert request.user.is_anonymous is False, 'Login required'
assert request.user.is_anonymous is False, 'Login required' assert 'url' in request.GET, 'Bad request: Missing `url`'
assert 'url' in request.GET, 'Bad request: Missing `url`'
url = request.GET['url'].split('\n')[0].strip() url = request.GET['url'].split('\n')[0].strip()
assert url != '', 'Bad request: Empty `url`' assert url != '', 'Bad request: Empty `url`'
return CreateSaveWorkflow().run( return CreateSaveWorkflow().run(
request=request, request=request,
account=request.user, account=request.user,
url=url, url=url,
force_post_save=True, force_post_save=True,
) )
except Exception as exception: except Exception as exception:
LOGGER.error( LOGGER.error(
'Unhandled exception: %s', 'Unhandled exception: %s',

View File

@ -4,7 +4,6 @@ from __future__ import annotations
import http import http
import logging import logging
import django.db
from django.http import HttpRequest, HttpResponse from django.http import HttpRequest, HttpResponse
from django.shortcuts import render from django.shortcuts import render
from django.urls import reverse from django.urls import reverse
@ -24,12 +23,11 @@ class CreateView(AccountRequiredMixin, FormView):
form_class = CreateForm form_class = CreateForm
def form_valid(self, form: CreateForm) -> HttpResponse: def form_valid(self, form: CreateForm) -> HttpResponse:
with django.db.transaction.atomic(): return CreateSaveWorkflow().run(
return CreateSaveWorkflow().run( request=self.request,
request=self.request, account=self.request.user,
account=self.request.user, url=form.cleaned_data['url'],
url=form.cleaned_data['url'], )
)
def get_success_url(self) -> str: def get_success_url(self) -> str:
return reverse('ui.associations.browse') return reverse('ui.associations.browse')

View File

@ -13,7 +13,7 @@ cat <<EOF
|_| |_|
production production
HotPocket v1.0.1 [${HOTPOCKET_BACKEND_IMAGE_ID}] (https://hotpocket.app/) HotPocket v1.0.2 [${HOTPOCKET_BACKEND_IMAGE_ID}] (https://hotpocket.app/)
Copyright 2025-present by BTHLabs. All rights reserved. (https://bthlabs.pl/) Copyright 2025-present by BTHLabs. All rights reserved. (https://bthlabs.pl/)
Licensed under Apache-2.0 Licensed under Apache-2.0
EOF EOF

View File

@ -1,6 +1,6 @@
{ {
"name": "hotpocket-backend", "name": "hotpocket-backend",
"version": "1.0.1", "version": "1.0.2",
"description": "HotPocket Backend", "description": "HotPocket Backend",
"main": "hotpocket_backend/apps/frontend/src/index.js", "main": "hotpocket_backend/apps/frontend/src/index.js",
"repository": "https://git.bthlabs.pl/tomekwojcik/hotpocket", "repository": "https://git.bthlabs.pl/tomekwojcik/hotpocket",

View File

@ -1,6 +1,6 @@
[tool.poetry] [tool.poetry]
name = "hotpocket-backend" name = "hotpocket-backend"
version = "1.0.1" version = "1.0.2"
description = "HotPocket Backend" description = "HotPocket Backend"
authors = ["Tomek Wójcik <contact@bthlabs.pl>"] authors = ["Tomek Wójcik <contact@bthlabs.pl>"]
license = "Apache-2.0" license = "Apache-2.0"

View File

@ -2,8 +2,9 @@
extend-exclude = extend-exclude =
hotpocket_backend/apps/*/migrations/*.py, hotpocket_backend/apps/*/migrations/*.py,
node_modules/**/*.py, node_modules/**/*.py,
skel/*.py skel/*.py,
skel/*/*.py skel/*/*.py,
playground.py
ignore = E131,W503,W504 ignore = E131,W503,W504
max-line-length = 119 max-line-length = 119
hang-closing = False hang-closing = False