test: add my_requests.html and IP restriction test scripts
This commit is contained in:
parent
98dabd6c53
commit
592a799cc7
54
backend/templates/requests_app/my_requests.html
Normal file
54
backend/templates/requests_app/my_requests.html
Normal file
@ -0,0 +1,54 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static django_bootstrap5 %}
|
||||
|
||||
{% block title %}Мои заявления{% endblock %}
|
||||
|
||||
{% block extra_css %}
|
||||
<link rel="stylesheet" href="{% static 'css/components/common.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'css/components/ios-search.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'css/components/page-header.css' %}">
|
||||
<link rel="stylesheet" href="{% static 'css/components/list-view.css' %}">
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container">
|
||||
<div class="row gx-0">
|
||||
<div class="col-12">
|
||||
|
||||
{# — Шапка страницы — #}
|
||||
{% include "includes/components/page_header.html" with icon="bi-file-earmark-text" title="Мои заявления" search_id="requestFilter" search_placeholder="Поиск по типу или комментарию" create_url="requests_app:request_create" create_text="Подать новое заявление" %}
|
||||
|
||||
<div class="card mb-3">
|
||||
<div id="requestList" class="list-view card-list">
|
||||
{# Список загружается через JavaScript из requestListHandler.js #}
|
||||
<div class="text-center py-4">
|
||||
<div class="spinner-border text-primary" role="status">
|
||||
<span class="visually-hidden">Загрузка...</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
{% block extra_js %}
|
||||
<script type="module">
|
||||
import { initRequestListHandler } from "{% static 'js/components/requestListHandler.js' %}";
|
||||
|
||||
// Получаем токен доступа
|
||||
const accessMeta = document.querySelector('meta[name="api-access"]');
|
||||
const ACCESS = accessMeta ? accessMeta.content : '';
|
||||
const headers = ACCESS ? { 'Authorization': 'Bearer ' + ACCESS } : {};
|
||||
|
||||
// Инициализация списка заявлений
|
||||
initRequestListHandler({
|
||||
apiListUrl: '/api/v1/requests/',
|
||||
scope: 'my',
|
||||
userId: {{ user.id }},
|
||||
headers
|
||||
});
|
||||
</script>
|
||||
{% endblock %}
|
||||
171
backend/test_ip_restrictions.py
Normal file
171
backend/test_ip_restrictions.py
Normal file
@ -0,0 +1,171 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Тестирование IP-ограничений для регистрации.
|
||||
|
||||
Запуск:
|
||||
python backend/test_ip_restrictions.py
|
||||
"""
|
||||
import os
|
||||
import sys
|
||||
import django
|
||||
|
||||
# Настройка Django
|
||||
sys.path.insert(0, os.path.join(os.path.dirname(__file__)))
|
||||
os.environ.setdefault("DJANGO_SECRET_KEY", "test-key")
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "eusrr_backend.settings")
|
||||
django.setup()
|
||||
|
||||
from common.ip_restrictions import (
|
||||
get_client_ip,
|
||||
is_local_ip,
|
||||
is_ip_allowed,
|
||||
)
|
||||
|
||||
|
||||
def test_is_local_ip():
|
||||
"""Тест проверки локальных IP."""
|
||||
print("\n=== Тест: is_local_ip ===")
|
||||
|
||||
test_cases = [
|
||||
('127.0.0.1', True, 'localhost IPv4'),
|
||||
('127.0.0.100', True, 'localhost range'),
|
||||
('192.168.1.1', True, 'private class C'),
|
||||
('192.168.100.50', True, 'private class C'),
|
||||
('10.0.0.1', True, 'private class A'),
|
||||
('172.16.0.1', True, 'private class B'),
|
||||
('172.31.255.255', True, 'private class B edge'),
|
||||
('8.8.8.8', False, 'public Google DNS'),
|
||||
('203.0.113.50', False, 'public TEST-NET'),
|
||||
('::1', True, 'localhost IPv6'),
|
||||
('invalid-ip', False, 'invalid IP'),
|
||||
]
|
||||
|
||||
passed = 0
|
||||
failed = 0
|
||||
|
||||
for ip, expected, description in test_cases:
|
||||
result = is_local_ip(ip)
|
||||
status = "✅" if result == expected else "❌"
|
||||
|
||||
if result == expected:
|
||||
passed += 1
|
||||
else:
|
||||
failed += 1
|
||||
|
||||
print(f"{status} {ip:20} -> {result:5} (expected: {expected:5}) # {description}")
|
||||
|
||||
print(f"\nПройдено: {passed}/{passed + failed}")
|
||||
return failed == 0
|
||||
|
||||
|
||||
def test_is_ip_allowed():
|
||||
"""Тест проверки разрешенных IP с кастомными настройками."""
|
||||
print("\n=== Тест: is_ip_allowed ===")
|
||||
|
||||
# Тест 1: Разрешить все
|
||||
print("\n1. Разрешить все IP ['*']:")
|
||||
result = is_ip_allowed('203.0.113.50', ['*'])
|
||||
print(f" {'✅' if result else '❌'} 203.0.113.50 -> {result} (expected: True)")
|
||||
|
||||
# Тест 2: Разрешить конкретную сеть
|
||||
print("\n2. Разрешить сеть 192.168.1.0/24:")
|
||||
allowed_net = ['192.168.1.0/24']
|
||||
tests = [
|
||||
('192.168.1.1', True),
|
||||
('192.168.1.100', True),
|
||||
('192.168.1.255', True),
|
||||
('192.168.2.1', False),
|
||||
('10.0.0.1', False),
|
||||
]
|
||||
|
||||
for ip, expected in tests:
|
||||
result = is_ip_allowed(ip, allowed_net)
|
||||
status = "✅" if result == expected else "❌"
|
||||
print(f" {status} {ip:20} -> {result:5} (expected: {expected:5})")
|
||||
|
||||
# Тест 3: Разрешить конкретные IP
|
||||
print("\n3. Разрешить конкретные IP ['192.168.1.100', '10.0.0.5']:")
|
||||
allowed_ips = ['192.168.1.100', '10.0.0.5']
|
||||
tests = [
|
||||
('192.168.1.100', True),
|
||||
('10.0.0.5', True),
|
||||
('192.168.1.101', False),
|
||||
('10.0.0.6', False),
|
||||
]
|
||||
|
||||
for ip, expected in tests:
|
||||
result = is_ip_allowed(ip, allowed_ips)
|
||||
status = "✅" if result == expected else "❌"
|
||||
print(f" {status} {ip:20} -> {result:5} (expected: {expected:5})")
|
||||
|
||||
# Тест 4: По умолчанию (только локальные)
|
||||
print("\n4. По умолчанию (None = только локальные IP):")
|
||||
tests = [
|
||||
('127.0.0.1', True),
|
||||
('192.168.1.1', True),
|
||||
('10.0.0.1', True),
|
||||
('8.8.8.8', False),
|
||||
('203.0.113.50', False),
|
||||
]
|
||||
|
||||
for ip, expected in tests:
|
||||
result = is_ip_allowed(ip, None)
|
||||
status = "✅" if result == expected else "❌"
|
||||
print(f" {status} {ip:20} -> {result:5} (expected: {expected:5})")
|
||||
|
||||
|
||||
def test_get_client_ip():
|
||||
"""Тест получения IP из request."""
|
||||
print("\n=== Тест: get_client_ip ===")
|
||||
|
||||
from django.test import RequestFactory
|
||||
|
||||
factory = RequestFactory()
|
||||
|
||||
# Тест 1: Обычный запрос
|
||||
print("\n1. Обычный запрос (без прокси):")
|
||||
request = factory.get('/')
|
||||
ip = get_client_ip(request)
|
||||
print(f" IP: {ip}")
|
||||
|
||||
# Тест 2: С заголовком X-Forwarded-For
|
||||
print("\n2. Запрос через прокси (X-Forwarded-For):")
|
||||
request = factory.get('/', HTTP_X_FORWARDED_FOR='203.0.113.50, 192.168.1.1')
|
||||
ip = get_client_ip(request)
|
||||
expected = '203.0.113.50'
|
||||
status = "✅" if ip == expected else "❌"
|
||||
print(f" {status} IP: {ip} (expected: {expected})")
|
||||
|
||||
# Тест 3: С одним IP в X-Forwarded-For
|
||||
print("\n3. Запрос через прокси (один IP):")
|
||||
request = factory.get('/', HTTP_X_FORWARDED_FOR='10.0.0.5')
|
||||
ip = get_client_ip(request)
|
||||
expected = '10.0.0.5'
|
||||
status = "✅" if ip == expected else "❌"
|
||||
print(f" {status} IP: {ip} (expected: {expected})")
|
||||
|
||||
|
||||
def main():
|
||||
"""Запуск всех тестов."""
|
||||
print("=" * 60)
|
||||
print("Тестирование модуля IP-ограничений")
|
||||
print("=" * 60)
|
||||
|
||||
try:
|
||||
test_is_local_ip()
|
||||
test_is_ip_allowed()
|
||||
test_get_client_ip()
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("✅ Все тесты выполнены")
|
||||
print("=" * 60)
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n❌ Ошибка: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
167
backend/test_ip_simple.py
Normal file
167
backend/test_ip_simple.py
Normal file
@ -0,0 +1,167 @@
|
||||
#!/usr/bin/env python
|
||||
"""
|
||||
Простой тест IP-ограничений (без Django).
|
||||
"""
|
||||
import ipaddress
|
||||
|
||||
|
||||
def is_local_ip(ip_address: str) -> bool:
|
||||
"""Проверяет, является ли IP-адрес локальным."""
|
||||
try:
|
||||
ip = ipaddress.ip_address(ip_address)
|
||||
return ip.is_private or ip.is_loopback or ip.is_link_local
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
|
||||
def is_ip_allowed(ip_address: str, allowed_networks=None):
|
||||
"""Проверяет, разрешен ли доступ с данного IP-адреса."""
|
||||
if allowed_networks is None:
|
||||
return is_local_ip(ip_address)
|
||||
|
||||
if not allowed_networks:
|
||||
return False
|
||||
|
||||
if allowed_networks == ['*'] or '*' in allowed_networks:
|
||||
return True
|
||||
|
||||
try:
|
||||
ip = ipaddress.ip_address(ip_address)
|
||||
|
||||
for network_str in allowed_networks:
|
||||
if '/' in network_str:
|
||||
network = ipaddress.ip_network(network_str, strict=False)
|
||||
if ip in network:
|
||||
return True
|
||||
else:
|
||||
allowed_ip = ipaddress.ip_address(network_str)
|
||||
if ip == allowed_ip:
|
||||
return True
|
||||
|
||||
return False
|
||||
except ValueError:
|
||||
return False
|
||||
|
||||
|
||||
def test_is_local_ip():
|
||||
"""Тест проверки локальных IP."""
|
||||
print("\n=== Тест: is_local_ip ===")
|
||||
|
||||
test_cases = [
|
||||
('127.0.0.1', True, 'localhost IPv4'),
|
||||
('127.0.0.100', True, 'localhost range'),
|
||||
('192.168.1.1', True, 'private class C'),
|
||||
('192.168.100.50', True, 'private class C'),
|
||||
('10.0.0.1', True, 'private class A'),
|
||||
('172.16.0.1', True, 'private class B'),
|
||||
('172.31.255.255', True, 'private class B edge'),
|
||||
('8.8.8.8', False, 'public Google DNS'),
|
||||
('203.0.113.50', False, 'public TEST-NET'),
|
||||
('::1', True, 'localhost IPv6'),
|
||||
('invalid-ip', False, 'invalid IP'),
|
||||
]
|
||||
|
||||
passed = 0
|
||||
failed = 0
|
||||
|
||||
for ip, expected, description in test_cases:
|
||||
result = is_local_ip(ip)
|
||||
status = "✅" if result == expected else "❌"
|
||||
|
||||
if result == expected:
|
||||
passed += 1
|
||||
else:
|
||||
failed += 1
|
||||
|
||||
print(f"{status} {ip:20} -> {str(result):5} "
|
||||
f"(expected: {str(expected):5}) # {description}")
|
||||
|
||||
print(f"\nПройдено: {passed}/{passed + failed}")
|
||||
return failed == 0
|
||||
|
||||
|
||||
def test_is_ip_allowed():
|
||||
"""Тест проверки разрешенных IP с кастомными настройками."""
|
||||
print("\n=== Тест: is_ip_allowed ===")
|
||||
|
||||
# Тест 1: Разрешить все
|
||||
print("\n1. Разрешить все IP ['*']:")
|
||||
result = is_ip_allowed('203.0.113.50', ['*'])
|
||||
status = '✅' if result else '❌'
|
||||
print(f" {status} 203.0.113.50 -> {result} (expected: True)")
|
||||
|
||||
# Тест 2: Разрешить конкретную сеть
|
||||
print("\n2. Разрешить сеть 192.168.1.0/24:")
|
||||
allowed_net = ['192.168.1.0/24']
|
||||
tests = [
|
||||
('192.168.1.1', True),
|
||||
('192.168.1.100', True),
|
||||
('192.168.1.255', True),
|
||||
('192.168.2.1', False),
|
||||
('10.0.0.1', False),
|
||||
]
|
||||
|
||||
for ip, expected in tests:
|
||||
result = is_ip_allowed(ip, allowed_net)
|
||||
status = "✅" if result == expected else "❌"
|
||||
print(f" {status} {ip:20} -> {str(result):5} "
|
||||
f"(expected: {str(expected):5})")
|
||||
|
||||
# Тест 3: Разрешить конкретные IP
|
||||
print("\n3. Разрешить IP ['192.168.1.100', '10.0.0.5']:")
|
||||
allowed_ips = ['192.168.1.100', '10.0.0.5']
|
||||
tests = [
|
||||
('192.168.1.100', True),
|
||||
('10.0.0.5', True),
|
||||
('192.168.1.101', False),
|
||||
('10.0.0.6', False),
|
||||
]
|
||||
|
||||
for ip, expected in tests:
|
||||
result = is_ip_allowed(ip, allowed_ips)
|
||||
status = "✅" if result == expected else "❌"
|
||||
print(f" {status} {ip:20} -> {str(result):5} "
|
||||
f"(expected: {str(expected):5})")
|
||||
|
||||
# Тест 4: По умолчанию (только локальные)
|
||||
print("\n4. По умолчанию (None = только локальные IP):")
|
||||
tests = [
|
||||
('127.0.0.1', True),
|
||||
('192.168.1.1', True),
|
||||
('10.0.0.1', True),
|
||||
('8.8.8.8', False),
|
||||
('203.0.113.50', False),
|
||||
]
|
||||
|
||||
for ip, expected in tests:
|
||||
result = is_ip_allowed(ip, None)
|
||||
status = "✅" if result == expected else "❌"
|
||||
print(f" {status} {ip:20} -> {str(result):5} "
|
||||
f"(expected: {str(expected):5})")
|
||||
|
||||
|
||||
def main():
|
||||
"""Запуск всех тестов."""
|
||||
print("=" * 60)
|
||||
print("Тестирование модуля IP-ограничений")
|
||||
print("=" * 60)
|
||||
|
||||
try:
|
||||
test_is_local_ip()
|
||||
test_is_ip_allowed()
|
||||
|
||||
print("\n" + "=" * 60)
|
||||
print("✅ Все тесты выполнены успешно")
|
||||
print("=" * 60)
|
||||
|
||||
except Exception as e:
|
||||
print(f"\n❌ Ошибка: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
exit(main())
|
||||
Loading…
x
Reference in New Issue
Block a user