Security hardening: fix open redirect, API auth, MIME validation, PII exposure

- core/views.py: fix open redirect in login — validate next_url with
  url_has_allowed_host_and_scheme before redirecting
- visit_manager/api/views.py: add explicit permission_classes/
  authentication_classes on all 3 API views; add MIME magic-byte
  validation + Pillow verify for photo uploads; validate employee_id/
  location_id/date query params; restrict photo access to is_staff,
  own record, or direct manager
- employees/serializers.py: split into EmployeeSerializer (public
  fields only) and EmployeeDetailSerializer (PII fields, for HR/admin)
- mattermost_service.py: sanitize sensitive fields (password, token)
  before logging; log only error message not full response body
- settings/base.py: add SESSION/CSRF cookie HttpOnly + SameSite flags;
  set file upload size limits (15MB); remove BasicAuthentication from
  DRF (sends credentials in plaintext)
This commit is contained in:
2026-05-31 18:05:54 +03:00
parent 24c2f28e43
commit faa06b9f82
5 changed files with 121 additions and 30 deletions
+4
View File
@@ -1,6 +1,8 @@
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
from django.utils.http import url_has_allowed_host_and_scheme
from django.conf import settings
from apps.employees.models.base import Employee
from apps.locations.models.pharmacies import Pharmacy
from core.models.directories import Directory
@@ -182,6 +184,8 @@ def login_view(request):
if user is not None:
login(request, user)
next_url = request.GET.get('next') or request.POST.get('next') or '/'
if not url_has_allowed_host_and_scheme(next_url, allowed_hosts=settings.ALLOWED_HOSTS):
next_url = '/'
return redirect(next_url)
return render(request, 'login.html', {'login_error': 'Неверный логин или пароль'})
return render(request, 'login.html')