vpn integration
This commit is contained in:
+22
-12
@@ -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
@@ -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
@@ -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])
|
||||
|
||||
@@ -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
@@ -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,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
@@ -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
@@ -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
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user