vpn integration

This commit is contained in:
2026-04-11 22:07:59 +02:00
parent c4d27e9842
commit 00ac38d126
47 changed files with 945 additions and 749 deletions
+22 -12
View File
@@ -2,8 +2,8 @@ from django.contrib import admin
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.template.defaultfilters import filesizeformat
from .forms import UserCreationForm, UserChangeForm
from .models import User, FriendRequest, Invitation
from .forms import UserChangeForm
from .models import FriendRequest, Invitation, User
@admin.register(User)
@@ -12,26 +12,36 @@ class UserAdmin(BaseUserAdmin):
# add_form = UserCreationForm
form = UserChangeForm
fieldsets = BaseUserAdmin.fieldsets + (
["Custom Fields", {
"fields": ["max_size", "friends"]
}]
,)
list_display = ["username", "email", "is_superuser", "is_active", "is_staff", "display_max_size", "size_used"]
["Custom Fields", {"fields": ["max_size", "friends"]}],
)
list_display = [
"username",
"email",
"is_superuser",
"is_active",
"is_staff",
"display_max_size",
"size_used",
]
add_fieldsets = (
(None, {
"classes": ("wide",),
"fields": ("username", "email", "max_size", "password1", "password2"),
}),
(
None,
{
"classes": ("wide",),
"fields": ("username", "email", "max_size", "password1", "password2"),
},
),
)
def display_max_size(self, obj: User):
return filesizeformat(obj.max_size)
display_max_size.short_description = "Max size"
def size_used(self, obj: User):
return filesizeformat(obj.size_used)
size_used.short_description = "Size used"
size_used.short_description = "Size used"
@admin.register(Invitation)
+2 -2
View File
@@ -2,5 +2,5 @@ from django.apps import AppConfig
class UserConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'user'
default_auto_field = "django.db.models.BigAutoField"
name = "user"
+1 -1
View File
@@ -15,6 +15,7 @@ class RegisterForm(base_auth_forms.UserCreationForm):
class UserCreationForm(AdminUserCreationForm):
max_size = forms.IntegerField(required=True)
email = forms.EmailField(required=True)
class Meta(base_auth_forms.UserCreationForm):
model = User
fields = base_auth_forms.BaseUserCreationForm.Meta.fields + ("max_size",)
@@ -24,4 +25,3 @@ class UserChangeForm(base_auth_forms.UserChangeForm):
class Meta:
model = User
fields = ["max_size"]
@@ -1,9 +1,9 @@
from django.core.management.base import BaseCommand
import json
import base64
import json
import sys
from django.core.management.base import BaseCommand
from user.models import User
@@ -26,7 +26,9 @@ class Command(BaseCommand):
user_data = data["fields"]
user_pk = data["pk"]
if User.objects.filter(username__iexact=user_data["username"]).exists():
old_new_users_maps[user_pk] = User.objects.filter(username__iexact=user_data["username"]).get()
old_new_users_maps[user_pk] = User.objects.filter(
username__iexact=user_data["username"]
).get()
else:
old_new_users_maps[user_pk] = User.objects.create(
email=user_data["email"],
@@ -35,12 +37,14 @@ class Command(BaseCommand):
is_superuser=user_data["is_superuser"],
username=user_data["username"],
password=user_data["password"],
max_size=user_data["limit_size"]
max_size=user_data["limit_size"],
)
old_friends[user_pk] = user_data["friends"]
for old_user, friends in old_friends.items():
current_user = old_new_users_maps[old_user]
for friend in friends:
if not current_user.friends.filter(id=old_new_users_maps[friend].id).exists():
if not current_user.friends.filter(
id=old_new_users_maps[friend].id
).exists():
current_user.friends.add(old_new_users_maps[friend])
+170 -37
View File
@@ -1,72 +1,205 @@
# Generated by Django 5.1.6 on 2025-03-04 23:41
import uuid
import django.contrib.auth.validators
import django.db.models.deletion
import django.utils.timezone
import user.models
import uuid
from django.conf import settings
from django.db import migrations, models
import user.models
class Migration(migrations.Migration):
initial = True
dependencies = [
('auth', '0012_alter_user_first_name_max_length'),
("auth", "0012_alter_user_first_name_max_length"),
]
operations = [
migrations.CreateModel(
name='User',
name="User",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('password', models.CharField(max_length=128, verbose_name='password')),
('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
('username', models.CharField(error_messages={'unique': 'A user with that username already exists.'}, help_text='Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=150, unique=True, validators=[django.contrib.auth.validators.UnicodeUsernameValidator()], verbose_name='username')),
('first_name', models.CharField(blank=True, max_length=150, verbose_name='first name')),
('last_name', models.CharField(blank=True, max_length=150, verbose_name='last name')),
('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
('is_active', models.BooleanField(default=True, help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', verbose_name='active')),
('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
('email', models.EmailField(max_length=254, unique=True)),
('max_size', models.PositiveBigIntegerField(default=53687091200)),
('is_trusted', models.BooleanField(default=False)),
('friends', models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL)),
('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')),
('user_permissions', models.ManyToManyField(blank=True, help_text='Specific permissions for this user.', related_name='user_set', related_query_name='user', to='auth.permission', verbose_name='user permissions')),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("password", models.CharField(max_length=128, verbose_name="password")),
(
"last_login",
models.DateTimeField(
blank=True, null=True, verbose_name="last login"
),
),
(
"is_superuser",
models.BooleanField(
default=False,
help_text="Designates that this user has all permissions without explicitly assigning them.",
verbose_name="superuser status",
),
),
(
"username",
models.CharField(
error_messages={
"unique": "A user with that username already exists."
},
help_text="Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.",
max_length=150,
unique=True,
validators=[
django.contrib.auth.validators.UnicodeUsernameValidator()
],
verbose_name="username",
),
),
(
"first_name",
models.CharField(
blank=True, max_length=150, verbose_name="first name"
),
),
(
"last_name",
models.CharField(
blank=True, max_length=150, verbose_name="last name"
),
),
(
"is_staff",
models.BooleanField(
default=False,
help_text="Designates whether the user can log into this admin site.",
verbose_name="staff status",
),
),
(
"is_active",
models.BooleanField(
default=True,
help_text="Designates whether this user should be treated as active. Unselect this instead of deleting accounts.",
verbose_name="active",
),
),
(
"date_joined",
models.DateTimeField(
default=django.utils.timezone.now, verbose_name="date joined"
),
),
("email", models.EmailField(max_length=254, unique=True)),
("max_size", models.PositiveBigIntegerField(default=53687091200)),
("is_trusted", models.BooleanField(default=False)),
(
"friends",
models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL),
),
(
"groups",
models.ManyToManyField(
blank=True,
help_text="The groups this user belongs to. A user will get all permissions granted to each of their groups.",
related_name="user_set",
related_query_name="user",
to="auth.group",
verbose_name="groups",
),
),
(
"user_permissions",
models.ManyToManyField(
blank=True,
help_text="Specific permissions for this user.",
related_name="user_set",
related_query_name="user",
to="auth.permission",
verbose_name="user permissions",
),
),
],
options={
'verbose_name': 'user',
'verbose_name_plural': 'users',
'abstract': False,
"verbose_name": "user",
"verbose_name_plural": "users",
"abstract": False,
},
managers=[
('objects', user.models.UsernameUserManager()),
("objects", user.models.UsernameUserManager()),
],
),
migrations.CreateModel(
name='Invitation',
name="Invitation",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('token', models.UUIDField(default=uuid.uuid4)),
('date_created', models.DateTimeField(auto_now_add=True)),
('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='invitations', to=settings.AUTH_USER_MODEL)),
('user', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='invitation', to=settings.AUTH_USER_MODEL)),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("token", models.UUIDField(default=uuid.uuid4)),
("date_created", models.DateTimeField(auto_now_add=True)),
(
"created_by",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="invitations",
to=settings.AUTH_USER_MODEL,
),
),
(
"user",
models.OneToOneField(
blank=True,
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="invitation",
to=settings.AUTH_USER_MODEL,
),
),
],
),
migrations.CreateModel(
name='FriendRequest',
name="FriendRequest",
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('date', models.DateTimeField(auto_now_add=True)),
('receiver', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='friend_request_receives', to=settings.AUTH_USER_MODEL)),
('sender', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='friend_request_sends', to=settings.AUTH_USER_MODEL)),
(
"id",
models.BigAutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("date", models.DateTimeField(auto_now_add=True)),
(
"receiver",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="friend_request_receives",
to=settings.AUTH_USER_MODEL,
),
),
(
"sender",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="friend_request_sends",
to=settings.AUTH_USER_MODEL,
),
),
],
options={
'unique_together': {('sender', 'receiver')},
"unique_together": {("sender", "receiver")},
},
),
]
+17 -8
View File
@@ -1,9 +1,10 @@
from django.db import models
from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.db.models import Sum
import uuid
from functools import cached_property
from django.contrib.auth.models import AbstractUser, BaseUserManager
from django.db import models
from django.db.models import Sum
from torrent.models import Torrent
@@ -53,7 +54,9 @@ class User(AbstractUser):
if hasattr(self, "total_size"):
return self.total_size
else:
return Torrent.objects.filter(user=self).aggregate(total_size=Sum("size", default=0))["total_size"]
return Torrent.objects.filter(user=self).aggregate(
total_size=Sum("size", default=0)
)["total_size"]
@property
def min_infos(self):
@@ -61,8 +64,12 @@ class User(AbstractUser):
class FriendRequest(models.Model):
sender = models.ForeignKey("User", on_delete=models.CASCADE, related_name="friend_request_sends")
receiver = models.ForeignKey("User", on_delete=models.CASCADE, related_name="friend_request_receives")
sender = models.ForeignKey(
"User", on_delete=models.CASCADE, related_name="friend_request_sends"
)
receiver = models.ForeignKey(
"User", on_delete=models.CASCADE, related_name="friend_request_receives"
)
date = models.DateTimeField(auto_now_add=True)
class Meta:
@@ -72,5 +79,7 @@ class FriendRequest(models.Model):
class Invitation(models.Model):
created_by = models.ForeignKey("User", models.CASCADE, related_name="invitations")
token = models.UUIDField(default=uuid.uuid4)
user = models.OneToOneField("User", models.CASCADE, related_name="invitation", null=True, blank=True)
user = models.OneToOneField(
"User", models.CASCADE, related_name="invitation", null=True, blank=True
)
date_created = models.DateTimeField(auto_now_add=True)
+1 -1
View File
@@ -1,6 +1,6 @@
from rest_framework import serializers
from .models import User, FriendRequest, Invitation
from .models import FriendRequest, Invitation, User
class UserSerializer(serializers.ModelSerializer):
+80 -115
View File
@@ -1,26 +1,25 @@
from unittest.mock import MagicMock, patch
from django.test import TestCase
from django.urls import reverse
from rest_framework.test import APITestCase, APIClient
from rest_framework import status
from unittest.mock import patch, MagicMock
from rest_framework.test import APIClient, APITestCase
from .models import User, FriendRequest, Invitation, UsernameUserManager
from torrent.models import Torrent
from .views import UserViewSet, FriendRequestViewSet
from .models import FriendRequest, Invitation, User
class UserModelTestCase(TestCase):
def setUp(self):
self.user = User.objects.create_user(
username='testuser',
email='test@example.com',
password='testpassword',
max_size=1000000
username="testuser",
email="test@example.com",
password="testpassword",
max_size=1000000,
)
self.friend = User.objects.create_user(
username='frienduser',
email='friend@example.com',
password='friendpassword'
username="frienduser", email="friend@example.com", password="friendpassword"
)
def test_size_used_property(self):
@@ -30,35 +29,32 @@ class UserModelTestCase(TestCase):
# Create a torrent for the user
Torrent.objects.create(
id='abc123',
name='Test Torrent',
id="abc123",
name="Test Torrent",
user=self.user,
size=5000,
transmission_data={}
transmission_data={},
)
# Create another torrent
Torrent.objects.create(
id='def456',
name='Another Torrent',
id="def456",
name="Another Torrent",
user=self.user,
size=3000,
transmission_data={}
transmission_data={},
)
# Clear cached_property if it exists
if hasattr(self.user, 'total_size'):
delattr(self.user, 'total_size')
if hasattr(self.user, "total_size"):
delattr(self.user, "total_size")
# Size used should be the sum of torrent sizes
self.assertEqual(self.user.size_used, 8000)
def test_min_infos_property(self):
"""Test the min_infos property returns the correct user info"""
expected_info = {
'username': 'testuser',
'id': self.user.id
}
expected_info = {"username": "testuser", "id": self.user.id}
self.assertEqual(self.user.min_infos, expected_info)
@@ -66,111 +62,86 @@ class UsernameUserManagerTestCase(TestCase):
def test_create_user(self):
"""Test creating a regular user"""
user = User.objects.create_user(
username='newuser',
email='new@example.com',
password='newpassword'
username="newuser", email="new@example.com", password="newpassword"
)
self.assertFalse(user.is_staff)
self.assertFalse(user.is_superuser)
self.assertEqual(user.username, 'newuser')
self.assertEqual(user.email, 'new@example.com')
self.assertTrue(user.check_password('newpassword'))
self.assertEqual(user.username, "newuser")
self.assertEqual(user.email, "new@example.com")
self.assertTrue(user.check_password("newpassword"))
def test_create_superuser(self):
"""Test creating a superuser"""
admin = User.objects.create_superuser(
username='admin',
email='admin@example.com',
password='adminpassword'
username="admin", email="admin@example.com", password="adminpassword"
)
self.assertTrue(admin.is_staff)
self.assertTrue(admin.is_superuser)
self.assertEqual(admin.username, 'admin')
self.assertEqual(admin.email, 'admin@example.com')
self.assertEqual(admin.username, "admin")
self.assertEqual(admin.email, "admin@example.com")
def test_create_user_without_username(self):
"""Test creating a user without username raises error"""
with self.assertRaises(ValueError):
User.objects.create_user(
username='',
email='test@example.com',
password='testpassword'
username="", email="test@example.com", password="testpassword"
)
def test_create_user_without_email(self):
"""Test creating a user without email raises error"""
with self.assertRaises(ValueError):
User.objects.create_user(
username='testuser',
email='',
password='testpassword'
username="testuser", email="", password="testpassword"
)
class FriendRequestModelTestCase(TestCase):
def setUp(self):
self.sender = User.objects.create_user(
username='sender',
email='sender@example.com',
password='senderpassword'
username="sender", email="sender@example.com", password="senderpassword"
)
self.receiver = User.objects.create_user(
username='receiver',
email='receiver@example.com',
password='receiverpassword'
username="receiver",
email="receiver@example.com",
password="receiverpassword",
)
def test_friend_request_creation(self):
"""Test creating a friend request"""
friend_request = FriendRequest.objects.create(
sender=self.sender,
receiver=self.receiver
sender=self.sender, receiver=self.receiver
)
self.assertEqual(friend_request.sender, self.sender)
self.assertEqual(friend_request.receiver, self.receiver)
def test_unique_together_constraint(self):
"""Test that the unique_together constraint works"""
FriendRequest.objects.create(
sender=self.sender,
receiver=self.receiver
)
FriendRequest.objects.create(sender=self.sender, receiver=self.receiver)
# Creating another request with the same sender and receiver should raise an error
with self.assertRaises(Exception):
FriendRequest.objects.create(
sender=self.sender,
receiver=self.receiver
)
FriendRequest.objects.create(sender=self.sender, receiver=self.receiver)
class InvitationModelTestCase(TestCase):
def setUp(self):
self.creator = User.objects.create_user(
username='creator',
email='creator@example.com',
password='creatorpassword'
username="creator", email="creator@example.com", password="creatorpassword"
)
def test_invitation_creation(self):
"""Test creating an invitation"""
invitation = Invitation.objects.create(
created_by=self.creator
)
invitation = Invitation.objects.create(created_by=self.creator)
self.assertEqual(invitation.created_by, self.creator)
self.assertIsNotNone(invitation.token)
self.assertIsNone(invitation.user)
def test_invitation_assignment(self):
"""Test assigning an invitation to a user"""
invitation = Invitation.objects.create(
created_by=self.creator
)
invitation = Invitation.objects.create(created_by=self.creator)
new_user = User.objects.create_user(
username='newuser',
email='new@example.com',
password='newpassword'
username="newuser", email="new@example.com", password="newpassword"
)
invitation.user = new_user
@@ -184,133 +155,127 @@ class InvitationModelTestCase(TestCase):
class UserViewSetTestCase(APITestCase):
def setUp(self):
self.user = User.objects.create_user(
username='testuser',
email='test@example.com',
password='testpassword'
username="testuser", email="test@example.com", password="testpassword"
)
self.friend = User.objects.create_user(
username='frienduser',
email='friend@example.com',
password='friendpassword'
username="frienduser", email="friend@example.com", password="friendpassword"
)
self.client = APIClient()
self.client.force_authenticate(user=self.user)
def test_list_users(self):
"""Test listing users"""
url = reverse('user-list')
url = reverse("user-list")
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(len(response.data), 2) # Should include both users
def test_retrieve_user(self):
"""Test retrieving a specific user"""
url = reverse('user-detail', args=[self.friend.id])
url = reverse("user-detail", args=[self.friend.id])
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data['username'], 'frienduser')
self.assertEqual(response.data["username"], "frienduser")
def test_add_friend_request(self):
"""Test adding a friend request"""
url = reverse('user-add-friend-request', args=[self.friend.username])
url = reverse("user-add-friend-request", args=[self.friend.username])
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertTrue(response.data['success'])
self.assertEqual(response.data['message'], 'Request sent')
self.assertTrue(response.data["success"])
self.assertEqual(response.data["message"], "Request sent")
# Verify the friend request was created
self.assertTrue(FriendRequest.objects.filter(
sender=self.user,
receiver=self.friend
).exists())
self.assertTrue(
FriendRequest.objects.filter(
sender=self.user, receiver=self.friend
).exists()
)
def test_add_friend_request_nonexistent_user(self):
"""Test adding a friend request to a nonexistent user"""
url = reverse('user-add-friend-request', args=['nonexistentuser'])
url = reverse("user-add-friend-request", args=["nonexistentuser"])
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertFalse(response.data['success'])
self.assertEqual(response.data['message'], "User 'nonexistentuser' doesn't exist")
self.assertFalse(response.data["success"])
self.assertEqual(
response.data["message"], "User 'nonexistentuser' doesn't exist"
)
def test_remove_friend(self):
"""Test removing a friend"""
# First add as friend
self.user.friends.add(self.friend)
url = reverse('user-remove-friend', args=[self.friend.id])
url = reverse("user-remove-friend", args=[self.friend.id])
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertTrue(response.data['success'])
self.assertTrue(response.data["success"])
# Verify the friend was removed
self.assertFalse(self.user.friends.filter(id=self.friend.id).exists())
@patch('user.views.shutil.disk_usage')
@patch("user.views.shutil.disk_usage")
def test_user_stats(self, mock_disk_usage):
"""Test getting user stats"""
# Mock disk_usage return value
mock_disk_usage.return_value = MagicMock(
total=1000000,
used=500000,
free=500000
total=1000000, used=500000, free=500000
)
# Create torrents for the user
Torrent.objects.create(
id='abc123',
name='Test Torrent',
id="abc123",
name="Test Torrent",
user=self.user,
size=5000,
transmission_data={}
transmission_data={},
)
url = reverse('user-user-stats')
url = reverse("user-user-stats")
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
# Check that the response contains the expected fields
self.assertIn('torrents_size', response.data)
self.assertIn('torrents_len', response.data)
self.assertIn('user_max_size', response.data)
self.assertIn('disk_total', response.data)
self.assertIn('disk_used', response.data)
self.assertIn('disk_free', response.data)
self.assertIn("torrents_size", response.data)
self.assertIn("torrents_len", response.data)
self.assertIn("user_max_size", response.data)
self.assertIn("disk_total", response.data)
self.assertIn("disk_used", response.data)
self.assertIn("disk_free", response.data)
class FriendRequestViewSetTestCase(APITestCase):
def setUp(self):
self.user = User.objects.create_user(
username='testuser',
email='test@example.com',
password='testpassword'
username="testuser", email="test@example.com", password="testpassword"
)
self.sender = User.objects.create_user(
username='sender',
email='sender@example.com',
password='senderpassword'
username="sender", email="sender@example.com", password="senderpassword"
)
self.client = APIClient()
self.client.force_authenticate(user=self.user)
# Create a friend request
self.friend_request = FriendRequest.objects.create(
sender=self.sender,
receiver=self.user
sender=self.sender, receiver=self.user
)
def test_list_friend_requests(self):
"""Test listing friend requests"""
url = reverse('friendrequest-list')
url = reverse("friendrequest-list")
response = self.client.get(url)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(len(response.data), 1)
self.assertEqual(response.data[0]['sender']['username'], 'sender')
self.assertEqual(response.data[0]["sender"]["username"], "sender")
def test_delete_friend_request(self):
"""Test deleting a friend request"""
url = reverse('friendrequest-detail', args=[self.friend_request.id])
url = reverse("friendrequest-detail", args=[self.friend_request.id])
response = self.client.delete(url)
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
# Verify the friend request was deleted
self.assertFalse(FriendRequest.objects.filter(id=self.friend_request.id).exists())
self.assertFalse(
FriendRequest.objects.filter(id=self.friend_request.id).exists()
)
+1 -1
View File
@@ -1,6 +1,6 @@
from django.urls import path
from .views import UserLoginView, RegisterView
from .views import RegisterView, UserLoginView
app_name = "user"
urlpatterns = [
+50 -38
View File
@@ -1,20 +1,19 @@
from django.contrib.auth.views import LoginView
from django.views.generic import CreateView
from django.contrib.auth import login
from django.urls import reverse_lazy
from django.db.models import Count, Sum, F, IntegerField
from django.db.models.functions import Coalesce
import shutil
from rest_framework.viewsets import ModelViewSet, GenericViewSet
from django.contrib.auth import login
from django.contrib.auth.views import LoginView
from django.db.models import Count, Sum
from django.db.models.functions import Coalesce
from django.urls import reverse_lazy
from django.views.generic import CreateView
from rest_framework import mixins
from rest_framework.decorators import action
from rest_framework.response import Response
import shutil
from rest_framework.viewsets import GenericViewSet
from .models import User, FriendRequest, Invitation
from .forms import RegisterForm
from .serializers import UserSerializer, FriendRequestSerializer, InvitationSerializer
from .models import FriendRequest, Invitation, User
from .serializers import FriendRequestSerializer, UserSerializer
class UserLoginView(LoginView):
@@ -31,7 +30,9 @@ class RegisterView(CreateView):
invitation = None
def get_form(self, form_class=None):
self.invitation = Invitation.objects.get(token=self.kwargs.get("token"), user__isnull=True)
self.invitation = Invitation.objects.get(
token=self.kwargs.get("token"), user__isnull=True
)
return super().get_form(form_class)
def form_valid(self, form):
@@ -42,9 +43,7 @@ class RegisterView(CreateView):
return r
class UserViewSet(mixins.RetrieveModelMixin,
mixins.ListModelMixin,
GenericViewSet):
class UserViewSet(mixins.RetrieveModelMixin, mixins.ListModelMixin, GenericViewSet):
queryset = User.objects.all().annotate(
count_torrent=Count("torrents") + Count("torrents_shares")
)
@@ -72,18 +71,22 @@ class UserViewSet(mixins.RetrieveModelMixin,
return Response({"success": False, "message": "Already friend"})
elif FriendRequest.objects.filter(sender=user, receiver=receiver).exists():
# déjà une demande en attente
return Response({"success": False, "message": "Friend request Already sent"})
return Response(
{"success": False, "message": "Friend request Already sent"}
)
elif FriendRequest.objects.filter(sender=receiver, receiver=user).exists():
# friend request en cours, on accepte
FriendRequest.objects.filter(sender=receiver, receiver=user).delete()
user.friends.add(receiver)
return Response({"success": True, "message": f"{receiver.username} added to your friend list"})
return Response(
{
"success": True,
"message": f"{receiver.username} added to your friend list",
}
)
else:
# aucune demande en cours, on créer un friend request
FriendRequest.objects.create(
sender=user,
receiver=receiver
)
FriendRequest.objects.create(sender=user, receiver=receiver)
return Response({"success": True, "message": "Request sent"})
@action(methods=["get"], detail=True)
@@ -91,8 +94,13 @@ class UserViewSet(mixins.RetrieveModelMixin,
friend = User.objects.get(pk=pk)
if self.request.user.friends.filter(pk=friend.pk).exists():
self.request.user.friends.remove(friend)
return Response({"success": True, "message": f"The friend {friend.username} successfully removed"})
return Response({"success": False, "message": f"error"})
return Response(
{
"success": True,
"message": f"The friend {friend.username} successfully removed",
}
)
return Response({"success": False, "message": "error"})
@action(methods=["get"], detail=False)
def user_stats(self, request):
@@ -104,23 +112,27 @@ class UserViewSet(mixins.RetrieveModelMixin,
disk_usage = shutil.disk_usage("/")
return Response({
"torrents_size": stats["total_size"],
"torrents_len": stats["total_torrent"],
"torrent_len_shared": stats["total_shared_torrent"],
"torrents_total_len": stats["total_torrent"] + stats["total_shared_torrent"],
"user_max_size": request.user.max_size,
"user_usage_percent": (stats["total_size"] / request.user.max_size) * 100,
"disk_total": disk_usage.total,
"disk_used": disk_usage.used,
"disk_free": disk_usage.free,
"disk_usage_percent": (disk_usage.used / disk_usage.total) * 100,
})
return Response(
{
"torrents_size": stats["total_size"],
"torrents_len": stats["total_torrent"],
"torrent_len_shared": stats["total_shared_torrent"],
"torrents_total_len": stats["total_torrent"]
+ stats["total_shared_torrent"],
"user_max_size": request.user.max_size,
"user_usage_percent": (stats["total_size"] / request.user.max_size)
* 100,
"disk_total": disk_usage.total,
"disk_used": disk_usage.used,
"disk_free": disk_usage.free,
"disk_usage_percent": (disk_usage.used / disk_usage.total) * 100,
}
)
class FriendRequestViewSet(mixins.ListModelMixin,
mixins.DestroyModelMixin,
GenericViewSet):
class FriendRequestViewSet(
mixins.ListModelMixin, mixins.DestroyModelMixin, GenericViewSet
):
queryset = FriendRequest.objects.all()
serializer_class = FriendRequestSerializer