Files
Andrey Smakotin 387f5dfdb4 Усилена безопасность: запрет доступа владельцев тенантов к Django админке
Реализовано три уровня защиты от доступа владельцев тенантов к /admin/:

1. Явные флаги безопасности в CustomUserManager.create_user()
   - Добавлены setdefault(is_staff=False, is_superuser=False)
   - Устраняет зависимость от неявных дефолтов Django

2. Явные флаги при создании владельцев тенантов (tenants/admin.py)
   - Владельцы создаются с is_staff=False, is_superuser=False
   - Явная документация намерений в коде

3. Middleware защита на уровне HTTP (TenantAdminAccessMiddleware)
   - Блокирует доступ к /admin/ на поддоменах тенантов
   - Только is_superuser=True может войти в админку тенанта
   - Последний рубеж обороны (defense-in-depth)

Дополнительно:
- Исправлена видимость alert-уведомлений на странице регистрации
  (добавлены явные цвета для всех типов alert)

Суперпользователи НЕ затронуты: create_superuser() работает как прежде.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-02 11:51:17 +03:00

163 lines
4.7 KiB
HTML

<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{% block title %}Регистрация магазина{% endblock %} - Inventory System</title>
<!-- Bootstrap 5 CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<style>
body {
background: linear-gradient(135deg, #1e293b 0%, #334155 100%);
min-height: 100vh;
padding: 20px 10px;
display: flex;
align-items: center;
}
.container {
max-width: 520px;
}
.card {
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);
border: none;
border-radius: 8px;
overflow: hidden;
}
.card-header {
background: #3b82f6;
color: white;
padding: 0.875rem 1.25rem;
border-bottom: none;
}
.card-header h3 {
font-size: 1.125rem;
font-weight: 600;
margin: 0;
}
.card-header p {
font-size: 0.8rem;
opacity: 0.95;
margin: 0.2rem 0 0 0;
}
.card-body {
padding: 1.25rem;
}
.form-label {
font-size: 0.875rem;
font-weight: 500;
color: #374151;
margin-bottom: 0.25rem;
}
.form-control, .input-group-text {
font-size: 0.9375rem;
padding: 0.45rem 0.7rem;
border-radius: 5px;
}
.input-group-text {
background: #f3f4f6;
border-left: none;
color: #6b7280;
font-size: 0.875rem;
}
.form-control:focus {
border-color: #3b82f6;
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
}
.form-text {
font-size: 0.75rem;
color: #6b7280;
margin-top: 0.2rem;
}
.text-danger {
color: #ef4444 !important;
font-size: 0.8125rem;
}
.mb-2 {
margin-bottom: 0.65rem !important;
}
.mb-3 {
margin-bottom: 0.875rem !important;
}
.btn-primary {
background: #3b82f6;
border: none;
font-weight: 500;
font-size: 0.9rem;
padding: 0.5rem 1rem;
border-radius: 6px;
transition: all 0.2s;
}
.btn-primary:hover {
background: #2563eb;
transform: translateY(-1px);
box-shadow: 0 4px 8px rgba(59, 130, 246, 0.3);
}
.alert {
border-radius: 6px;
font-size: 0.85rem;
padding: 0.65rem 0.875rem;
color: #1f2937 !important;
background-color: #ffffff;
border: 1px solid rgba(0, 0, 0, 0.1);
}
.alert-success {
background-color: #d1fae5 !important;
border-color: #10b981 !important;
color: #065f46 !important;
}
.alert-error, .alert-danger {
background-color: #fee2e2 !important;
border-color: #ef4444 !important;
color: #991b1b !important;
}
.alert-warning {
background-color: #fef3c7 !important;
border-color: #f59e0b !important;
color: #92400e !important;
}
.alert-info {
background-color: #dbeafe !important;
border-color: #3b82f6 !important;
color: #1e40af !important;
}
small.text-muted {
font-size: 0.8125rem;
color: #6b7280;
line-height: 1.3;
}
.row {
margin-left: -0.375rem;
margin-right: -0.375rem;
}
.row > * {
padding-left: 0.375rem;
padding-right: 0.375rem;
}
</style>
{% block extra_css %}{% endblock %}
</head>
<body>
<div class="container">
{% if messages %}
<div class="mb-3">
{% for message in messages %}
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
{{ message }}
<button type="button" class="btn-close" data-bs-dismiss="alert"></button>
</div>
{% endfor %}
</div>
{% endif %}
{% block content %}{% endblock %}
</div>
<!-- Bootstrap 5 JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
{% block extra_js %}{% endblock %}
</body>
</html>