aboutsummaryrefslogtreecommitdiff
path: root/users
diff options
context:
space:
mode:
Diffstat (limited to 'users')
-rw-r--r--users/__init__.py0
-rw-r--r--users/accountFunctions.py48
-rw-r--r--users/admin.py7
-rw-r--r--users/apps.py6
-rw-r--r--users/forms.py279
-rw-r--r--users/mail_send.py75
-rw-r--r--users/migrations/0001_initial.py29
-rw-r--r--users/migrations/0002_userprofile_email_verified.py18
-rw-r--r--users/migrations/0003_captchastore.py22
-rw-r--r--users/migrations/0004_remove_captchastore_id_alter_captchastore_csrf_token.py22
-rw-r--r--users/migrations/0005_captchastore_id_alter_captchastore_csrf_token.py24
-rw-r--r--users/migrations/0006_delete_captchastore.py16
-rw-r--r--users/migrations/0007_captchastore.py22
-rw-r--r--users/migrations/0008_remove_userprofile_gravatar_email_and_more.py22
-rw-r--r--users/migrations/0009_delete_captchastore.py16
-rw-r--r--users/migrations/0010_userprofile_blinkie_url.py17
-rw-r--r--users/migrations/0011_tokenstore.py42
-rw-r--r--users/migrations/0012_alter_tokenstore_expires.py17
-rw-r--r--users/migrations/__init__.py0
-rw-r--r--users/models.py36
-rw-r--r--users/templates/email_change_verification_email.html27
-rw-r--r--users/templates/reset_password_email.html25
-rw-r--r--users/templates/verification_email.html26
-rw-r--r--users/tests.py3
-rw-r--r--users/tokens.py45
-rw-r--r--users/urls.py31
-rw-r--r--users/views.py300
27 files changed, 0 insertions, 1175 deletions
diff --git a/users/__init__.py b/users/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/users/__init__.py
+++ /dev/null
diff --git a/users/accountFunctions.py b/users/accountFunctions.py
deleted file mode 100644
index 38bc7099..00000000
--- a/users/accountFunctions.py
+++ /dev/null
@@ -1,48 +0,0 @@
-import secrets
-import uuid
-
-from django.utils import timezone
-
-from users.models import TokenStore, UserProfile
-
-
-def generate_token():
- uid = uuid.uuid4().hex
- token = secrets.token_urlsafe(32)
- print(uid, token)
- return uid, token
-
-def store_token(token_type, user, email=None):
- previous_tokens = TokenStore.objects.filter(user=user, token_type=token_type)
- if previous_tokens.exists():
- previous_tokens.delete()
- uid, token = generate_token()
- token_store = TokenStore.objects.create(
- user=user,
- email=email if email is not None else user.email,
- uid=uid,
- token=token,
- token_type=token_type,
- expires=timezone.now() + timezone.timedelta(minutes=30),
- )
- token_store.save()
- return uid, token
-
-def verify_token(token_type, uid, token, hold_verification=False):
- try:
- token_store = TokenStore.objects.get(token_type=token_type, uid=uid, token=token)
- if token_store.expires > timezone.now() and not token_store.verified and token_store.token_type == token_type and token_store.uid == uid and token_store.token == token:
-
- if hold_verification:
- return token_store
- token_store.verified = True
-
- if token_type == "verifyemail":
- UserProfile.objects.filter(user=token_store.user).update(email_verified=True)
-
- token_store.save()
-
- return token_store
- except TokenStore.DoesNotExist:
- return None
- \ No newline at end of file
diff --git a/users/admin.py b/users/admin.py
deleted file mode 100644
index 0f1d5fdb..00000000
--- a/users/admin.py
+++ /dev/null
@@ -1,7 +0,0 @@
-from django.contrib import admin
-
-# Register your models here.
-from .models import TokenStore, UserProfile
-
-admin.site.register(UserProfile)
-admin.site.register(TokenStore)
diff --git a/users/apps.py b/users/apps.py
deleted file mode 100644
index 72b14010..00000000
--- a/users/apps.py
+++ /dev/null
@@ -1,6 +0,0 @@
-from django.apps import AppConfig
-
-
-class UsersConfig(AppConfig):
- default_auto_field = 'django.db.models.BigAutoField'
- name = 'users'
diff --git a/users/forms.py b/users/forms.py
deleted file mode 100644
index c2b80732..00000000
--- a/users/forms.py
+++ /dev/null
@@ -1,279 +0,0 @@
-# Registration form
-
-import string
-from random import choice
-
-from django import forms
-from django.contrib.auth.models import User
-from django.template.loader import render_to_string
-from django.utils.html import strip_tags
-
-from apps.blog.context_processors import avatar_list
-from users.models import UserProfile
-
-from .accountFunctions import store_token
-from .mail_send import send_email
-
-
-class RegisterForm(forms.Form):
- username = forms.CharField(
- label="Username",
- max_length=30,
- min_length=4,
- required=True,
- widget=forms.TextInput(
- attrs={"placeholder": "Username", "autocomplete": "off"}
- ),
- )
- email = forms.EmailField(
- label="Email",
- max_length=255,
- required=True,
- widget=forms.EmailInput(attrs={"placeholder": "Email", "autocomplete": "off"}),
- )
- password1 = forms.CharField(
- label="Password",
- min_length=8,
- required=True,
- widget=forms.PasswordInput(attrs={"placeholder": "Password"}),
- )
- password2 = forms.CharField(
- label="Password (again)",
- widget=forms.PasswordInput(attrs={"placeholder": "Password (again)"}),
- min_length=8,
- required=True,
- )
- captcha = forms.CharField(
- label="Captcha",
- max_length=6,
- min_length=6,
- required=True,
- widget=forms.TextInput(attrs={"placeholder": "Captcha", "autocomplete": "off"}),
- )
- expected_captcha = None
- protected_usernames = [
- "admin",
- "administrator",
- "root",
- "thatcomputerscientist",
- "skippy",
- "system",
- "test",
- "user",
- "webmaster",
- "www",
- "postmaster",
- "hostmaster",
- "info",
- "support",
- "anonymous",
- "guest",
- "nobody",
- "someone",
- "moderator",
- "moderators",
- "mods",
- "crvs",
- ]
- allowed_chars = string.ascii_letters + string.digits
-
- def __init__(self, *args, **kwargs):
- if "expected_captcha" in kwargs:
- self.expected_captcha = kwargs.pop("expected_captcha")
- super().__init__(*args, **kwargs)
-
- def clean(self):
- cleaned_data = super().clean()
- password1 = cleaned_data.get("password1")
- password2 = cleaned_data.get("password2")
- captcha = cleaned_data.get("captcha")
- if password1 and password2:
- if password1 != password2:
- raise forms.ValidationError("Passwords do not match.")
- if len(password1) < 8:
- raise forms.ValidationError("Password must be at least 8 characters long.")
- if str.lower(captcha) != str.lower(self.expected_captcha):
- raise forms.ValidationError("Captcha does not match.")
- if User.objects.filter(username=cleaned_data.get("username")).exists():
- raise forms.ValidationError(
- "Username not available. Please choose another."
- )
- if cleaned_data.get("username").lower() in self.protected_usernames:
- raise forms.ValidationError(
- "Username not available. Please choose another."
- )
- for char in cleaned_data.get("username"):
- if char not in self.allowed_chars:
- raise forms.ValidationError(
- "Username contains invalid characters. Only A-Z, a-z, and 0-9 are allowed."
- )
- if User.objects.filter(email=cleaned_data.get("email")).exists():
- raise forms.ValidationError(
- "Email already exists. Please login if this account is yours."
- )
- return cleaned_data
-
- def save(self, request):
- user = User.objects.create_user(
- username=self.cleaned_data.get("username").lower(),
- email=self.cleaned_data.get("email").lower(),
- password=self.cleaned_data.get("password1"),
- )
- user.save()
- user_profile = UserProfile.objects.create(user=user)
- avatar_dir = choice(list(avatar_list().keys()))
- avatar_file = choice(avatar_list()[avatar_dir])
- user_profile.avatar_url = avatar_dir + "/" + avatar_file.replace(".gif", "")
- user_profile.save()
-
- uid, token = store_token(token_type="verifyemail", user=user, email=user.email)
-
- # Send verification email
- subject = "Verify your email address"
- message = render_to_string(
- "verification_email.html",
- {
- "user": user.username if user.first_name is None else user.first_name,
- "site_name": "Shifoo",
- "uid": uid,
- "token": token,
- "protocol": "https://" if request.is_secure() else "http://",
- "domain": request.get_host(),
- },
- )
- # message = strip_tags(message)
- # send_mail(subject, message, 'Shifoo <' + settings.EMAIL_HOST_USER + '>', [user.email], fail_silently=False)
- if send_email(
- sender="[email protected]",
- sender_name="Shifoo",
- recipient=user.email,
- subject=subject,
- body_html=message,
- body_text=message,
- ):
- return user
- else:
- return user
-
-
-class ForgotPasswordForm(forms.Form):
- email = forms.EmailField(label="Email", required=True)
-
- def clean(self):
- cleaned_data = super().clean()
- return cleaned_data
-
- def save(self, request):
- email = self.cleaned_data.get("email")
- user = User.objects.get(email=email)
- uid, token = store_token(
- token_type="resetpassword", user=user, email=user.email
- )
- subject = "Reset your password"
- message = render_to_string(
- "reset_password_email.html",
- {
- "user": user.username if user.first_name is None else user.first_name,
- "site_name": "Shifoo",
- "uid": uid,
- "token": token,
- "protocol": "https://" if request.is_secure() else "http://",
- "domain": request.get_host(),
- },
- )
- # message = strip_tags(message)
- if send_email(
- sender="[email protected]",
- sender_name="Shifoo",
- recipient=user.email,
- subject=subject,
- body_html=message,
- body_text=message,
- ):
- return user
- else:
- raise forms.ValidationError("Failed to send email.")
-
-
-class ResetPasswordForm(forms.Form):
- password1 = forms.CharField(
- label="New Password", widget=forms.PasswordInput, min_length=8
- )
- password2 = forms.CharField(
- label="New Password (again)", widget=forms.PasswordInput, min_length=8
- )
-
- def clean(self):
- cleaned_data = super().clean()
- password1 = cleaned_data.get("password1")
- password2 = cleaned_data.get("password2")
- if password1 and password2:
- if password1 != password2:
- raise forms.ValidationError("Passwords do not match.")
- if len(password1) < 8:
- raise forms.ValidationError("Password must be at least 8 characters long.")
- return cleaned_data
-
- def save(self, user):
- user.set_password(self.cleaned_data.get("password1"))
- user.save()
- return user
-
-
-class UpdateUserDetailsForm(forms.Form):
- first_name = forms.CharField(
- label="First name",
- max_length=30,
- required=False,
- widget=forms.TextInput(attrs={"placeholder": "First name"}),
- )
- last_name = forms.CharField(
- label="Last name",
- max_length=30,
- required=False,
- widget=forms.TextInput(attrs={"placeholder": "Last name"}),
- )
- location = forms.CharField(
- label="Location",
- max_length=30,
- required=False,
- widget=forms.TextInput(attrs={"placeholder": "Location"}),
- )
- bio = forms.CharField(
- label="Bio",
- max_length=500,
- required=False,
- widget=forms.Textarea(attrs={"placeholder": "Bio"}),
- )
- is_public = forms.ChoiceField(
- label="Activity Visibility",
- choices=((True, "Public"), (False, "Private")),
- widget=forms.RadioSelect,
- )
- email_public = forms.ChoiceField(
- label="Email Visibility",
- choices=((True, "Public"), (False, "Private")),
- widget=forms.RadioSelect,
- )
-
- def __init__(self, *args, **kwargs):
- self.user = kwargs.pop("user")
- super().__init__(*args, **kwargs)
-
- def clean(self):
- cleaned_data = super().clean()
- return cleaned_data
-
- def save(self):
- self.user.first_name = self.cleaned_data.get("first_name")
- self.user.last_name = self.cleaned_data.get("last_name")
- self.user.save()
-
- user_profile = UserProfile.objects.get(user=self.user)
- user_profile.location = self.cleaned_data.get("location")
- user_profile.bio = self.cleaned_data.get("bio")
- user_profile.is_public = self.cleaned_data.get("is_public")
- user_profile.email_public = self.cleaned_data.get("email_public")
- user_profile.save()
-
- return (self.user, user_profile)
diff --git a/users/mail_send.py b/users/mail_send.py
deleted file mode 100644
index df837a32..00000000
--- a/users/mail_send.py
+++ /dev/null
@@ -1,75 +0,0 @@
-# python script for sending SMTP configuration with Oracle Cloud Infrastructure Email Delivery
-import email.utils
-import smtplib
-import ssl
-from email.message import EmailMessage
-
-from django.conf import settings
-
-
-def send_email(sender, sender_name, recipient, subject, body_html, body_text):
- # Replace [email protected] with your "From" address.
- # This address must be verified.
- # this is the approved sender email
- SENDER = sender
- SENDERNAME = sender_name
-
- # Replace [email protected] with a "To" address. If your account
- # is still in the sandbox, this address must be verified.
- RECIPIENT = recipient
-
- # Replace the USERNAME_SMTP value with your Email Delivery SMTP username.
- USERNAME_SMTP = settings.USERNAME_SMTP
-
- # Put the PASSWORD value from your Email Delivery SMTP password into the following file.
- PASSWORD_SMTP = settings.PASSWORD_SMTP
-
- # If you're using Email Delivery in a different region, replace the HOST value with an appropriate SMTP endpoint.
- # Use port 25 or 587 to connect to the SMTP endpoint.
- HOST = settings.EMAIL_HOST
- PORT = settings.EMAIL_PORT
-
- # The subject line of the email.
- SUBJECT = subject
-
- # The email body for recipients with non-HTML email clients.
- BODY_TEXT = body_text
-
- # The HTML body of the email.
- BODY_HTML = body_html
-
- # create message container
- msg = EmailMessage()
- msg["Subject"] = SUBJECT
- msg["From"] = email.utils.formataddr((SENDERNAME, SENDER))
- msg["To"] = RECIPIENT
-
- # make the message multi-part alternative, making the content the first part
- msg.add_alternative(BODY_TEXT, subtype="text")
- # this adds the additional part to the message
- # According to RFC 2046, the last part of a multipart message, in this case
- # the HTML message, is best and preferred.
- msg.add_alternative(BODY_HTML, subtype="html")
-
- # Try to send the message.
- try:
- server = smtplib.SMTP(HOST, PORT)
- server.ehlo()
- # most python runtimes default to a set of trusted public CAs that will include the CA used by OCI Email Delivery.
- # However, on platforms lacking that default (or with an outdated set of CAs), customers may need to provide a capath that includes our public CA.
- server.starttls(
- context=ssl.create_default_context(
- purpose=ssl.Purpose.SERVER_AUTH, cafile=None, capath=None
- )
- )
- # smtplib docs recommend calling ehlo() before & after starttls()
- server.ehlo()
- server.login(USERNAME_SMTP, PASSWORD_SMTP)
- # our requirement is that SENDER is the same as From address set previously
- server.sendmail(SENDER, RECIPIENT, msg.as_string())
- server.close()
- # Display an error message if something goes wrong.
- except Exception as e:
- return e
- else:
- return True
diff --git a/users/migrations/0001_initial.py b/users/migrations/0001_initial.py
deleted file mode 100644
index a8a78c6b..00000000
--- a/users/migrations/0001_initial.py
+++ /dev/null
@@ -1,29 +0,0 @@
-# Generated by Django 4.0.6 on 2022-07-29 15:58
-
-import django.db.models.deletion
-from django.conf import settings
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- initial = True
-
- dependencies = [
- migrations.swappable_dependency(settings.AUTH_USER_MODEL),
- ]
-
- operations = [
- migrations.CreateModel(
- name='UserProfile',
- fields=[
- ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('location', models.CharField(blank=True, max_length=50)),
- ('bio', models.TextField(blank=True)),
- ('gravatar_email', models.EmailField(blank=True, max_length=254)),
- ('is_public', models.BooleanField(default=False)),
- ('email_public', models.BooleanField(default=False)),
- ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)),
- ],
- ),
- ]
diff --git a/users/migrations/0002_userprofile_email_verified.py b/users/migrations/0002_userprofile_email_verified.py
deleted file mode 100644
index ca89b815..00000000
--- a/users/migrations/0002_userprofile_email_verified.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Generated by Django 4.0.6 on 2022-07-29 18:34
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('users', '0001_initial'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='userprofile',
- name='email_verified',
- field=models.BooleanField(default=False),
- ),
- ]
diff --git a/users/migrations/0003_captchastore.py b/users/migrations/0003_captchastore.py
deleted file mode 100644
index 9aebc0aa..00000000
--- a/users/migrations/0003_captchastore.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Generated by Django 4.0.6 on 2022-09-05 22:27
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('users', '0002_userprofile_email_verified'),
- ]
-
- operations = [
- migrations.CreateModel(
- name='CaptchaStore',
- fields=[
- ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('captcha_string', models.CharField(max_length=6)),
- ('csrf_token', models.CharField(max_length=100)),
- ('created_at', models.DateTimeField(auto_now_add=True)),
- ],
- ),
- ]
diff --git a/users/migrations/0004_remove_captchastore_id_alter_captchastore_csrf_token.py b/users/migrations/0004_remove_captchastore_id_alter_captchastore_csrf_token.py
deleted file mode 100644
index 1dd16bcc..00000000
--- a/users/migrations/0004_remove_captchastore_id_alter_captchastore_csrf_token.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Generated by Django 4.0.6 on 2022-09-05 22:30
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('users', '0003_captchastore'),
- ]
-
- operations = [
- migrations.RemoveField(
- model_name='captchastore',
- name='id',
- ),
- migrations.AlterField(
- model_name='captchastore',
- name='csrf_token',
- field=models.CharField(max_length=100, primary_key=True, serialize=False),
- ),
- ]
diff --git a/users/migrations/0005_captchastore_id_alter_captchastore_csrf_token.py b/users/migrations/0005_captchastore_id_alter_captchastore_csrf_token.py
deleted file mode 100644
index bc3d86e5..00000000
--- a/users/migrations/0005_captchastore_id_alter_captchastore_csrf_token.py
+++ /dev/null
@@ -1,24 +0,0 @@
-# Generated by Django 4.0.6 on 2022-09-05 23:41
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('users', '0004_remove_captchastore_id_alter_captchastore_csrf_token'),
- ]
-
- operations = [
- migrations.AddField(
- model_name='captchastore',
- name='id',
- field=models.BigAutoField(auto_created=True, default=1, primary_key=True, serialize=False, verbose_name='ID'),
- preserve_default=False,
- ),
- migrations.AlterField(
- model_name='captchastore',
- name='csrf_token',
- field=models.CharField(max_length=100),
- ),
- ]
diff --git a/users/migrations/0006_delete_captchastore.py b/users/migrations/0006_delete_captchastore.py
deleted file mode 100644
index f324ff2f..00000000
--- a/users/migrations/0006_delete_captchastore.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Generated by Django 4.0.6 on 2022-09-05 23:47
-
-from django.db import migrations
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('users', '0005_captchastore_id_alter_captchastore_csrf_token'),
- ]
-
- operations = [
- migrations.DeleteModel(
- name='CaptchaStore',
- ),
- ]
diff --git a/users/migrations/0007_captchastore.py b/users/migrations/0007_captchastore.py
deleted file mode 100644
index 15ac458a..00000000
--- a/users/migrations/0007_captchastore.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Generated by Django 4.0.6 on 2022-09-05 23:48
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('users', '0006_delete_captchastore'),
- ]
-
- operations = [
- migrations.CreateModel(
- name='CaptchaStore',
- fields=[
- ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
- ('captcha_string', models.CharField(max_length=6)),
- ('csrf_token', models.CharField(max_length=100)),
- ('created_at', models.DateTimeField(auto_now_add=True)),
- ],
- ),
- ]
diff --git a/users/migrations/0008_remove_userprofile_gravatar_email_and_more.py b/users/migrations/0008_remove_userprofile_gravatar_email_and_more.py
deleted file mode 100644
index 07f33320..00000000
--- a/users/migrations/0008_remove_userprofile_gravatar_email_and_more.py
+++ /dev/null
@@ -1,22 +0,0 @@
-# Generated by Django 4.0.6 on 2022-12-28 10:05
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ('users', '0007_captchastore'),
- ]
-
- operations = [
- migrations.RemoveField(
- model_name='userprofile',
- name='gravatar_email',
- ),
- migrations.AddField(
- model_name='userprofile',
- name='avatar_url',
- field=models.TextField(blank=True),
- ),
- ]
diff --git a/users/migrations/0009_delete_captchastore.py b/users/migrations/0009_delete_captchastore.py
deleted file mode 100644
index dbde60c8..00000000
--- a/users/migrations/0009_delete_captchastore.py
+++ /dev/null
@@ -1,16 +0,0 @@
-# Generated by Django 4.1.4 on 2022-12-28 12:41
-
-from django.db import migrations
-
-
-class Migration(migrations.Migration):
-
- dependencies = [
- ("users", "0008_remove_userprofile_gravatar_email_and_more"),
- ]
-
- operations = [
- migrations.DeleteModel(
- name="CaptchaStore",
- ),
- ]
diff --git a/users/migrations/0010_userprofile_blinkie_url.py b/users/migrations/0010_userprofile_blinkie_url.py
deleted file mode 100644
index 06f5e53c..00000000
--- a/users/migrations/0010_userprofile_blinkie_url.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Generated by Django 4.1.4 on 2023-04-04 01:27
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
- dependencies = [
- ("users", "0009_delete_captchastore"),
- ]
-
- operations = [
- migrations.AddField(
- model_name="userprofile",
- name="blinkie_url",
- field=models.TextField(blank=True, default=""),
- ),
- ]
diff --git a/users/migrations/0011_tokenstore.py b/users/migrations/0011_tokenstore.py
deleted file mode 100644
index f0bf9330..00000000
--- a/users/migrations/0011_tokenstore.py
+++ /dev/null
@@ -1,42 +0,0 @@
-# Generated by Django 4.1.4 on 2023-04-30 03:19
-
-import django.db.models.deletion
-from django.conf import settings
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
- dependencies = [
- migrations.swappable_dependency(settings.AUTH_USER_MODEL),
- ("users", "0010_userprofile_blinkie_url"),
- ]
-
- operations = [
- migrations.CreateModel(
- name="TokenStore",
- fields=[
- (
- "id",
- models.BigAutoField(
- auto_created=True,
- primary_key=True,
- serialize=False,
- verbose_name="ID",
- ),
- ),
- ("uid", models.TextField(unique=True)),
- ("token", models.TextField(unique=True)),
- ("email", models.EmailField(blank=True, max_length=254)),
- ("token_type", models.CharField(max_length=50)),
- ("expires", models.DateTimeField(auto_now_add=True)),
- ("verified", models.BooleanField(default=False)),
- (
- "user",
- models.ForeignKey(
- on_delete=django.db.models.deletion.CASCADE,
- to=settings.AUTH_USER_MODEL,
- ),
- ),
- ],
- ),
- ]
diff --git a/users/migrations/0012_alter_tokenstore_expires.py b/users/migrations/0012_alter_tokenstore_expires.py
deleted file mode 100644
index 4b3481fd..00000000
--- a/users/migrations/0012_alter_tokenstore_expires.py
+++ /dev/null
@@ -1,17 +0,0 @@
-# Generated by Django 4.1.4 on 2023-05-03 01:54
-
-from django.db import migrations, models
-
-
-class Migration(migrations.Migration):
- dependencies = [
- ("users", "0011_tokenstore"),
- ]
-
- operations = [
- migrations.AlterField(
- model_name="tokenstore",
- name="expires",
- field=models.DateTimeField(),
- ),
- ]
diff --git a/users/migrations/__init__.py b/users/migrations/__init__.py
deleted file mode 100644
index e69de29b..00000000
--- a/users/migrations/__init__.py
+++ /dev/null
diff --git a/users/models.py b/users/models.py
deleted file mode 100644
index f11f2f46..00000000
--- a/users/models.py
+++ /dev/null
@@ -1,36 +0,0 @@
-from django.conf import settings
-from django.db import models
-
-
-# User Profile Model
-class UserProfile(models.Model):
- user = models.ForeignKey(
- settings.AUTH_USER_MODEL,
- on_delete=models.CASCADE,
- )
- location = models.CharField(max_length=50, blank=True)
- bio = models.TextField(blank=True)
- avatar_url = models.TextField(blank=True)
- is_public = models.BooleanField(default=False)
- email_public = models.BooleanField(default=False)
- email_verified = models.BooleanField(default=False)
- blinkie_url = models.TextField(blank=True, default='')
-
- def __str__(self):
- return self.user.username
-
-
-class TokenStore(models.Model):
- user = models.ForeignKey(
- settings.AUTH_USER_MODEL,
- on_delete=models.CASCADE,
- )
- uid = models.TextField(unique=True)
- token = models.TextField(unique=True)
- email = models.EmailField(blank=True)
- token_type = models.CharField(max_length=50)
- expires = models.DateTimeField()
- verified = models.BooleanField(default=False)
-
- def __str__(self):
- return self.user.username
diff --git a/users/templates/email_change_verification_email.html b/users/templates/email_change_verification_email.html
deleted file mode 100644
index f6f9b127..00000000
--- a/users/templates/email_change_verification_email.html
+++ /dev/null
@@ -1,27 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <meta charset="UTF-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>Change Email</title>
- </head>
- <body>
- <h3>Change Your Current Email</h3>
- <p>Hi {{ user }},</p>
- <p>
- We received a request to change your email address on {{ site_name }}. To
- verify and change your email address, please click the link below.
- </p>
- <a
- href="{{ protocol }}{{ domain }}{% url 'users:changeemail' 'changeemail' uid token %}"
- >Change Email</a
- >
- <p>If the above link does not work, copy and paste the URL below into your browser:</p>
- <a href="{{ protocol }}{{ domain }}{% url 'users:changeemail' 'changeemail' uid token %}">{{ protocol }}{{ domain }}{% url 'users:changeemail' 'changeemail' uid token %}</a>
-
- <p>Please ignore this email if you did not make this request.</p>
- <p>Thanks,</p>
- <p>Bobby from {{ site_name }}</p>
- </body>
-</html>
diff --git a/users/templates/reset_password_email.html b/users/templates/reset_password_email.html
deleted file mode 100644
index f9651a13..00000000
--- a/users/templates/reset_password_email.html
+++ /dev/null
@@ -1,25 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <meta charset="UTF-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>Reset Password</title>
- </head>
- <body>
- <h3>Reset Your Current Password</h3>
- <p>Hi {{ user }},</p>
- <p>
- We received a request to reset your password on {{ site_name }}. To reset
- your password, please click the link below.
- </p>
- <a href="{{ protocol }}{{ domain }}{% url 'blog:resetpassword' uid token %}"
- >Reset Password</a
- >
- <p>If the above link does not work, copy and paste the URL below into your browser:</p>
- <a href="{{ protocol }}{{ domain }}{% url 'blog:resetpassword' uid token %}">{{ protocol }}{{ domain }}{% url 'blog:resetpassword' uid token %}</a>
- <p>Please ignore this email if you did not make this request.</p>
- <p>Thanks,</p>
- <p>Bobby from {{ site_name }}</p>
- </body>
-</html>
diff --git a/users/templates/verification_email.html b/users/templates/verification_email.html
deleted file mode 100644
index 06e91a79..00000000
--- a/users/templates/verification_email.html
+++ /dev/null
@@ -1,26 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
- <head>
- <meta charset="UTF-8" />
- <meta http-equiv="X-UA-Compatible" content="IE=edge" />
- <meta name="viewport" content="width=device-width, initial-scale=1.0" />
- <title>Verify Email</title>
- </head>
- <body>
- <h1>Verify Your New Account</h1>
- <p>Hi {{ user }},</p>
- <p>
- Thanks for registering an account on {{ site_name }}. To verify your email
- address, please click the link below.
- </p>
- <a
- href="{{ protocol }}{{ domain }}{% url 'users:changeemail' 'verifyemail' uid token %}"
- >Verify Email</a
- >
- <p>If the above link does not work, copy and paste the URL below into your browser:</p>
- <a href="{{ protocol }}{{ domain }}{% url 'users:changeemail' 'verifyemail' uid token %}">{{ protocol }}{{ domain }}{% url 'users:changeemail' 'verifyemail' uid token %}</a>
- <p>Please ignore this email if you did not make this request.</p>
- <p>Thanks,</p>
- <p>Bobby from {{ site_name }}</p>
- </body>
-</html>
diff --git a/users/tests.py b/users/tests.py
deleted file mode 100644
index 7ce503c2..00000000
--- a/users/tests.py
+++ /dev/null
@@ -1,3 +0,0 @@
-from django.test import TestCase
-
-# Create your tests here.
diff --git a/users/tokens.py b/users/tokens.py
deleted file mode 100644
index 05d73362..00000000
--- a/users/tokens.py
+++ /dev/null
@@ -1,45 +0,0 @@
-import os
-
-from Crypto.Cipher import AES
-from django.contrib.auth.tokens import PasswordResetTokenGenerator
-from dotenv import load_dotenv
-from six import text_type
-
-load_dotenv()
-
-class AccountActivationTokenGenerator(PasswordResetTokenGenerator):
- def _make_hash_value(self, user, timestamp):
- return (
- text_type(user.pk) + text_type(timestamp) +
- text_type(user.is_active)
- )
-
-class EmailChangeTokenGenerator():
- def encrypt(self, email):
- auth_string = os.getenv('AUTHORIZATION_STRING')
- key = auth_string.encode('utf-8')[0:16]
- cipher = AES.new(key, AES.MODE_CFB, key)
- return cipher.encrypt(email.encode('utf-8')).hex()
-
-
- def decrypt(self, token):
- auth_string = os.getenv('AUTHORIZATION_STRING')
- key = auth_string.encode('utf-8')[0:16]
- cipher = AES.new(key, AES.MODE_CFB, key)
- return cipher.decrypt(bytes.fromhex(token)).decode('utf-8')
-
-
-class CaptchaTokenGenerator():
- def encrypt(self, captcha_string):
- auth_string = os.getenv('AUTHORIZATION_STRING')
- key = auth_string.encode('utf-8')[0:16]
- cipher = AES.new(key, AES.MODE_CFB, key)
- return cipher.encrypt(captcha_string.encode('utf-8')).hex()
-
- def decrypt(self, token):
- auth_string = os.getenv('AUTHORIZATION_STRING')
- key = auth_string.encode('utf-8')[0:16]
- cipher = AES.new(key, AES.MODE_CFB, key)
- return cipher.decrypt(bytes.fromhex(token)).decode('utf-8')
-
-account_activation_token = AccountActivationTokenGenerator()
diff --git a/users/urls.py b/users/urls.py
deleted file mode 100644
index b7081e42..00000000
--- a/users/urls.py
+++ /dev/null
@@ -1,31 +0,0 @@
-from django.contrib import admin
-from django.urls import path
-
-from . import views
-
-app_name = "users"
-urlpatterns = [
- path("/login", views.login_user, name="login"),
- path("/logout", views.logout_user, name="logout"),
- path("/update", views.update_user, name="update"),
- path("/changepassword", views.change_password, name="changepassword"),
- path(
- "/sendchangeuseremail", views.send_change_user_email, name="sendchangeuseremail"
- ),
- path(
- "/sendverificationemail",
- views.send_verification_email,
- name="sendverificationemail",
- ),
- path("/updateavatar", views.update_avatar, name="updateavatar"),
- path("/updateblinkies", views.update_blinkie, name="updateblinkie"),
- path("/delete", views.delete_user, name="delete"),
- path("/<mode>/<uid>/<token>", views.verify_email, name="verifyemail"),
- path("/<mode>/<uid>/<token>", views.verify_email, name="changeemail"),
- path("/resetpassword/<uid>/<token>", views.reset_password, name="resetpassword"),
-]
-
-# Configure Admin Site
-admin.site.site_header = "Shifoo Administation"
-admin.site.site_title = "Shifoo"
-admin.site.index_title = "Administration Area"
diff --git a/users/views.py b/users/views.py
deleted file mode 100644
index 5dba135b..00000000
--- a/users/views.py
+++ /dev/null
@@ -1,300 +0,0 @@
-from django.contrib import messages
-from django.contrib.auth import authenticate, login, logout, update_session_auth_hash
-from django.contrib.auth.models import User
-from django.http import HttpResponse, HttpResponseRedirect
-from django.shortcuts import redirect, reverse
-from django.template.loader import render_to_string
-from django.utils.html import strip_tags
-
-from .accountFunctions import store_token, verify_token
-from .forms import UpdateUserDetailsForm
-from .mail_send import send_email
-from .models import UserProfile
-
-
-# Create your views here.
-def login_user(request):
- # pass
- next = request.POST.get("next", "blog:home")
- username = request.POST["username"]
- password = request.POST["password"]
- if username == "" or password == "" or username is None or password is None:
- # required fields are empty
- messages.error(request, "RFEERR", extra_tags="loginError")
- return HttpResponseRedirect(next + "?username=" + username)
- else:
- # check if email is verified
- user = authenticate(request, username=username, password=password)
- if user is not None:
- try:
- email_verified = UserProfile.objects.get(user=user.pk).email_verified
- except:
- # user has no profile
- email_verified = False
- if email_verified:
- login(request, user)
- return HttpResponseRedirect(next)
- else:
- # email not verified
- messages.error(request, "ENVERR", extra_tags="loginError")
- return HttpResponseRedirect(next + "?username=" + username)
- else:
- # invalid credentials
- messages.error(request, "IUOPERR", extra_tags="loginError")
- return HttpResponseRedirect(next + "?username=" + username)
-
-
-def logout_user(request):
- logout(request)
- return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
-
-
-def update_user(request):
- user = request.user
- if user is not None:
- if request.method == "POST":
- form = UpdateUserDetailsForm(request.POST, user=user)
- if form.is_valid():
- form.save()
- messages.success(request, "Profile was successfully updated!")
- return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
- else:
- messages.error(
- request, "Unable to update profile! Please try again later."
- )
- return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
- else:
- return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
- else:
- messages.error(request, "You must be logged in to update your profile!")
- return redirect("blog:home")
-
-
-def delete_user(request):
- user = request.user
- if user is not None:
- if request.method == "POST":
- password = request.POST["password"]
- if user.check_password(password):
- # delete user, all comments, user profile details, and all posts
- user.delete()
- messages.success(request, "Your account was successfully deleted!")
- return redirect("blog:home")
- else:
- messages.error(request, "Incorrect password!")
- return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
- else:
- messages.error(request, "Unable to delete account! Please try again later.")
- return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
- else:
- messages.error(request, "You must be logged in to delete your account!")
- return redirect("blog:home")
-
-
-def update_avatar(request):
- user = request.user
- if user is not None:
- if request.method == "POST":
- user_profile = UserProfile.objects.get(user=user)
- user_profile.avatar_url = request.POST["avatar"]
- user_profile.save()
- messages.success(request, "Avatar was successfully updated!")
- return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
- else:
- messages.error(request, "Unable to update avatar! Please try again later.")
- return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
- else:
- messages.error(request, "You must be logged in to update your avatar!")
- return redirect("blog:home")
-
-
-def update_blinkie(request):
- user = request.user
- if user is not None:
- if request.method == "POST":
- user_profile = UserProfile.objects.get(user=user)
- user_profile.blinkie_url = request.POST["blinkie"]
- user_profile.save()
- messages.success(request, "Blinkie was successfully updated!")
- return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
- else:
- messages.error(request, "Unable to update blinkie! Please try again later.")
- return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
- else:
- messages.error(request, "You must be logged in to update your blinkie!")
- return redirect("blog:home")
-
-
-def change_password(request):
- username = request.user
- old_password = request.POST["oldPassword"]
- new_password = request.POST["newPassword"]
- confirm_password = request.POST["confirmPassword"]
- if username is not None:
- user = User.objects.get(username=username)
- if user.check_password(old_password):
- if new_password == confirm_password:
- if len(new_password) < 8:
- messages.error(
- request, "The new password must be at least 8 characters long!"
- )
- return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
- user.set_password(new_password)
- user.save()
- update_session_auth_hash(request, user)
- messages.success(request, "Password was successfully changed!")
- return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
- else:
- messages.error(
- request, "The new password and confirmation password do not match!"
- )
- return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
- else:
- messages.error(request, "Old password is incorrect!")
- return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
- else:
- messages.error(request, "Unable to change password! Please try again later.")
- return redirect("blog:home")
-
-
-def send_change_user_email(request):
- user = request.user
- new_email = request.POST["email"]
- if user is not None:
- # Check if the new and the old email are the same
- if user.email == new_email:
- messages.error(request, "New email is the same as the old one!")
- return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
-
- # check if email is already in use
- if User.objects.filter(email=new_email).exists():
- messages.error(request, "Email is already in use!")
- # Redirect to referrer
- return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
- # Send verification email
- subject = "Change your email address"
- uid, token = store_token(token_type="changeemail", user=user, email=new_email)
-
- message = render_to_string(
- "email_change_verification_email.html",
- {
- "user": user.username if user.first_name is None else user.first_name,
- "site_name": "Shifoo",
- "uid": uid,
- "token": token,
- "protocol": request.scheme + "://",
- "domain": request.get_host(),
- },
- )
- # message = strip_tags(message)
- # send_mail(subject, message, 'That Computer Scientist <' + settings.EMAIL_HOST_USER + '>', [new_email])
-
- if send_email(
- sender="[email protected]",
- sender_name="Shifoo",
- recipient=new_email,
- subject=subject,
- body_html=message,
- body_text=message,
- ):
- messages.success(
- request, "Verification email was sent! Please check your email."
- )
- return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
- else:
- messages.error(request, "Unable to change email! Please try again later.")
- return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
-
- else:
- messages.error(request, "Unable to change email! Please try again later.")
- return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
-
-
-def send_verification_email(request):
- # this is a post only view
- if request.method == "POST":
- username = request.POST.get("username")
- subject = "Verify your email address"
- user = User.objects.get(username=username)
- uid, token = store_token(token_type="verifyemail", user=user, email=user.email)
-
- message = render_to_string(
- "verification_email.html",
- {
- "user": user.username if user.first_name is None else user.first_name,
- "site_name": "Shifoo",
- "uid": uid,
- "token": token,
- "protocol": "https://" if request.is_secure() else "http://",
- "domain": request.get_host(),
- },
- )
- # message = strip_tags(message)
- if send_email(
- sender="[email protected]",
- sender_name="Shifoo",
- recipient=user.email,
- subject=subject,
- body_html=message,
- body_text=message,
- ):
- messages.success(request, "VESENT", extra_tags="loginError")
- return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
- else:
- messages.error(request, "VESENDERR", extra_tags="loginError")
- return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
- else:
- messages.error(request, "VESENDERR", extra_tags="loginError")
- return HttpResponseRedirect(request.META.get("HTTP_REFERER"))
-
-
-def verify_email(request, mode, uid, token):
- token_object = verify_token(mode, uid, token)
- redirect_to = (
- reverse("blog:account") + "?tab=email" if mode == "changeemail" else "blog:home"
- )
- success_message = (
- "Email was successfully changed!" if mode == "changeemail" else "VESUCCESS"
- )
- error_message = "Unable to verify email! Please try again later."
-
- if token_object is not None and token_object.verified:
- user = User.objects.get(pk=token_object.user_id)
- user.email = token_object.email
- user.save()
- token_object.delete()
- messages.success(
- request,
- success_message,
- extra_tags="loginError" if mode == "verifyemail" else "",
- )
- return redirect(redirect_to)
- else:
- messages.error(request, error_message)
- return redirect(redirect_to)
-
-
-def reset_password(request, uid, token):
- mode = "resetpassword"
- token_object = verify_token(mode, uid, token)
-
- # Token is not verified yet, but confirmed that it belongs to the user
- # Now we send a form for the user to reset their password
- if token_object is not None and token_object.verified:
- print(token_object.user_id)
- # redirect to forgotpassword/reset?uid=uid&token=token
- return HttpResponseRedirect(
- reverse("blog:resetpassword")
- + "?uid="
- + token_object.user_id
- + "&token="
- + token
- )
- else:
- # Token is invalid
- messages.error(
- request,
- "Unable to reset password! Please try again later.",
- extra_tags="passwordReset",
- )
- return redirect("blog:forgotpassword")