Internal
Public Access
Fix Critical Security Issue: Replace print() with proper logging
Replaced all debug print() statements with proper logging framework: - tasks/views.py: 5 print statements → logger.debug() - sync/views.py: 15 print statements → logger.debug() - config/celery.py: 1 print statement → logger.debug() - notifications/tasks.py: 2 print statements → logger.error() Retained print() in settings files (development.py, selfhosted.py) as they are appropriate warnings to stderr for configuration issues. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.5
parent
a22c3eed50
commit
b57321e1e4
+4
-1
@@ -2,10 +2,13 @@
|
|||||||
Celery configuration for KeepItGoing.
|
Celery configuration for KeepItGoing.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
import os
|
import os
|
||||||
from celery import Celery
|
from celery import Celery
|
||||||
from celery.schedules import crontab
|
from celery.schedules import crontab
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
# Set the default Django settings module
|
# Set the default Django settings module
|
||||||
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
|
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
|
||||||
|
|
||||||
@@ -32,4 +35,4 @@ app.conf.beat_schedule = {
|
|||||||
|
|
||||||
@app.task(bind=True)
|
@app.task(bind=True)
|
||||||
def debug_task(self):
|
def debug_task(self):
|
||||||
print(f'Request: {self.request!r}')
|
logger.debug(f'Request: {self.request!r}')
|
||||||
|
|||||||
@@ -2,10 +2,13 @@
|
|||||||
Celery tasks for notifications.
|
Celery tasks for notifications.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
from celery import shared_task
|
from celery import shared_task
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@shared_task
|
@shared_task
|
||||||
def send_due_reminders():
|
def send_due_reminders():
|
||||||
@@ -157,7 +160,7 @@ def send_fcm_notification(token, title, body, data=None):
|
|||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Log error but don't fail
|
# Log error but don't fail
|
||||||
print(f"FCM notification failed: {e}")
|
logger.error(f"FCM notification failed: {e}")
|
||||||
|
|
||||||
|
|
||||||
@shared_task
|
@shared_task
|
||||||
@@ -187,7 +190,7 @@ def send_web_push_notification(subscription_info, title, body, data=None):
|
|||||||
)
|
)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Web push notification failed: {e}")
|
logger.error(f"Web push notification failed: {e}")
|
||||||
|
|
||||||
|
|
||||||
@shared_task
|
@shared_task
|
||||||
|
|||||||
+17
-14
@@ -4,6 +4,7 @@ Sync views for KeepItGoing.
|
|||||||
Handles data synchronization between clients and server.
|
Handles data synchronization between clients and server.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
import uuid
|
import uuid
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
@@ -25,6 +26,8 @@ from tasks.serializers import (
|
|||||||
from .models import SyncLog, SyncConflict
|
from .models import SyncLog, SyncConflict
|
||||||
from .serializers import SyncConflictSerializer
|
from .serializers import SyncConflictSerializer
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
@api_view(['POST'])
|
@api_view(['POST'])
|
||||||
@permission_classes([IsAuthenticated])
|
@permission_classes([IsAuthenticated])
|
||||||
@@ -64,7 +67,7 @@ def sync(request):
|
|||||||
# Debug logging
|
# Debug logging
|
||||||
task_changes = changes.get('tasks', [])
|
task_changes = changes.get('tasks', [])
|
||||||
deleted_task_count = sum(1 for t in task_changes if t.get('is_deleted', False))
|
deleted_task_count = sum(1 for t in task_changes if t.get('is_deleted', False))
|
||||||
print(f"[SERVER SYNC DEBUG] Received sync request with {len(task_changes)} tasks, {deleted_task_count} marked as deleted")
|
logger.debug(f"Received sync request with {len(task_changes)} tasks, {deleted_task_count} marked as deleted")
|
||||||
|
|
||||||
if not device_id:
|
if not device_id:
|
||||||
return Response(
|
return Response(
|
||||||
@@ -122,17 +125,17 @@ def process_task_changes(user, task_changes, last_sync_at):
|
|||||||
|
|
||||||
# Debug logging
|
# Debug logging
|
||||||
if is_deleted:
|
if is_deleted:
|
||||||
print(f"[SERVER SYNC DEBUG] Received deletion for task sync_id: {sync_id}")
|
logger.debug(f"Received deletion for task sync_id: {sync_id}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
existing = Task.all_objects.get(sync_id=sync_id, user=user)
|
existing = Task.all_objects.get(sync_id=sync_id, user=user)
|
||||||
|
|
||||||
if is_deleted:
|
if is_deleted:
|
||||||
# Soft delete the task
|
# Soft delete the task
|
||||||
print(f"[SERVER SYNC DEBUG] Soft deleting task: {existing.title} (id: {existing.id})")
|
logger.debug(f"Soft deleting task: {existing.title} (id: {existing.id})")
|
||||||
existing.is_deleted = True
|
existing.is_deleted = True
|
||||||
existing.save()
|
existing.save()
|
||||||
print(f"[SERVER SYNC DEBUG] Task soft deleted successfully")
|
logger.debug(f"Task soft deleted successfully")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Check for conflict
|
# Check for conflict
|
||||||
@@ -212,12 +215,12 @@ def process_time_entry_changes(user, entry_changes, last_sync_at):
|
|||||||
"""Process time entry changes from client."""
|
"""Process time entry changes from client."""
|
||||||
conflicts = []
|
conflicts = []
|
||||||
|
|
||||||
print(f"[SERVER SYNC DEBUG] Processing {len(entry_changes)} time entry changes")
|
logger.debug(f"Processing {len(entry_changes)} time entry changes")
|
||||||
|
|
||||||
for entry_data in entry_changes:
|
for entry_data in entry_changes:
|
||||||
sync_id = entry_data.get('sync_id')
|
sync_id = entry_data.get('sync_id')
|
||||||
is_deleted = entry_data.get('is_deleted', False)
|
is_deleted = entry_data.get('is_deleted', False)
|
||||||
print(f"[SERVER SYNC DEBUG] Time entry sync_id: {sync_id}, is_deleted: {is_deleted}")
|
logger.debug(f"Time entry sync_id: {sync_id}, is_deleted: {is_deleted}")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
existing = TimeEntry.all_objects.get(sync_id=sync_id, user=user)
|
existing = TimeEntry.all_objects.get(sync_id=sync_id, user=user)
|
||||||
@@ -254,8 +257,8 @@ def process_time_entry_changes(user, entry_changes, last_sync_at):
|
|||||||
except TimeEntry.DoesNotExist:
|
except TimeEntry.DoesNotExist:
|
||||||
if not is_deleted:
|
if not is_deleted:
|
||||||
task_sync_id = entry_data.get('task_sync_id')
|
task_sync_id = entry_data.get('task_sync_id')
|
||||||
print(f"[SERVER SYNC DEBUG] Creating new time entry for task_sync_id: {task_sync_id}")
|
logger.debug(f"Creating new time entry for task_sync_id: {task_sync_id}")
|
||||||
print(f"[SERVER SYNC DEBUG] started_at: {entry_data.get('started_at')}, ended_at: {entry_data.get('ended_at')}")
|
logger.debug(f" started_at: {entry_data.get('started_at')}, ended_at: {entry_data.get('ended_at')}")
|
||||||
try:
|
try:
|
||||||
task = Task.objects.get(sync_id=task_sync_id, user=user)
|
task = Task.objects.get(sync_id=task_sync_id, user=user)
|
||||||
|
|
||||||
@@ -276,9 +279,9 @@ def process_time_entry_changes(user, entry_changes, last_sync_at):
|
|||||||
ended_at=ended_at,
|
ended_at=ended_at,
|
||||||
notes=entry_data.get('notes', ''),
|
notes=entry_data.get('notes', ''),
|
||||||
)
|
)
|
||||||
print(f"[SERVER SYNC DEBUG] Created time entry: {new_entry.id}, duration_seconds: {new_entry.duration_seconds}")
|
logger.debug(f"Created time entry: {new_entry.id}, duration_seconds: {new_entry.duration_seconds}")
|
||||||
except Task.DoesNotExist:
|
except Task.DoesNotExist:
|
||||||
print(f"[SERVER SYNC DEBUG] Task not found for sync_id: {task_sync_id}")
|
logger.debug(f"Task not found for sync_id: {task_sync_id}")
|
||||||
pass # Skip if task doesn't exist
|
pass # Skip if task doesn't exist
|
||||||
|
|
||||||
return conflicts
|
return conflicts
|
||||||
@@ -348,7 +351,7 @@ def create_task_from_data(user, data):
|
|||||||
|
|
||||||
def get_server_changes(user, last_sync_at):
|
def get_server_changes(user, last_sync_at):
|
||||||
"""Get all changes on server since last sync."""
|
"""Get all changes on server since last sync."""
|
||||||
print(f"[SERVER SYNC DEBUG] get_server_changes: last_sync_at={last_sync_at}")
|
logger.debug(f"get_server_changes: last_sync_at={last_sync_at}")
|
||||||
filter_kwargs = {'user': user}
|
filter_kwargs = {'user': user}
|
||||||
|
|
||||||
# For incremental sync, filter by updated_at
|
# For incremental sync, filter by updated_at
|
||||||
@@ -364,11 +367,11 @@ def get_server_changes(user, last_sync_at):
|
|||||||
tags = Tag.all_objects.filter(user=user)
|
tags = Tag.all_objects.filter(user=user)
|
||||||
time_entries = TimeEntry.all_objects.filter(user=user)
|
time_entries = TimeEntry.all_objects.filter(user=user)
|
||||||
|
|
||||||
print(f"[SERVER SYNC DEBUG] Returning {len(tasks)} tasks, {len(tags)} tags, {len(time_entries)} time entries")
|
logger.debug(f"Returning {len(tasks)} tasks, {len(tags)} tags, {len(time_entries)} time entries")
|
||||||
if time_entries:
|
if time_entries:
|
||||||
print(f"[SERVER SYNC DEBUG] Time entries being sent to client:")
|
logger.debug(f"Time entries being sent to client:")
|
||||||
for entry in time_entries:
|
for entry in time_entries:
|
||||||
print(f"[SERVER SYNC DEBUG] sync_id: {entry.sync_id}, task: {entry.task.title}, duration: {entry.duration_seconds}s, updated_at: {entry.updated_at}")
|
logger.debug(f" sync_id: {entry.sync_id}, task: {entry.task.title}, duration: {entry.duration_seconds}s, updated_at: {entry.updated_at}")
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'tasks': TaskSyncSerializer(tasks, many=True).data,
|
'tasks': TaskSyncSerializer(tasks, many=True).data,
|
||||||
|
|||||||
+8
-5
@@ -2,6 +2,7 @@
|
|||||||
Task views for KeepItGoing.
|
Task views for KeepItGoing.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
from django.contrib.auth.decorators import login_required
|
from django.contrib.auth.decorators import login_required
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.shortcuts import render, redirect, get_object_or_404
|
from django.shortcuts import render, redirect, get_object_or_404
|
||||||
@@ -22,6 +23,8 @@ from .serializers import (
|
|||||||
TaskShareSerializer,
|
TaskShareSerializer,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# API Views
|
# API Views
|
||||||
@@ -553,7 +556,7 @@ def task_detail_partial(request, task_id):
|
|||||||
def web_timer_start(request, task_id):
|
def web_timer_start(request, task_id):
|
||||||
"""Start a timer for a task (web view)."""
|
"""Start a timer for a task (web view)."""
|
||||||
task = get_object_or_404(Task, id=task_id, user=request.user)
|
task = get_object_or_404(Task, id=task_id, user=request.user)
|
||||||
print(f"[WEB TIMER DEBUG] Starting timer for task: {task.title} (id: {task_id})")
|
logger.debug(f"Starting timer for task: {task.title} (id: {task_id})")
|
||||||
|
|
||||||
# Stop any existing running timer first (properly to calculate duration)
|
# Stop any existing running timer first (properly to calculate duration)
|
||||||
running_entries = TimeEntry.objects.filter(
|
running_entries = TimeEntry.objects.filter(
|
||||||
@@ -567,7 +570,7 @@ def web_timer_start(request, task_id):
|
|||||||
entry.save() # This will calculate duration_seconds
|
entry.save() # This will calculate duration_seconds
|
||||||
stopped_count += 1
|
stopped_count += 1
|
||||||
|
|
||||||
print(f"[WEB TIMER DEBUG] Stopped {stopped_count} existing timers")
|
logger.debug(f"Stopped {stopped_count} existing timers")
|
||||||
|
|
||||||
# Create new timer
|
# Create new timer
|
||||||
entry = TimeEntry.objects.create(
|
entry = TimeEntry.objects.create(
|
||||||
@@ -575,7 +578,7 @@ def web_timer_start(request, task_id):
|
|||||||
user=request.user,
|
user=request.user,
|
||||||
started_at=timezone.now()
|
started_at=timezone.now()
|
||||||
)
|
)
|
||||||
print(f"[WEB TIMER DEBUG] Created new timer entry: {entry.id}")
|
logger.debug(f"Created new timer entry: {entry.id}")
|
||||||
|
|
||||||
next_url = request.POST.get('next', 'dashboard')
|
next_url = request.POST.get('next', 'dashboard')
|
||||||
return redirect(next_url)
|
return redirect(next_url)
|
||||||
@@ -585,7 +588,7 @@ def web_timer_start(request, task_id):
|
|||||||
@require_POST
|
@require_POST
|
||||||
def web_timer_stop(request, task_id):
|
def web_timer_stop(request, task_id):
|
||||||
"""Stop a timer for a task (web view)."""
|
"""Stop a timer for a task (web view)."""
|
||||||
print(f"[WEB TIMER DEBUG] Stopping timer for task_id: {task_id}")
|
logger.debug(f"Stopping timer for task_id: {task_id}")
|
||||||
|
|
||||||
# Get the running timer and stop it properly (to trigger save() and calculate duration)
|
# Get the running timer and stop it properly (to trigger save() and calculate duration)
|
||||||
entries = TimeEntry.objects.filter(
|
entries = TimeEntry.objects.filter(
|
||||||
@@ -600,7 +603,7 @@ def web_timer_stop(request, task_id):
|
|||||||
entry.save() # This will calculate duration_seconds
|
entry.save() # This will calculate duration_seconds
|
||||||
stopped_count += 1
|
stopped_count += 1
|
||||||
|
|
||||||
print(f"[WEB TIMER DEBUG] Stopped {stopped_count} timer entries")
|
logger.debug(f"Stopped {stopped_count} timer entries")
|
||||||
|
|
||||||
next_url = request.POST.get('next', 'dashboard')
|
next_url = request.POST.get('next', 'dashboard')
|
||||||
return redirect(next_url)
|
return redirect(next_url)
|
||||||
|
|||||||
Reference in New Issue
Block a user