First Commit

This commit is contained in:
mrtoine 2025-09-12 11:11:44 +02:00
commit ce0758fbbb
496 changed files with 52062 additions and 0 deletions

0
users/__init__.py Executable file
View file

30
users/admin.py Executable file
View file

@ -0,0 +1,30 @@
from django.contrib import admin
# admin.py des utilisateurs
from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from django.contrib.auth.models import Group
from .models import User
# Register your models here.
class UserAdmin(BaseUserAdmin):
model = User
fieldsets = (
(None, {'fields': ('username', 'username_decoration', 'password')}),
('Informations personnelles', {'fields': ('first_name', 'last_name', 'email', 'theme', 'avatar', 'border_avatar', 'biography', 'birth_date')}),
('Permissions', {'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions')}),
('Dates importantes', {'fields': ('last_login', 'date_joined')}),
)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('username', 'password1', 'password2'),
}),
)
list_display = ('username', 'email', 'first_name', 'last_name', 'is_staff')
search_fields = ('username', 'email', 'first_name', 'last_name')
admin.site.register(User, UserAdmin)

6
users/apps.py Executable file
View file

@ -0,0 +1,6 @@
from django.apps import AppConfig
class UsersConfig(AppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "users"

13
users/decorators.py Executable file
View file

@ -0,0 +1,13 @@
from django.core.exceptions import PermissionDenied
from django.contrib.auth.decorators import login_required
def groups_required(*group_names):
def decorator(view_func):
@login_required
def _wrapped_view(request, *args, **kwargs):
if any(request.user.groups.filter(name=group_name).exists() for group_name in group_names):
return view_func(request, *args, **kwargs)
else:
raise PermissionDenied
return _wrapped_view
return decorator

79
users/forms.py Executable file
View file

@ -0,0 +1,79 @@
from django import forms
from .models import User
class UserRegistrationForm(forms.Form):
username = forms.CharField(
label='',
max_length=150,
widget=forms.TextInput(attrs={'class': 'form-group', 'placeholder': 'Pseudo'})
)
email = forms.EmailField(
label='',
widget=forms.EmailInput(attrs={'class': 'form-group', 'placeholder': 'Email'})
)
password1 = forms.CharField(
label='',
widget=forms.PasswordInput(attrs={'class': 'form-group', 'placeholder': 'Mot de passe'})
)
password2 = forms.CharField(
label='',
widget=forms.PasswordInput(attrs={'class': 'form-group', 'placeholder': 'Mot de passe (vérification)'})
)
def clean(self):
cleaned_data = super().clean()
password1 = cleaned_data.get("password1")
password2 = cleaned_data.get("password2")
if password1 and password2 and password1 != password2:
raise forms.ValidationError("Passwords do not match")
class UserLoginForm(forms.Form):
username = forms.CharField(
label='',
max_length=150,
widget=forms.TextInput(attrs={'class': 'form-group', 'placeholder': 'Pseudo'})
)
password = forms.CharField(
label='',
widget=forms.PasswordInput(attrs={'class': 'form-group', 'placeholder': 'Mot de passe'})
)
class UserUpdateForm(forms.ModelForm):
theme = forms.CharField(
# On créer une liste de choix pour le thème
label='Thème',
widget=forms.Select(choices=[('default', 'Thème par defaut'), ('80s', 'Thème années 80'), ('00s', 'Thème années 2000 (adapté pour mobiles)')]),
)
class Meta:
model = User
labels = {
'avatar': 'Avatar',
'email': 'Email',
'first_name': 'Prénom',
'last_name': 'Nom',
'biography': 'Biographie',
}
fields = ['avatar', 'email', 'first_name', 'last_name', 'biography']
class ProfileUpdateForm(forms.ModelForm):
class Meta:
model = User
fields = ['avatar', 'biography']
class CompleteProfileForm(forms.ModelForm):
class Meta:
model = User
fields = ['avatar', 'birth_date', 'biography']
class PostForm(forms.Form):
title = forms.CharField(
max_length=150,
label='',
widget=forms.TextInput(attrs={'placeholder': 'Titre de l\'article'})
)
content = forms.CharField(
label='',
widget=forms.Textarea(attrs={'placeholder': 'Contenu de l\'article'})
)

113
users/middleware.py Executable file
View file

@ -0,0 +1,113 @@
# yourapp/middleware.py
from django.shortcuts import redirect
from django.core.cache import cache
from django.utils import timezone
from .models import User, VisitorStats
from messagerie.models import PrivateMessage, PrivateMessageSubject
from django.utils.deprecation import MiddlewareMixin
from django.contrib import messages
# On vérifie que l'user existe dans la table user_level. Si pas, on le redirige vers la page tuto de la nouvelle feature
class UserLevelMiddleware(MiddlewareMixin):
# On vérifie que l'on est pas sur la page de tuto de la nouvelle feature
def process_request(self, request):
if request.user.is_authenticated:
if request.path != '/users/new/feature':
if not request.user.levels.exists():
return redirect('new_feature_user')
if request.path != '/users/new/feature':
if not request.user.inventory.exists():
return redirect('new_feature_user')
class UserLevelUpMiddleware(MiddlewareMixin):
def process_request(self, request):
if request.user.is_authenticated and request.user.levels.exists():
if not request.session.get('level_up_processed', False):
user = request.user
user_level = user.level # Accède à l'objet UserLevel associé à l'utilisateur
# Calcul de l'XP requise pour le prochain niveau
def xp_required(level):
return int(33.33 * (level ** 2) - 16.66 * level)
if user_level.experience >= xp_required(user_level.level):
user_level.level += 1
user_level.save()
messages.success(request, f"Bravo ! Vous avez atteint le niveau {user_level.level} !")
subject = PrivateMessageSubject.objects.create(
receiver=user,
sender=User.objects.get(username='RetroBot'),
subject=f"Bravo { request.user } ! Tu as atteint un nouveau niveau !"
)
PrivateMessage.objects.create(
subject=subject,
author=User.objects.get(username='RetroBot'),
message=f"""[b]🎉 Félicitations {request.user}! 🎉[/b]
Tu viens de passer au [b]Niveau Supérieur[/b] ! Tu es maintenant [b]Niveau { user_level.level }[/b] !
💰 En récompense, tu gagnes [b]20 Or[/b] ! 💰
[i]Continue tes efforts, aventurier, et vise toujours plus haut ![/i]
"""
)
# Marquez le niveau comme traité pour cette requête
request.session['level_up_processed'] = True
# Ajouter 20 Or à l'inventaire de l'utilisateur
if request.user.inventory.exists():
inventory_item = request.user.inventory.get(item__name='Or')
inventory_item.quantity += 20
inventory_item.save()
# On affiche l'experience restante pour le prochain niveau
request.user.experience_left = xp_required(user_level.level) - user_level.experience
else:
# On affiche l'expérience restante pour le prochain niveau même si le niveau n'a pas changé
user_level = request.user.level
def xp_required(level):
return int(33.33 * (level ** 2) - 16.66 * level)
request.user.experience_left = xp_required(user_level.level) - user_level.experience
class UserStatsMiddleware(MiddlewareMixin):
def process_request(self, request):
# Nombre total d'utilisateurs
total_users = User.objects.count()
# Dernier utilisateur inscrit
last_user = User.objects.latest('date_joined') if total_users > 0 else None
# Gestion des visiteurs actuels
current_time = timezone.now()
visitor_key = request.session.session_key or request.META.get('REMOTE_ADDR')
# Mise à jour du cache des visiteurs actuels
active_visitors = cache.get('active_visitors', set())
active_visitors.add(visitor_key)
cache.set('active_visitors', active_visitors, 300) # expire après 5 minutes
visitor_count = len(active_visitors)
# Gestion du total des visiteurs
stats, created = VisitorStats.objects.get_or_create(pk=1)
if 'first_visit' not in request.session:
request.session['first_visit'] = True
stats.total_visitors += 1
stats.save()
total_visitor_count = stats.total_visitors
# Si l'utilisateur est authentifié
if request.user.is_authenticated:
theme_active = request.user.theme
else:
theme_active = '00s'
# Ajouter les variables à l'objet request
request.total_users = total_users
request.last_user = last_user
request.visitor_count = visitor_count
request.total_visitor_count = total_visitor_count
request.theme_active = theme_active

View file

@ -0,0 +1,138 @@
# Generated by Django 4.2.16 on 2024-10-21 18:39
import django.contrib.auth.models
import django.contrib.auth.validators
from django.db import migrations, models
import django.utils.timezone
class Migration(migrations.Migration):
initial = True
dependencies = [
("auth", "0012_alter_user_first_name_max_length"),
]
operations = [
migrations.CreateModel(
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"
),
),
(
"email",
models.EmailField(
blank=True, max_length=254, verbose_name="email address"
),
),
(
"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"
),
),
(
"avatar",
models.ImageField(
default="avatars/default.png", upload_to="avatars/"
),
),
("biography", models.TextField(default="Pas de bio")),
("birth_date", models.DateField(blank=True, null=True)),
(
"groups",
models.ManyToManyField(
blank=True,
help_text="The groups this user belongs to.",
related_name="customuser_set",
to="auth.group",
verbose_name="groups",
),
),
(
"user_permissions",
models.ManyToManyField(
blank=True,
help_text="Specific permissions for this user.",
related_name="customuser_permissions_set",
to="auth.permission",
verbose_name="user permissions",
),
),
],
options={
"verbose_name": "user",
"verbose_name_plural": "users",
"abstract": False,
},
managers=[
("objects", django.contrib.auth.models.UserManager()),
],
),
]

View file

@ -0,0 +1,26 @@
# Generated by Django 4.2.16 on 2024-10-21 21:29
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("users", "0001_initial"),
]
operations = [
migrations.AlterModelOptions(
name="user",
options={
"ordering": ["username"],
"verbose_name": "Utilisateur",
"verbose_name_plural": "Utilisateurs",
},
),
migrations.AlterField(
model_name="user",
name="avatar",
field=models.ImageField(default="default.gif", upload_to="avatars/"),
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 4.2.16 on 2024-10-22 10:56
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("users", "0002_alter_user_options_alter_user_avatar"),
]
operations = [
migrations.AddField(
model_name="user",
name="active",
field=models.BooleanField(default=True),
),
]

View file

@ -0,0 +1,25 @@
# Generated by Django 4.2.16 on 2024-10-23 17:04
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("users", "0003_user_active"),
]
operations = [
migrations.AddField(
model_name="user",
name="theme",
field=models.CharField(default="default", max_length=50),
),
migrations.AlterField(
model_name="user",
name="avatar",
field=models.ImageField(
default="avatars/default.gif", upload_to="avatars/"
),
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 4.2.17 on 2024-12-16 13:35
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0004_user_theme_alter_user_avatar'),
]
operations = [
migrations.AlterField(
model_name='user',
name='active',
field=models.BooleanField(default=False),
),
]

View file

@ -0,0 +1,24 @@
# Generated by Django 4.2.17 on 2024-12-23 14:31
from django.db import migrations, models
import users.models
class Migration(migrations.Migration):
dependencies = [
('users', '0005_alter_user_active'),
]
operations = [
migrations.AlterField(
model_name='user',
name='avatar',
field=models.ImageField(default='media/avatars/default.gif', upload_to=users.models.user_avatar_path),
),
migrations.AlterField(
model_name='user',
name='email',
field=models.EmailField(max_length=254),
),
]

View file

@ -0,0 +1,19 @@
# Generated by Django 4.2.17 on 2024-12-23 16:48
from django.db import migrations, models
import users.models
class Migration(migrations.Migration):
dependencies = [
('users', '0006_alter_user_avatar_alter_user_email'),
]
operations = [
migrations.AlterField(
model_name='user',
name='avatar',
field=models.ImageField(default='avatars/default.gif', upload_to=users.models.user_avatar_path),
),
]

View file

@ -0,0 +1,21 @@
# Generated by Django 4.2.17 on 2025-01-04 12:07
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0007_alter_user_avatar'),
]
operations = [
migrations.CreateModel(
name='VisitorStats',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('total_visitors', models.PositiveIntegerField(default=0)),
('last_reset', models.DateTimeField(auto_now=True)),
],
),
]

View file

@ -0,0 +1,29 @@
# Generated by Django 4.2.17 on 2025-01-06 17:27
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('users', '0008_visitorstats'),
]
operations = [
migrations.CreateModel(
name='UserLevel',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('level', models.PositiveIntegerField(default=1)),
('experience', models.PositiveIntegerField(default=0)),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='levels', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'Niveau utilisateur',
'verbose_name_plural': 'Niveaux utilisateurs',
'ordering': ['level'],
},
),
]

View file

@ -0,0 +1,23 @@
# Generated by Django 4.2.17 on 2025-01-06 18:46
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0009_userlevel'),
]
operations = [
migrations.AlterField(
model_name='user',
name='first_name',
field=models.CharField(blank=True, max_length=30),
),
migrations.AlterField(
model_name='user',
name='last_name',
field=models.CharField(blank=True, max_length=150),
),
]

View file

@ -0,0 +1,30 @@
# Generated by Django 4.2.17 on 2025-01-07 10:47
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('shop', '0001_initial'),
('users', '0010_alter_user_first_name_alter_user_last_name'),
]
operations = [
migrations.CreateModel(
name='UserInventory',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('quantity', models.PositiveIntegerField(default=1)),
('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='shop.item')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='inventory', to=settings.AUTH_USER_MODEL)),
],
options={
'verbose_name': 'Inventaire utilisateur',
'verbose_name_plural': 'Inventaires utilisateurs',
'ordering': ['item'],
},
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 4.2.17 on 2025-01-07 13:43
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0011_userinventory'),
]
operations = [
migrations.AddField(
model_name='user',
name='border_avatar',
field=models.CharField(default='', max_length=50),
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 4.2.17 on 2025-01-07 13:47
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0012_user_border_avatar'),
]
operations = [
migrations.AddField(
model_name='user',
name='username_decoration',
field=models.CharField(default='', max_length=50),
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 4.2.17 on 2025-01-07 16:41
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0013_user_username_decoration'),
]
operations = [
migrations.AlterField(
model_name='user',
name='username_decoration',
field=models.CharField(blank=True, max_length=50, null=True),
),
]

View file

@ -0,0 +1,18 @@
# Generated by Django 4.2.17 on 2025-01-07 16:41
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('users', '0014_alter_user_username_decoration'),
]
operations = [
migrations.AlterField(
model_name='user',
name='border_avatar',
field=models.CharField(blank=True, max_length=50, null=True),
),
]

0
users/migrations/__init__.py Executable file
View file

87
users/models.py Executable file
View file

@ -0,0 +1,87 @@
from django.contrib.auth.models import AbstractUser, Group, Permission
from django.db import models
from shop.models import Item
def user_avatar_path(instance, filename):
return f'avatars/{instance.id}/{filename}'
class User(AbstractUser):
avatar = models.ImageField(upload_to=user_avatar_path, default='avatars/default.gif')
email = models.EmailField(unique=False)
biography = models.TextField(default='Pas de bio')
first_name = models.CharField(max_length=30, blank=True)
last_name = models.CharField(max_length=150, blank=True)
birth_date = models.DateField(null=True, blank=True)
active = models.BooleanField(default=False)
theme = models.CharField(max_length=50, default='default')
border_avatar = models.CharField(max_length=50, blank=True, null=True)
username_decoration = models.CharField(max_length=50, blank=True, null=True)
groups = models.ManyToManyField(
Group,
related_name='customuser_set', # Ajoutez un related_name unique
blank=True,
help_text='The groups this user belongs to.',
verbose_name='groups',
)
user_permissions = models.ManyToManyField(
Permission,
related_name='customuser_permissions_set', # Ajoutez un related_name unique
blank=True,
help_text='Specific permissions for this user.',
verbose_name='user permissions',
)
@property
def level(self):
return self.levels.first()
@property
def experience(self):
return self.levels.get(user=self).experience
@property
def inventory(self):
return self.inventory.all()
@property
def money(self):
return self.inventory.get(item__name='Or').quantity
def __str__(self):
return self.username
class Meta:
verbose_name = 'Utilisateur'
verbose_name_plural = 'Utilisateurs'
ordering = ['username']
class VisitorStats(models.Model):
total_visitors = models.PositiveIntegerField(default=0)
last_reset = models.DateTimeField(auto_now=True)
class UserLevel(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='levels')
level = models.PositiveIntegerField(default=1)
experience = models.PositiveIntegerField(default=0)
def __str__(self):
return self.level
class Meta:
verbose_name = 'Niveau utilisateur'
verbose_name_plural = 'Niveaux utilisateurs'
ordering = ['level']
class UserInventory(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='inventory')
item = models.ForeignKey(Item, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField(default=1)
def __str__(self):
return self.item.name
class Meta:
verbose_name = 'Inventaire utilisateur'
verbose_name_plural = 'Inventaires utilisateurs'
ordering = ['item']

0
users/templatetags/__init__.py Executable file
View file

View file

@ -0,0 +1,7 @@
from django import template
register = template.Library()
@register.filter(name='has_group')
def has_group(user, group_name):
return user.groups.filter(name=group_name).exists()

3
users/tests.py Executable file
View file

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

22
users/urls.py Executable file
View file

@ -0,0 +1,22 @@
from django.urls import path
from django.conf.urls.static import static
from django.contrib.auth import views as auth_views
from passion_retro import settings
from . import views
urlpatterns = [
path('activate/<uidb64>/<token>/', views.activate, name='activate'),
path("login/", views.login, name="login"),
path("register/", views.register, name="register"),
path("profile/", views.profile, name="profile"),
path("profile/update/", views.profile_update, name="profile_update"),
path("profile/contributions/", views.contributions, name="contributions"),
path("profile/<str:user_id>/", views.another_profile, name="profile"),
path("contribute/", views.contribute, name="contribute"),
path("contribute/<str:type>/", views.form_contribute, name="form_contribute"),
path("new/feature", views.new_feature_user, name="new_feature_user"),
path("item/use/<int:item_id>/", views.use_item, name="use_item"),
path('logout/', auth_views.LogoutView.as_view(), name='logout'),
]

308
users/views.py Executable file
View file

@ -0,0 +1,308 @@
from django.shortcuts import render, redirect
from django.contrib.auth import authenticate, login as auth_login
from django.contrib.auth.forms import AuthenticationForm
from django.contrib import messages
from django.contrib.auth.decorators import login_required
from .forms import PostForm, UserRegistrationForm, UserLoginForm, UserUpdateForm, ProfileUpdateForm
from posts.models import Post
from django.utils.text import slugify
from django.template.loader import render_to_string
from django.core.mail import send_mail
from django.conf import settings
from django.contrib.auth.tokens import PasswordResetTokenGenerator
from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode
from django.utils.encoding import force_bytes, force_str
from .models import User, UserLevel
from django.db.models import F
import urllib.request
import json
def register(request):
from messagerie.models import PrivateMessageSubject, PrivateMessage
if request.user.is_authenticated:
return redirect('profile')
if request.method == "POST":
form = UserRegistrationForm(request.POST)
recaptcha = request.POST.get('g-recaptcha-response')
if form.is_valid():
url = 'https://www.google.com/recaptcha/api/siteverify'
values = {
'secret': settings.GOOGLE_PRIVATE_KEY,
'response': recaptcha
}
data = urllib.parse.urlencode(values).encode()
req = urllib.request.Request(url, data=data)
response = urllib.request.urlopen(req)
result = json.loads(response.read().decode())
if result['success']:
user = User.objects.create_user(
username=form.cleaned_data['username'],
email=form.cleaned_data['email'],
password=form.cleaned_data['password1'],
theme='00s',
active=True
)
messages.success(request, f"Bonjour et bienvenue {user.username} ! Ton compte à été créer avec succès. Tu peux désormais te connecter.")
subject = PrivateMessageSubject.objects.create(
receiver=user,
sender=User.objects.get(username='RetroBot'),
subject="Bienvenue sur PassionRetro !"
)
PrivateMessage.objects.create(
subject=subject,
author=User.objects.get(username='RetroBot'),
message=f"""[b]Bienvenue sur Passion Retro ![/b]
Salut [b]{user.username}[/b] !,
Merci de nous avoir rejoints dans cette aventure dédiée aux passionnés de rétro ! Que tu sois fan de consoles vintage, collectionneur d'objets d'époque ou simple curieux, tu es ici chez toi.
[b]Découvre tout ce que Passion Retro a à offrir :[/b]
Plonge dans nos articles pour en apprendre plus sur les trésors du passé, participe aux discussions sur le forum et teste tes connaissances avec nos jeux rétro. Chaque section est pour te permettre de partager ta passion et d'en apprendre davantage.
🚀 [b]Rejoins la communauté :[/b]
Ton avis et tes contributions sont précieux ! Nhésite pas à lancer une discussion sur le forum, à réagir aux articles ou à défier les autres membres sur nos jeux. Plus nous sommes actifs, plus lexpérience sera enrichissante pour tous.
Si tu as des questions ou des suggestions pour améliorer le site, contacte-nous. Nous sommes pour t'accompagner !
Encore une fois, bienvenue parmi nous et prépare-toi à replonger dans lunivers du rétro !
À bientôt,
[b]L'équipe Passion Retro[/b]""")
return redirect('login')
else:
messages.error(request, f"On y est presque ! Vérifie bien le captcha pour finaliser ton inscription.")
form = UserRegistrationForm()
return render(request, 'users/register.html', {'form': form, 'GOOGLE_PUBLIC_KEY': settings.GOOGLE_PUBLIC_KEY})
def register_with_token(request):
# Si l'utilisateur est deja connecté, on le redirige vers la page de pr>
if request.user.is_authenticated:
return redirect('profile')
if request.method == 'POST':
form = UserRegistrationForm(request.POST)
if form.is_valid():
user = User.objects.create_user(
username=form.cleaned_data['username'],
email=form.cleaned_data['email'],
password=form.cleaned_data['password1']
)
genToken = PasswordResetTokenGenerator()
token = genToken.make_token(user)
uid = urlsafe_base64_encode(force_bytes(user.pk))
activation_link = request.build_absolute_uri(f"/users/activate/{uid}/{token}")
email_subject = 'Activation de votre compte'
email_body = render_to_string('emails/activation_account.html', {
'user': user,
'activation_link': activation_link,
})
send_mail(
email_subject,
email_body,
settings.DEFAULT_FROM_EMAIL,
[user.email],
fail_silently=False,
)
messages.success(request, f"Ton compte a été créé avec succès, {user.username}! Un email d'activation t'a été envoyé pour valider ton inscription.")
return redirect('login')
else:
form = UserRegistrationForm()
return render(request, 'users/register.html', {'form': form})
def activate(request, uidb64, token):
uid = None # Initialisation de la variable uid
try:
uid = force_str(urlsafe_base64_decode(uidb64))
user = User.objects.get(pk=uid)
except (TypeError, ValueError, OverflowError, User.DoesNotExist):
user = None
token_generator = PasswordResetTokenGenerator()
if user is not None and token_generator.check_token(user, token):
user.active = True
user.save()
messages.success(request, "Votre compte a été activé avec succès.")
return redirect('login')
else:
messages.error(request, "Le lien d'activation est invalide.")
return redirect('register')
def login(request):
if request.method == 'POST':
form = UserLoginForm(data=request.POST)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(request, username=username, password=password)
if user is None:
messages.error(request, "Nom d'utilisateur ou mot de passe incorrect.")
return redirect('login')
if user.active == False:
messages.error(request, "Votre compte n'est pas activé. Veuillez vérifier votre boîte mail.")
return redirect('login')
auth_login(request, user)
messages.success(request, f"Bienvenue, {username}!")
return redirect('home')
else:
messages.error(request, "Nom d'utilisateur ou mot de passe incorrect.")
else:
form = UserLoginForm()
return render(request, 'users/login.html', {'form': form})
def profile(request):
from forum.models import Topic, Post
from posts.models import Post
user = User.objects.get(id=request.user.id)
# On compte le nombre de topics du forum de l'utilisateur
topics = Topic.objects.filter(author=user).count()
forum_posts = Post.objects.filter(author=user).count()
posts = Post.objects.filter(author=user).count()
return render(request, 'users/profile.html', { 'user': user, 'topics': topics, 'forum_posts': forum_posts, 'posts': posts })
def another_profile(request, user_id):
from forum.models import Topic, Post
from posts.models import Post
user = User.objects.get(id=user_id)
# On compte le nombre de topics du forum de l'utilisateur
topics = Topic.objects.filter(author=user).count()
forum_posts = Post.objects.filter(author=user).count()
posts = Post.objects.filter(author=user).count()
return render(request, 'users/profile.html', {'user': user, 'topics': topics, 'forum_posts': forum_posts, 'posts': posts})
@login_required(login_url='login')
def profile_update(request):
if request.method == 'POST':
user_form = UserUpdateForm(request.POST, request.FILES, instance=request.user)
if user_form.is_valid():
user_form.save()
messages.success(request, 'Votre profil a été mis à jour avec succès !')
return redirect('profile')
else:
user_form = UserUpdateForm(instance=request.user)
return render(request, 'users/profile_update.html', {'user_form': user_form})
@login_required
def contribute(request):
return render(request, "users/contribute.html")
@login_required(login_url='register')
def form_contribute(request, type):
if request.method == 'POST':
# Initialisation des articles
form = PostForm(request.POST)
posts = []
# Traite l'article principal (parent)
main_title = request.POST.get('title') # Titre principal du formulaire Django
main_content = request.POST.get('content') # Contenu principal
parent_post = None
if main_title and main_content:
# Crée le parent
parent_post = Post.objects.create(
title=main_title,
slug=slugify(main_title),
content=main_content,
type=type,
author=request.user,
contribution=True,
parent=True
)
posts.append(parent_post)
UserLevel.objects.update(user=request.user, experience=F('experience') + 10)
# Vérifie si des articles dynamiques existent (type_form = multiple)
type_form = request.POST.get('type_form')
if type_form == 'multiple':
# Parcourt les champs dynamiques ajoutés en JS
for key in request.POST:
if key.startswith('title-post-'):
# Récupère le numéro de l'article
article_number = key.split('-')[-1]
# Récupère les données de l'article enfant
title = request.POST.get(f'title-post-{article_number}')
content = request.POST.get(f'content-post-{article_number}')
if title and content:
# Crée l'article enfant
child_post = Post.objects.create(
title=title,
slug=slugify(title),
content=content,
type=type,
author=request.user,
contribution=True,
parent=False,
post_parent=parent_post
)
posts.append(child_post)
UserLevel.objects.update(user=request.user, experience=F('experience') + 5)
messages.success(request, "Vos articles ont été soumis avec succès !")
context = {
'type': type,
'form': PostForm(),
}
return render(request, "users/form_contribute.html", context)
@login_required()
def contributions(request):
posts = Post.objects.filter(author=request.user)
return render(request, "users/contributions.html", {'posts':posts})
@login_required
def new_feature_user(request):
# On créer une entree dans la table user_level pour l'utilisateur si il n'en a pas
if not request.user.level:
request.user.levels.create(level=1)
return render(request, "features/new_feature_user_level.html")
if not request.user.inventory.exists():
request.user.inventory.create(item_id=1, quantity=100)
return render(request, "features/new_feature_user_inventory.html")
@login_required
def use_item(request, item_id):
item = request.user.inventory.get(item_id=item_id)
# On slugify le nom de l'item pour l'utiliser dans les conditions
item_name = slugify(item.item.name)
if item.quantity > 0:
if item.item.category.name == 'cadres':
request.user.border_avatar = item_name
if item.item.category.name == 'themes':
request.user.theme_active = item_name
if item.item.category.name == 'Décoration pseudo':
request.user.username_decoration = item_name
request.user.save()
messages.success(request, f"Vous avez utilisé {item.item.name}.")
else:
messages.error(request, f"Vous n'avez pass de {item.item.name}.")
return redirect('profile')