renator commited on
Commit
99122b8
·
1 Parent(s): 610ba5b
README.md CHANGED
@@ -1,11 +1,2 @@
1
- ---
2
- title: Voice Clone
3
- emoji: 🦀
4
- colorFrom: green
5
- colorTo: purple
6
- sdk: docker
7
- pinned: false
8
- license: mit
9
- ---
10
 
11
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
1
 
2
+ title: Voice Clone
accounts/admin.py CHANGED
@@ -1,3 +1,50 @@
1
  from django.contrib import admin
 
2
 
3
- # Register your models here.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  from django.contrib import admin
2
+ from django.contrib.auth.admin import UserAdmin
3
 
4
+ from .models import User
5
+
6
+
7
+ class AdminUser(UserAdmin):
8
+ list_display = ["email", "first_name", "last_name", "role", "is_active", "created"]
9
+
10
+ fieldsets = (
11
+ (
12
+ None,
13
+ {
14
+ "fields": (
15
+ "first_name",
16
+ "last_name",
17
+ "mobile",
18
+ "email",
19
+ "password",
20
+ )
21
+ },
22
+ ),
23
+ (
24
+ "Permissions",
25
+ {
26
+ "fields": (
27
+ "role",
28
+ "is_active",
29
+ "is_staff",
30
+ "is_superuser",
31
+ "user_permissions",
32
+ )
33
+ },
34
+ ),
35
+ )
36
+ add_fieldsets = (
37
+ (None, {"classes": ("wide",), "fields": ("email", "password1", "password2")}),
38
+ )
39
+
40
+ list_filter = ("role", "is_active")
41
+ search_fields = ("email", "first_name", "last_name")
42
+ ordering = ("email",)
43
+ filter_horizontal = (
44
+ "groups",
45
+ "user_permissions",
46
+ )
47
+
48
+
49
+ admin.site.register(User, AdminUser)
50
+ # admin.site.unregister(Group)
accounts/migrations/0001_initial.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by Django 5.0.1 on 2024-04-02 09:30
2
+
3
+ import django.contrib.auth.models
4
+ import django.contrib.auth.validators
5
+ import django.utils.timezone
6
+ from django.db import migrations, models
7
+
8
+
9
+ class Migration(migrations.Migration):
10
+
11
+ initial = True
12
+
13
+ dependencies = [
14
+ ('auth', '0012_alter_user_first_name_max_length'),
15
+ ]
16
+
17
+ operations = [
18
+ migrations.CreateModel(
19
+ name='User',
20
+ fields=[
21
+ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
22
+ ('password', models.CharField(max_length=128, verbose_name='password')),
23
+ ('last_login', models.DateTimeField(blank=True, null=True, verbose_name='last login')),
24
+ ('is_superuser', models.BooleanField(default=False, help_text='Designates that this user has all permissions without explicitly assigning them.', verbose_name='superuser status')),
25
+ ('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')),
26
+ ('is_staff', models.BooleanField(default=False, help_text='Designates whether the user can log into this admin site.', verbose_name='staff status')),
27
+ ('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')),
28
+ ('date_joined', models.DateTimeField(default=django.utils.timezone.now, verbose_name='date joined')),
29
+ ('email', models.EmailField(max_length=254, unique=True)),
30
+ ('first_name', models.CharField(max_length=150)),
31
+ ('last_name', models.CharField(max_length=150)),
32
+ ('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')),
33
+ ('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')),
34
+ ],
35
+ options={
36
+ 'verbose_name': 'user',
37
+ 'verbose_name_plural': 'users',
38
+ 'abstract': False,
39
+ },
40
+ managers=[
41
+ ('objects', django.contrib.auth.models.UserManager()),
42
+ ],
43
+ ),
44
+ ]
accounts/migrations/0002_alter_user_options_alter_user_managers_and_more.py ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Generated by Django 5.0.1 on 2024-04-02 09:44
2
+
3
+ import django.core.validators
4
+ import django.utils.timezone
5
+ from django.db import migrations, models
6
+
7
+
8
+ class Migration(migrations.Migration):
9
+
10
+ dependencies = [
11
+ ('accounts', '0001_initial'),
12
+ ]
13
+
14
+ operations = [
15
+ migrations.AlterModelOptions(
16
+ name='user',
17
+ options={'verbose_name': 'User', 'verbose_name_plural': 'Users'},
18
+ ),
19
+ migrations.AlterModelManagers(
20
+ name='user',
21
+ managers=[
22
+ ],
23
+ ),
24
+ migrations.RemoveField(
25
+ model_name='user',
26
+ name='username',
27
+ ),
28
+ migrations.AddField(
29
+ model_name='user',
30
+ name='address',
31
+ field=models.TextField(blank=True, null=True, verbose_name='Address'),
32
+ ),
33
+ migrations.AddField(
34
+ model_name='user',
35
+ name='city',
36
+ field=models.CharField(blank=True, max_length=50, null=True, verbose_name='City/Town'),
37
+ ),
38
+ migrations.AddField(
39
+ model_name='user',
40
+ name='country',
41
+ field=models.CharField(blank=True, max_length=50, null=True, verbose_name='Country'),
42
+ ),
43
+ migrations.AddField(
44
+ model_name='user',
45
+ name='created',
46
+ field=models.DateTimeField(auto_now_add=True, default=django.utils.timezone.now),
47
+ preserve_default=False,
48
+ ),
49
+ migrations.AddField(
50
+ model_name='user',
51
+ name='mobile',
52
+ field=models.CharField(blank=True, max_length=17, null=True, validators=[django.core.validators.RegexValidator(message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.", regex='^\\+?1?\\d{9,15}$')], verbose_name='mobile'),
53
+ ),
54
+ migrations.AddField(
55
+ model_name='user',
56
+ name='modified',
57
+ field=models.DateTimeField(auto_now=True),
58
+ ),
59
+ migrations.AddField(
60
+ model_name='user',
61
+ name='role',
62
+ field=models.PositiveSmallIntegerField(choices=[(1, 'Admin'), (2, 'User')], default=2, verbose_name='role'),
63
+ ),
64
+ migrations.AddField(
65
+ model_name='user',
66
+ name='state',
67
+ field=models.CharField(blank=True, max_length=50, null=True, verbose_name='State/Province'),
68
+ ),
69
+ migrations.AddField(
70
+ model_name='user',
71
+ name='zip_code',
72
+ field=models.CharField(blank=True, max_length=50, null=True),
73
+ ),
74
+ migrations.AlterField(
75
+ model_name='user',
76
+ name='date_joined',
77
+ field=models.DateTimeField(auto_now_add=True, verbose_name='date joined'),
78
+ ),
79
+ migrations.AlterField(
80
+ model_name='user',
81
+ name='email',
82
+ field=models.EmailField(max_length=254, unique=True, verbose_name='email address'),
83
+ ),
84
+ migrations.AlterField(
85
+ model_name='user',
86
+ name='first_name',
87
+ field=models.CharField(blank=True, max_length=50, null=True, verbose_name='First Name'),
88
+ ),
89
+ migrations.AlterField(
90
+ model_name='user',
91
+ name='is_active',
92
+ field=models.BooleanField(default=True),
93
+ ),
94
+ migrations.AlterField(
95
+ model_name='user',
96
+ name='is_staff',
97
+ field=models.BooleanField(default=False),
98
+ ),
99
+ migrations.AlterField(
100
+ model_name='user',
101
+ name='last_name',
102
+ field=models.CharField(blank=True, max_length=50, null=True, verbose_name='Last Name'),
103
+ ),
104
+ ]
accounts/models.py CHANGED
@@ -1,3 +1,111 @@
 
 
 
1
  from django.db import models
 
 
2
 
3
- # Create your models here.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Create your models here.
2
+ from django.contrib.auth.base_user import BaseUserManager
3
+ from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
4
  from django.db import models
5
+ from django.utils.translation import gettext_lazy as _
6
+ from django.core.validators import RegexValidator
7
 
8
+ from .task import send_email_to_user
9
+
10
+
11
+ class BaseModel(models.Model):
12
+ created = models.DateTimeField(auto_now_add=True, editable=False)
13
+ modified = models.DateTimeField(auto_now=True, editable=False)
14
+
15
+ class Meta:
16
+ abstract = True
17
+
18
+
19
+ class UserManager(BaseUserManager):
20
+ """
21
+ Custom user model manager where email is the unique identifiers
22
+ for authentication instead of usernames.
23
+ """
24
+
25
+ def create_user(self, email, password, **extra_fields):
26
+ """
27
+ Create and save a User with the given email and password.
28
+ """
29
+ if not email:
30
+ raise ValueError(_("The Email must be set"))
31
+ email = self.normalize_email(email)
32
+ user = self.model(email=email, **extra_fields)
33
+ user.set_password(password)
34
+ user.save()
35
+ return user
36
+
37
+ def create_superuser(self, email, password, **extra_fields):
38
+ """
39
+ Create and save a SuperUser with the given email and password.
40
+ """
41
+ extra_fields.setdefault("is_staff", True)
42
+ extra_fields.setdefault("is_superuser", True)
43
+ extra_fields.setdefault("is_active", True)
44
+
45
+ if extra_fields.get("is_staff") is not True:
46
+ raise ValueError(_("Superuser must have is_staff=True."))
47
+ if extra_fields.get("is_superuser") is not True:
48
+ raise ValueError(_("Superuser must have is_superuser=True."))
49
+ return self.create_user(email, password, **extra_fields)
50
+
51
+
52
+ phone_regex = RegexValidator(
53
+ regex=r"^\+?1?\d{9,15}$",
54
+ message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.",
55
+ )
56
+
57
+
58
+ class User(AbstractBaseUser, PermissionsMixin):
59
+ """Custom user model to add more fields"""
60
+
61
+ # User roles
62
+ class Roles(models.IntegerChoices):
63
+ """Roles for user model"""
64
+
65
+ ADMIN = 1
66
+ USER = 2
67
+
68
+ email = models.EmailField(_("email address"), unique=True)
69
+ first_name = models.CharField(_("First Name"), max_length=50, blank=True, null=True)
70
+ last_name = models.CharField(_("Last Name"), max_length=50, blank=True, null=True)
71
+
72
+ mobile = models.CharField(
73
+ _("mobile"),
74
+ max_length=17,
75
+ validators=[phone_regex],
76
+ null=True,
77
+ blank=True,
78
+ )
79
+
80
+ address = models.TextField(_("Address"), blank=True, null=True)
81
+ city = models.CharField(_("City/Town"), max_length=50, blank=True, null=True)
82
+ state = models.CharField(_("State/Province"), max_length=50, blank=True, null=True)
83
+ country = models.CharField(_("Country"), max_length=50, blank=True, null=True)
84
+ zip_code = models.CharField(max_length=50, blank=True, null=True)
85
+
86
+ is_staff = models.BooleanField(default=False)
87
+ is_active = models.BooleanField(default=True)
88
+ date_joined = models.DateTimeField(_("date joined"), auto_now_add=True)
89
+ role = models.PositiveSmallIntegerField(
90
+ _("role"), choices=Roles.choices, default=Roles.USER
91
+ )
92
+ created = models.DateTimeField(auto_now_add=True, editable=False)
93
+ modified = models.DateTimeField(auto_now=True, editable=False)
94
+
95
+ USERNAME_FIELD = "email"
96
+ REQUIRED_FIELDS = []
97
+
98
+ objects = UserManager()
99
+
100
+ class Meta:
101
+ verbose_name = _("User")
102
+ verbose_name_plural = _("Users")
103
+
104
+ def __str__(self):
105
+ return self.get_full_name()
106
+
107
+ def get_full_name(self):
108
+ return "{} {}".format(self.first_name, self.last_name)
109
+
110
+ def send_forgot_password_email(self,host,email):
111
+ return send_email_to_user(self.pk, host,email,email_type="forgot_password")
accounts/serializers.py CHANGED
@@ -1,20 +1,33 @@
1
  from rest_framework import serializers
2
- from django.contrib.auth.models import User
3
 
4
- class UserSerializer(serializers.ModelSerializer):
5
  password = serializers.CharField(write_only=True)
6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  def create(self, validated_data):
8
- # Create the user instance
9
- user = User.objects.create_user(
10
- username=validated_data['username'],
11
- email=validated_data.get('email', ''), # Default to empty string if email is not provided
12
- password=validated_data['password'],
13
- first_name=validated_data.get('first_name', ''), # Default to empty string if first_name is not provided
14
- last_name=validated_data.get('last_name', '') # Default to empty string if last_name is not provided
15
- )
16
  return user
17
 
18
- class Meta:
19
- model = User
20
- fields = ('id', 'username', 'password', 'first_name', 'last_name', 'email')
 
 
 
 
 
 
1
  from rest_framework import serializers
2
+ from .models import User
3
 
4
+ class UserRegistrationSerializer(serializers.ModelSerializer):
5
  password = serializers.CharField(write_only=True)
6
 
7
+ class Meta:
8
+ model = User
9
+ fields = ['email', 'password', 'first_name', 'last_name', 'mobile', 'address', 'city', 'state', 'country', 'zip_code', 'role']
10
+ extra_kwargs = {
11
+ 'first_name': {'required': False},
12
+ 'last_name': {'required': False},
13
+ 'mobile': {'required': False},
14
+ 'address': {'required': False},
15
+ 'city': {'required': False},
16
+ 'state': {'required': False},
17
+ 'country': {'required': False},
18
+ 'zip_code': {'required': False},
19
+ 'role': {'required': False},
20
+ }
21
+
22
  def create(self, validated_data):
23
+ user = User.objects.create_user(**validated_data)
 
 
 
 
 
 
 
24
  return user
25
 
26
+
27
+ class ForgotPasswordSerializer(serializers.Serializer):
28
+ email = serializers.EmailField()
29
+
30
+ class ResetPasswordSerializer(serializers.Serializer):
31
+ token = serializers.CharField()
32
+ uid = serializers.CharField()
33
+ new_password = serializers.CharField()
accounts/task.py ADDED
@@ -0,0 +1,56 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from django.contrib.auth.tokens import PasswordResetTokenGenerator
2
+ from django.core.mail import send_mail
3
+ from django.conf import settings
4
+ from django.contrib.auth import get_user_model
5
+ from django.utils.encoding import force_bytes
6
+ from django.utils.html import strip_tags
7
+ from django.utils.http import urlsafe_base64_encode
8
+
9
+
10
+ def send_email_to_user(
11
+ user_pk,
12
+ host,
13
+ email,
14
+ email_type,
15
+ new_email=None,
16
+ from_email=settings.EMAIL_HOST_USER,
17
+ **kwargs,
18
+ ):
19
+ user = get_user_model().objects.get(pk=user_pk)
20
+
21
+ token_generator = PasswordResetTokenGenerator()
22
+ token = token_generator.make_token(user)
23
+ uid = urlsafe_base64_encode(force_bytes(user.pk))
24
+ reset_link = f"{host}/verify/{uid}/{token}"
25
+
26
+ # Define your email subject
27
+ subject = "Reset Your Password for Text to Speech AI Voice Generator"
28
+
29
+ # Write the HTML content directly in the function
30
+ html_content = f"""
31
+ <html>
32
+ <body>
33
+ <p>Hello {user.get_full_name() or user.username},</p>
34
+ <p>You requested a password reset for your account. Click the link below to reset your password:</p>
35
+ <p><a href="{reset_link}">Reset Password</a></p>
36
+ <p>If you didn't request this, you can ignore this email.</p>
37
+ <p>Your link will expire in 48 hours.</p>
38
+ <p>Thank you!</p>
39
+ </body>
40
+ </html>
41
+ """
42
+
43
+ # Create a text-only version of the email
44
+ text_content = strip_tags(html_content)
45
+
46
+ try:
47
+ send_mail(
48
+ subject,
49
+ text_content,
50
+ from_email,
51
+ [email],
52
+ html_message=html_content, # This is the key part for HTML
53
+ fail_silently=False,
54
+ )
55
+ except Exception as e:
56
+ print(e)
accounts/urls.py CHANGED
@@ -1,9 +1,11 @@
1
  from django.urls import path
2
- from . import views
3
- from rest_framework.authtoken.views import obtain_auth_token
4
 
5
  urlpatterns = [
6
- path('register/', views.RegisterView.as_view(), name='register'),
7
- path('login', obtain_auth_token, name="Get Token"),
 
 
 
8
  ]
9
 
 
1
  from django.urls import path
2
+ from .views import *
 
3
 
4
  urlpatterns = [
5
+ path('register/', UserRegistrationAPIView.as_view(), name='user-registration'),
6
+ path('login/', LoginView.as_view(), name='login'),
7
+ path('forgot-password/', ResetPasswordView.as_view(), name='forgot_password'),
8
+ path('reset-password/', ChangePasswordView.as_view(), name='reset_password'),
9
+
10
  ]
11
 
accounts/views.py CHANGED
@@ -1,16 +1,100 @@
1
- from .serializers import UserSerializer
2
  from rest_framework import status
3
  from rest_framework.response import Response
4
- from rest_framework.generics import CreateAPIView
5
  from rest_framework.authtoken.models import Token
6
- from django.contrib.auth.models import User
 
 
 
 
 
7
 
8
- class RegisterView(CreateAPIView):
9
- queryset = User.objects.all()
10
- serializer_class = UserSerializer # Create a UserSerializer to handle user registration.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
- def perform_create(self, serializer):
13
- user = serializer.save()
14
  token, _ = Token.objects.get_or_create(user=user)
15
- return Response({'token': token.key}, status=status.HTTP_201_CREATED)
16
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from .models import User
2
  from rest_framework import status
3
  from rest_framework.response import Response
4
+ from rest_framework.generics import CreateAPIView,UpdateAPIView
5
  from rest_framework.authtoken.models import Token
6
+ from rest_framework.views import APIView
7
+ from django.contrib.auth import authenticate
8
+ from drf_yasg.utils import swagger_auto_schema
9
+ from drf_yasg import openapi
10
+ from django.utils.http import urlsafe_base64_decode
11
+ from django.utils.encoding import force_str
12
 
13
+ from .serializers import ForgotPasswordSerializer, ResetPasswordSerializer, UserRegistrationSerializer
14
+ from django.contrib.auth.tokens import default_token_generator
15
+
16
+
17
+ class UserRegistrationAPIView(CreateAPIView):
18
+ serializer_class = UserRegistrationSerializer
19
+ def post(self, request, format=None):
20
+ serializer = UserRegistrationSerializer(data=request.data)
21
+ if serializer.is_valid():
22
+ serializer.save()
23
+ return Response(serializer.data, status=status.HTTP_201_CREATED)
24
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
25
+
26
+
27
+
28
+ class LoginView(APIView):
29
+ @swagger_auto_schema(
30
+ request_body=openapi.Schema(
31
+ type=openapi.TYPE_OBJECT,
32
+ required=['email', 'password'],
33
+ properties={
34
+ 'email': openapi.Schema(type=openapi.TYPE_STRING),
35
+ 'password': openapi.Schema(type=openapi.TYPE_STRING),
36
+ },
37
+ ),
38
+ responses={
39
+ status.HTTP_200_OK: openapi.Schema(
40
+ type=openapi.TYPE_OBJECT,
41
+ properties={
42
+ 'token': openapi.Schema(type=openapi.TYPE_STRING),
43
+ },
44
+ ),
45
+ },
46
+ )
47
+ def post(self, request):
48
+ email = request.data.get('email')
49
+ password = request.data.get('password')
50
+
51
+ if email is None or password is None:
52
+ return Response({'error': 'Please provide both email and password'}, status=status.HTTP_400_BAD_REQUEST)
53
+
54
+ user = authenticate(email=email, password=password)
55
+
56
+ if not user:
57
+ return Response({'error': 'Invalid credentials'}, status=status.HTTP_401_UNAUTHORIZED)
58
 
 
 
59
  token, _ = Token.objects.get_or_create(user=user)
 
60
 
61
+ return Response({'token': token.key})
62
+
63
+
64
+ class ResetPasswordView(CreateAPIView):
65
+ serializer_class = ForgotPasswordSerializer
66
+
67
+ def post(self, request):
68
+ serializer = self.serializer_class(data=request.data)
69
+ if serializer.is_valid():
70
+ email = serializer.validated_data.get("email")
71
+ if User.objects.filter(email=email).exists():
72
+ user = User.objects.get(email=email)
73
+ scheme = "https" if request.is_secure() else "http"
74
+ full_host = request.get_host()
75
+ base_url = f"{scheme}://{full_host}"
76
+ user.send_forgot_password_email(base_url, email)
77
+ return Response({"message": "Password reset email sent"})
78
+ else:
79
+ return Response({"error": "Email does not exist"}, status=status.HTTP_400_BAD_REQUEST)
80
+ else:
81
+ return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
82
+
83
+
84
+ class ChangePasswordView(UpdateAPIView):
85
+ serializer_class = ResetPasswordSerializer
86
+ http_method_names = ['patch', 'head', 'options', 'trace']
87
+
88
+ def partial_update(self, request, *args, **kwargs):
89
+ serializer = self.get_serializer(data=request.data)
90
+ serializer.is_valid(raise_exception=True)
91
+
92
+ uid = force_str(urlsafe_base64_decode(serializer.validated_data['uid']))
93
+ user = User.objects.get(pk=uid)
94
+
95
+ if user is not None and default_token_generator.check_token(user, serializer.validated_data['token']):
96
+ user.set_password(serializer.validated_data['new_password'])
97
+ user.save()
98
+ return Response({"message": "Password updated successfully"}, status=status.HTTP_200_OK)
99
+ else:
100
+ return Response({"error": "Invalid token or user does not exist"}, status=status.HTTP_400_BAD_REQUEST)
config/schemaprotocol.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from drf_yasg.generators import OpenAPISchemaGenerator
2
+ class BothHttpAndHttpsSchemaGenerator(OpenAPISchemaGenerator):
3
+ def get_schema(self, request=None, public=False):
4
+ schema = super().get_schema(request, public)
5
+ schema.schemes = ["http", "https"]
6
+ return schema
config/settings.py CHANGED
@@ -51,7 +51,8 @@ INSTALLED_APPS = [
51
  CORS_ALLOW_ALL_ORIGINS = True # If this is used then `CORS_ALLOWED_ORIGINS` will not have any effect
52
  CORS_ALLOW_CREDENTIALS = True
53
  CORS_ALLOWED_ORIGINS = [
54
- 'https://undetectable-voice-clone.hf.space', "http://94.101.98.237:7860" ,"https://voice-clone-frontend.vercel.app" ,"https://voice.undetectable.ai" ,"https://api.voice.undetectable.ai"
 
55
  ]
56
 
57
  REST_FRAMEWORK = {
@@ -122,10 +123,12 @@ DATABASES = {
122
  }
123
  }
124
 
125
- MINIO_ENDPOINT = '94.101.98.237:9000' # Use the service name defined in Docker Compose
126
  MINIO_ACCESS_KEY = 'voice-clone'
127
  MINIO_SECRET_KEY = 'voice-clone'
128
- MINIO_SECURE = False # Change to True if using HTTPS
 
 
129
 
130
  # Password validation
131
  # https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators
@@ -157,7 +160,11 @@ USE_I18N = True
157
 
158
  USE_TZ = True
159
 
160
-
 
 
 
 
161
  # Static files (CSS, JavaScript, Images)
162
  # https://docs.djangoproject.com/en/5.0/howto/static-files/
163
 
@@ -169,3 +176,12 @@ MEDIA_URL = '/media/'
169
  # https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
170
 
171
  DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
 
 
 
 
 
 
 
 
 
 
51
  CORS_ALLOW_ALL_ORIGINS = True # If this is used then `CORS_ALLOWED_ORIGINS` will not have any effect
52
  CORS_ALLOW_CREDENTIALS = True
53
  CORS_ALLOWED_ORIGINS = [
54
+ 'https://undetectable-voice-clone.hf.space', "http://94.101.98.237:7860" ,"https://voice-clone-frontend.vercel.app" ,
55
+ "https://voice.undetectable.ai" ,"https://api.voice.undetectable.ai"
56
  ]
57
 
58
  REST_FRAMEWORK = {
 
123
  }
124
  }
125
 
126
+ MINIO_ENDPOINT = 'storage.voice.undetectable.ai' # Use the service name defined in Docker Compose
127
  MINIO_ACCESS_KEY = 'voice-clone'
128
  MINIO_SECRET_KEY = 'voice-clone'
129
+ MINIO_SECURE = True # Change to True if using HTTPS
130
+
131
+ AUTH_USER_MODEL = 'accounts.User'
132
 
133
  # Password validation
134
  # https://docs.djangoproject.com/en/5.0/ref/settings/#auth-password-validators
 
160
 
161
  USE_TZ = True
162
 
163
+ ACCOUNT_USER_MODEL_USERNAME_FIELD = None
164
+ ACCOUNT_AUTHENTICATION_METHOD = "email"
165
+ ACCOUNT_EMAIL_REQUIRED = True
166
+ ACCOUNT_UNIQUE_EMAIL = True
167
+ ACCOUNT_USERNAME_REQUIRED = False
168
  # Static files (CSS, JavaScript, Images)
169
  # https://docs.djangoproject.com/en/5.0/howto/static-files/
170
 
 
176
  # https://docs.djangoproject.com/en/5.0/ref/settings/#default-auto-field
177
 
178
  DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
179
+
180
+
181
+ EMAIL_HOST = "smtp.gmail.com"
182
+ EMAIL_PORT = 587 # For TLS
183
+ EMAIL_USE_TLS = True
184
+ EMAIL_USE_SSL = False
185
+ EMAIL_HOST_USER='[email protected]'
186
+ EMAIL_HOST_PASSWORD="fgxx yuns jagn rwak"
187
+ DEFAULT_FROM_EMAIL="[email protected]"
config/urls.py CHANGED
@@ -1,5 +1,6 @@
1
  from django.contrib import admin
2
  from django.urls import path, include
 
3
  from rest_framework import permissions
4
  from drf_yasg.views import get_schema_view
5
  from drf_yasg import openapi
@@ -17,7 +18,7 @@ schema_view = get_schema_view(
17
  license=openapi.License(name="Your License"),
18
  ),
19
  public=True,
20
- url="https://undetectable-voice-clone.hf.space/",
21
  permission_classes=(permissions.AllowAny,),
22
  )
23
 
 
1
  from django.contrib import admin
2
  from django.urls import path, include
3
+ from .schemaprotocol import BothHttpAndHttpsSchemaGenerator
4
  from rest_framework import permissions
5
  from drf_yasg.views import get_schema_view
6
  from drf_yasg import openapi
 
18
  license=openapi.License(name="Your License"),
19
  ),
20
  public=True,
21
+ # generator_class=BothHttpAndHttpsSchemaGenerator,
22
  permission_classes=(permissions.AllowAny,),
23
  )
24
 
db.sqlite3 DELETED
Binary file (160 kB)
 
project.log DELETED
The diff for this file is too large to render. See raw diff
 
texttovoice/models.py CHANGED
@@ -1,6 +1,6 @@
1
 
2
  from django.db import models
3
- from django.contrib.auth.models import User
4
 
5
  # Create your models here.
6
  class BaseModel(models.Model):
 
1
 
2
  from django.db import models
3
+ from accounts.models import User
4
 
5
  # Create your models here.
6
  class BaseModel(models.Model):
texttovoice/serializers.py CHANGED
@@ -8,7 +8,7 @@ class TextToSpeechSerializer(serializers.Serializer):
8
 
9
 
10
  class TextToSpeechSerializerResponse(serializers.ModelSerializer):
11
- created_by = serializers.SerializerMethodField()
12
 
13
  class Meta:
14
  model = TextToSpeech
@@ -16,12 +16,12 @@ class TextToSpeechSerializerResponse(serializers.ModelSerializer):
16
  # Ensure that all the fields you want to include are listed here
17
 
18
  def get_created_by(self, obj):
19
- return obj.created_by.username if obj.created_by else None
20
 
21
  class TextToSpeechSerializerResponseWithURL(serializers.ModelSerializer):
22
  speaker_wav_url = serializers.SerializerMethodField()
23
  output_wav_url = serializers.SerializerMethodField()
24
- created_by = serializers.SerializerMethodField()
25
 
26
 
27
  class Meta:
@@ -36,4 +36,4 @@ class TextToSpeechSerializerResponseWithURL(serializers.ModelSerializer):
36
  return self.context['view'].generate_presigned_url(obj.output_wav)
37
 
38
  def get_created_by(self, obj):
39
- return obj.created_by.username if obj.created_by else None
 
8
 
9
 
10
  class TextToSpeechSerializerResponse(serializers.ModelSerializer):
11
+ #created_by = serializers.SerializerMethodField()
12
 
13
  class Meta:
14
  model = TextToSpeech
 
16
  # Ensure that all the fields you want to include are listed here
17
 
18
  def get_created_by(self, obj):
19
+ return obj.created_by.email if obj.created_by else None
20
 
21
  class TextToSpeechSerializerResponseWithURL(serializers.ModelSerializer):
22
  speaker_wav_url = serializers.SerializerMethodField()
23
  output_wav_url = serializers.SerializerMethodField()
24
+ #created_by = serializers.SerializerMethodField()
25
 
26
 
27
  class Meta:
 
36
  return self.context['view'].generate_presigned_url(obj.output_wav)
37
 
38
  def get_created_by(self, obj):
39
+ return obj.created_by.email if obj.created_by else None