Author SHA1 Message Date
Luciano Gervasoni 3a33697ca3 Fix critical bugs in app_urls
- init_db.py: parameterize SQL queries to prevent SQL injection
- scheduled_tasks.json: resolve duplicate periodic task pk (4 -> 15)
- db_utils.py: use function parameter in _get_status_pattern_matching
  instead of capturing the enclosing scope variable
- url_detail.html: fix wrong field name image_urls -> images_url
- settings.py: align Celery queues (default/light/heavy) with the task
  queues and supervisord workers
- Add /task/publish_<id>/ route to fix broken publish links in templates
2026-09-01 15:08:14 -03:00
7 changed files with 24 additions and 15 deletions
+2 -1
View File
@@ -123,7 +123,8 @@ CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers.DatabaseScheduler'
CELERY_TASK_QUEUES = ( CELERY_TASK_QUEUES = (
Queue('default'), Queue('default'),
Queue('low'), Queue('light'),
Queue('heavy'),
) )
+1 -1
View File
@@ -212,7 +212,7 @@ class DB_Handler():
# Sort pattern tuples by priority. (pattern, priority, status) # Sort pattern tuples by priority. (pattern, priority, status)
for regex_pattern, regex_priority, status_if_match in sorted(list_pattern_status_tuple, key=lambda tup: tup[1], reverse=True): for regex_pattern, regex_priority, status_if_match in sorted(list_pattern_status_tuple, key=lambda tup: tup[1], reverse=True):
# Regular expression pattern matching: https://regexr.com/ # Regular expression pattern matching: https://regexr.com/
if bool(re.match(regex_pattern, obj_url.url)): if bool(re.match(regex_pattern, url)):
# logger.debug("Regex pattern found, status '{}' for URL: {}".format(status_if_match, url)) # logger.debug("Regex pattern found, status '{}' for URL: {}".format(status_if_match, url))
return status_if_match return status_if_match
return None return None
+1 -1
View File
@@ -246,7 +246,7 @@
</tr> </tr>
<tr> <tr>
<th>Image URLs</th> <th>Image URLs</th>
<td>{{ url_content.image_urls|default:"" }}</td> <td>{{ url_content.images_url|default:"" }}</td>
</tr> </tr>
<tr> <tr>
<th>Video URLs</th> <th>Video URLs</th>
+1
View File
@@ -17,4 +17,5 @@ urlpatterns = [
# #
path('urls/', views.filtered_urls, name='filtered_urls'), path('urls/', views.filtered_urls, name='filtered_urls'),
path('urls/<int:id>/', views.url_detail_view, name='url_detail'), path('urls/<int:id>/', views.url_detail_view, name='url_detail'),
path('task/publish_<int:id>/', views.publish, name='publish'),
] ]
+11 -1
View File
@@ -2,12 +2,13 @@ from .views_base import link_list, logs, log_db #, trigger_task,
from django.core.paginator import Paginator from django.core.paginator import Paginator
from django.shortcuts import render, get_object_or_404 from django.shortcuts import render, get_object_or_404
from django.http import StreamingHttpResponse, JsonResponse from django.http import StreamingHttpResponse, JsonResponse, HttpResponse
from django.db.models import Q, Count from django.db.models import Q, Count
from django.utils import timezone from django.utils import timezone
from django.utils.timezone import now, timedelta from django.utils.timezone import now, timedelta
from .models import Urls, Source, Search, UrlContent, UrlsSourceSearch, UrlsDuplicate from .models import Urls, Source, Search, UrlContent, UrlsSourceSearch, UrlsDuplicate
from .src.llm import OllamaClient from .src.llm import OllamaClient
from .src.publisher import Publisher
import json import json
@@ -62,6 +63,15 @@ def url_detail_view(request, id):
} }
return render(request, 'url_detail.html', context) return render(request, 'url_detail.html', context)
def publish(request, id):
# Publish URL content to Ghost
try:
Publisher().publish(id)
message = "URL ID {} published".format(id)
except Exception as e:
message = "Error publishing URL ID {}: {}".format(id, str(e))
return HttpResponse(message)
#################################################################################################### ####################################################################################################
def charts(request): def charts(request):
return render(request, 'charts.html') return render(request, 'charts.html')
+7 -10
View File
@@ -210,10 +210,9 @@ def initialize_data():
for list_pattern_status_priority in data_json.get("REGEX_PATTERN_STATUS_PRIORITY", []): for list_pattern_status_priority in data_json.get("REGEX_PATTERN_STATUS_PRIORITY", []):
# Decode # Decode
pattern, status, priority = list_pattern_status_priority pattern, status, priority = list_pattern_status_priority
# Query # Query (parameterized to avoid SQL injection)
query = "INSERT INTO STATUS_PATTERN_MATCHING (pattern, priority, status) VALUES ('{}', {}, '{}');".format(pattern, priority, status) query = "INSERT INTO STATUS_PATTERN_MATCHING (pattern, priority, status) VALUES (%s, %s, %s);"
print(query) cur.execute(query, (pattern, priority, status))
cur.execute(query)
# Connect to an existing database # Connect to an existing database
with psycopg.connect(connection_info) as conn: with psycopg.connect(connection_info) as conn:
@@ -222,9 +221,8 @@ def initialize_data():
# Feeds, URL host, keyword search # Feeds, URL host, keyword search
for search_type, list_searches in data_json.get("SEARCH", {}).items(): for search_type, list_searches in data_json.get("SEARCH", {}).items():
for search in list_searches: for search in list_searches:
query = "INSERT INTO SEARCH (search, type) VALUES ('{}', '{}');".format(search, search_type) insert_search_sql = "INSERT INTO SEARCH (search, type) VALUES (%s, %s);"
print(query) cur.execute(insert_search_sql, (search, search_type))
cur.execute(query)
# Try finding RSS feed # Try finding RSS feed
if (search_type == "url_host"): if (search_type == "url_host"):
@@ -232,9 +230,8 @@ def initialize_data():
list_feeds = find_feeds(url_host) list_feeds = find_feeds(url_host)
# If not exists, insert feed # If not exists, insert feed
for feed in list_feeds: for feed in list_feeds:
query = "INSERT INTO SEARCH (search, type) VALUES ('{}', '{}') ON CONFLICT DO NOTHING;".format(feed, "rss_feed") insert_feed_sql = "INSERT INTO SEARCH (search, type) VALUES (%s, %s) ON CONFLICT DO NOTHING;"
print(query) cur.execute(insert_feed_sql, (feed, "rss_feed"))
cur.execute(query)
if __name__ == '__main__': if __name__ == '__main__':
+1 -1
View File
@@ -393,7 +393,7 @@
}, },
{ {
"model": "django_celery_beat.periodictask", "model": "django_celery_beat.periodictask",
"pk": 4, "pk": 15,
"fields": { "fields": {
"name": "Notify status", "name": "Notify status",
"task": "fetcher.tasks.notify_status", "task": "fetcher.tasks.notify_status",