logging attckers try and add location to admin
This commit is contained in:
@@ -10,6 +10,12 @@ from django.contrib.auth.models import Group
|
||||
from unfold.forms import AdminPasswordChangeForm
|
||||
from unfold.forms import AdminPasswordChangeForm, UserChangeForm, UserCreationForm
|
||||
from utils.admin import ModelAdmin
|
||||
from django.template.loader import render_to_string
|
||||
from folium import Map, Marker
|
||||
from unfold.decorators import action, display
|
||||
from django.utils.html import format_html
|
||||
|
||||
|
||||
class UserAddressInLine(TabularInline):
|
||||
model = UserAddressModel
|
||||
extra = 0
|
||||
@@ -95,4 +101,37 @@ class PushSubscription(ModelAdmin, ImportExportModelAdmin):
|
||||
import_form_class = ImportForm
|
||||
export_form_class = ExportForm
|
||||
compressed_fields = True
|
||||
warn_unsaved_form = True
|
||||
warn_unsaved_form = True
|
||||
|
||||
|
||||
|
||||
@admin.register(SecurityBreachAttemptModel)
|
||||
class SecurityBreachAttemptAdmin(ModelAdmin, ImportExportModelAdmin):
|
||||
import_form_class = ImportForm
|
||||
export_form_class = ExportForm
|
||||
compressed_fields = True
|
||||
warn_unsaved_form = True
|
||||
change_form_template = 'loction_chagne_form.html'
|
||||
list_display = ['ip', 'country', 'region_name', 'city', 'zip_code', 'isp', 'created_at', 'trys', 'display_viewd']
|
||||
|
||||
def change_view(self, request, object_id, form_url='', extra_context=None):
|
||||
extra_context = extra_context or {}
|
||||
obj = self.get_object(request, object_id)
|
||||
|
||||
if obj and obj.lat and obj.lon:
|
||||
m = Map(location=[obj.lat, obj.lon], zoom_start=10)
|
||||
Marker([obj.lat, obj.lon], popup=f"Location: {obj.ip}").add_to(m)
|
||||
map_html = m._repr_html_()
|
||||
extra_context['map_html'] = map_html
|
||||
return super().change_view(request, object_id, form_url, extra_context)
|
||||
|
||||
@display(description='دیده شده')
|
||||
def display_viewd(self, instance):
|
||||
if instance.viewd:
|
||||
svg = f'<a href="/accounts/attack/view/{instance.id}"><svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 24 24"><path fill="green" d="M12 16q1.875 0 3.188-1.312T16.5 11.5t-1.312-3.187T12 7T8.813 8.313T7.5 11.5t1.313 3.188T12 16m0-1.8q-1.125 0-1.912-.788T9.3 11.5t.788-1.912T12 8.8t1.913.788t.787 1.912t-.787 1.913T12 14.2m0 4.8q-3.65 0-6.65-2.037T1 11.5q1.35-3.425 4.35-5.462T12 4t6.65 2.038T23 11.5q-1.35 3.425-4.35 5.463T12 19m0-2q2.825 0 5.188-1.487T20.8 11.5q-1.25-2.525-3.613-4.012T12 6T6.813 7.488T3.2 11.5q1.25 2.525 3.613 4.013T12 17"/></svg></a>'
|
||||
else:
|
||||
svg = f'<a href="/accounts/attack/view/{instance.id}"><svg xmlns="http://www.w3.org/2000/svg" width="25" height="25" viewBox="0 0 24 24"><path fill="#c30009" d="m19.1 21.9l-3.5-3.45q-.875.275-1.775.413T12 19q-3.35 0-6.125-1.8t-4.35-4.75q-.125-.225-.187-.462t-.063-.488t.063-.488t.187-.462q.55-.975 1.175-1.9T4.15 7L2.075 4.9Q1.8 4.625 1.8 4.213t.3-.713q.275-.275.7-.275t.7.275l17 17q.275.275.288.688t-.288.712q-.275.275-.7.275t-.7-.275M12 16q.275 0 .525-.025t.5-.1l-5.4-5.4q-.075.25-.1.5T7.5 11.5q0 1.875 1.313 3.188T12 16m0-12q3.35 0 6.138 1.813t4.362 4.762q.125.2.188.438t.062.487t-.05.488t-.175.437q-.475.925-1.062 1.75t-1.313 1.55q-.35.35-.825.325t-.825-.375l-2-2q-.175-.175-.225-.413t.025-.487q.1-.325.15-.625t.05-.65q0-1.875-1.312-3.187T12 7q-.35 0-.65.05t-.625.15q-.25.075-.5.025T9.8 7l-.825-.825q-.475-.475-.312-1.1t.787-.8q.625-.125 1.263-.2T12 4m1.975 5.65q.275.325.462.713t.238.812q.025.2-.15.275t-.325-.075l-2.05-2.05Q12 9.175 12.088 9t.287-.175q.475.05.875.263t.725.562"/></svg></a>'
|
||||
|
||||
return format_html(
|
||||
svg
|
||||
)
|
||||
@@ -0,0 +1,31 @@
|
||||
# Generated by Django 5.1.2 on 2025-02-20 20:25
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('account', '0014_alter_pushsubscription_created_at_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='SecurityBreachAttemptModel',
|
||||
fields=[
|
||||
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('ip', models.CharField(max_length=40, unique=True, verbose_name='آدرس آی\u200cپی')),
|
||||
('country', models.CharField(blank=True, max_length=40, null=True, verbose_name='کشور')),
|
||||
('region_name', models.CharField(blank=True, max_length=40, null=True, verbose_name='منطقه')),
|
||||
('city', models.CharField(blank=True, max_length=40, null=True, verbose_name='شهر')),
|
||||
('zip_code', models.CharField(blank=True, max_length=40, null=True, verbose_name='کد پستی')),
|
||||
('lon', models.CharField(blank=True, max_length=40, null=True, verbose_name='طول جغرافیایی')),
|
||||
('lat', models.CharField(blank=True, max_length=40, null=True, verbose_name='عرض جغرافیایی')),
|
||||
('isp', models.CharField(blank=True, max_length=40, null=True, verbose_name='ارائه\u200cدهنده اینترنت (ISP)')),
|
||||
],
|
||||
options={
|
||||
'verbose_name': 'تلاش نفوذ',
|
||||
'verbose_name_plural': 'تلاش\u200cهای نفوذ',
|
||||
},
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,18 @@
|
||||
# Generated by Django 5.1.2 on 2025-02-20 21:17
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('account', '0015_securitybreachattemptmodel'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='securitybreachattemptmodel',
|
||||
name='viewd',
|
||||
field=models.BooleanField(default=False, verbose_name='تماشا شده'),
|
||||
),
|
||||
]
|
||||
@@ -0,0 +1,25 @@
|
||||
# Generated by Django 5.1.2 on 2025-02-20 21:35
|
||||
|
||||
import django.utils.timezone
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('account', '0016_securitybreachattemptmodel_viewd'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='securitybreachattemptmodel',
|
||||
name='created_at',
|
||||
field=models.DateField(auto_now_add=True, default=django.utils.timezone.now),
|
||||
preserve_default=False,
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='securitybreachattemptmodel',
|
||||
name='trys',
|
||||
field=models.IntegerField(default=0),
|
||||
),
|
||||
]
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
# Generated by Django 5.1.2 on 2025-02-20 21:37
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('account', '0017_securitybreachattemptmodel_created_at_and_more'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AlterField(
|
||||
model_name='securitybreachattemptmodel',
|
||||
name='created_at',
|
||||
field=models.DateTimeField(auto_now_add=True, verbose_name='شروع حمله'),
|
||||
),
|
||||
migrations.AlterField(
|
||||
model_name='securitybreachattemptmodel',
|
||||
name='trys',
|
||||
field=models.IntegerField(default=0, verbose_name='تعداد تلاش ها'),
|
||||
),
|
||||
]
|
||||
@@ -198,4 +198,46 @@ class PushSubscription(models.Model):
|
||||
}
|
||||
)
|
||||
except WebPushException as ex:
|
||||
print(f"Failed to send notification to {sub.user}:", ex)
|
||||
print(f"Failed to send notification to {sub.user}:", ex)
|
||||
|
||||
|
||||
|
||||
def get_location_from_ip(ip_address):
|
||||
try:
|
||||
response = requests.get(f"http://ip-api.com/json/{ip_address}")
|
||||
data = response.json()
|
||||
if data["status"] == "success":
|
||||
return data['country'], data['regionName'], data['city'], data.get('zip', 'ناموجود'), data['lat'], data['lon'], data['isp']
|
||||
else:
|
||||
print("Error fetching data: ", data["message"])
|
||||
return None
|
||||
except Exception as e:
|
||||
print(f"An error occurred: {e}")
|
||||
return None
|
||||
|
||||
class SecurityBreachAttemptModel(models.Model):
|
||||
ip = models.CharField(max_length=40, unique=True, verbose_name="آدرس آیپی")
|
||||
country = models.CharField(max_length=40, verbose_name="کشور", blank=True, null=True)
|
||||
region_name = models.CharField(max_length=40, verbose_name="منطقه", blank=True, null=True)
|
||||
city = models.CharField(max_length=40, verbose_name="شهر", blank=True, null=True)
|
||||
zip_code = models.CharField(max_length=40, verbose_name="کد پستی", blank=True, null=True)
|
||||
lon = models.CharField(max_length=40, verbose_name="طول جغرافیایی", blank=True, null=True)
|
||||
lat = models.CharField(max_length=40, verbose_name="عرض جغرافیایی", blank=True, null=True)
|
||||
isp = models.CharField(max_length=40, verbose_name="ارائهدهنده اینترنت (ISP)", blank=True, null=True)
|
||||
viewd = models.BooleanField(default=False, verbose_name='تماشا شده')
|
||||
created_at = models.DateTimeField(auto_now_add=True, verbose_name='شروع حمله')
|
||||
trys = models.IntegerField(default=0, verbose_name='تعداد تلاش ها')
|
||||
|
||||
def save(self, *args, **kwargs):
|
||||
if not self.id:
|
||||
location_data = get_location_from_ip(self.ip)
|
||||
if location_data:
|
||||
self.country, self.region_name, self.city, self.zip_code, self.lat, self.lon, self.isp = location_data
|
||||
|
||||
super().save(*args, **kwargs)
|
||||
|
||||
def __str__(self):
|
||||
return f'تلاش نفوذ از {self.ip} در {self.city}, {self.country}'
|
||||
class Meta:
|
||||
verbose_name = "تلاش نفوذ"
|
||||
verbose_name_plural = "تلاشهای نفوذ"
|
||||
@@ -12,5 +12,6 @@ urlpatterns = [
|
||||
path('address/delete/<int:pk>', views.DeleteAddressView.as_view(), name='delete-address'),
|
||||
path('address/list', views.GetUserAddressesView.as_view(), name='list-addresses'),
|
||||
path('address/<int:pk>', views.GetIDUserAddressView.as_view(), name='get-ID-address'),
|
||||
path('subscribe', views.SubscribeView.as_view(), name='subscibe')
|
||||
path('subscribe', views.SubscribeView.as_view(), name='subscibe'),
|
||||
path('attack/view/<int:pk>', views.ChangeViewAttack.as_view(), name='attack-view'),
|
||||
]
|
||||
@@ -3,13 +3,14 @@ from rest_framework.views import APIView
|
||||
from rest_framework import generics, permissions, status
|
||||
from rest_framework.response import Response
|
||||
from .serializers import *
|
||||
from .models import UserAddressModel, User
|
||||
from .models import UserAddressModel, User, SecurityBreachAttemptModel
|
||||
from rest_framework.permissions import IsAuthenticated, AllowAny
|
||||
from drf_spectacular.utils import extend_schema, OpenApiParameter
|
||||
from rest_framework_simplejwt.views import TokenObtainPairView
|
||||
from django.shortcuts import get_object_or_404
|
||||
from django.shortcuts import get_object_or_404, redirect
|
||||
from rest_framework_simplejwt.tokens import RefreshToken
|
||||
import ghasedak_sms
|
||||
from django.views import View
|
||||
# this works only need to be used
|
||||
# class APIView(APIView):
|
||||
# def __init__(self, *args, **kwargs):
|
||||
@@ -185,4 +186,12 @@ class SubscribeView(APIView):
|
||||
defaults=(push_ser.validated_data)
|
||||
)
|
||||
return Response(status=status.HTTP_201_CREATED)
|
||||
return Response(status=status.HTTP_400_BAD_REQUEST)
|
||||
return Response(status=status.HTTP_400_BAD_REQUEST)
|
||||
|
||||
|
||||
class ChangeViewAttack(View):
|
||||
def get(self, request, pk):
|
||||
attack = get_object_or_404(SecurityBreachAttemptModel, pk=pk)
|
||||
attack.viewd = not attack.viewd
|
||||
attack.save()
|
||||
return redirect('admin:account_securitybreachattemptmodel_changelist')
|
||||
Reference in New Issue
Block a user