diff --git a/accounts/templates/accounts/register.html b/accounts/templates/accounts/register.html new file mode 100644 index 0000000..7a58c5e --- /dev/null +++ b/accounts/templates/accounts/register.html @@ -0,0 +1,89 @@ + + + + + + + Registration + + + + +
+ {% if error %} +
+

ERROR: {{ error.title }}

+

{{ error.reason }}

+
+ {% endif %} + {% csrf_token %} +
+

Register

+

Welcome to mystiq registration.

+
+ + + + + + + + + +
+ +

By creating an account you agree to our Terms & Privacy.

+ +
+ +
+

Already have an account? Sign in.

+
+
+ + \ No newline at end of file diff --git a/accounts/tests.py b/accounts/tests.py index 406b5dd..2d290cc 100644 --- a/accounts/tests.py +++ b/accounts/tests.py @@ -1,6 +1,7 @@ # Create your tests here. # Copyright © 2022 Aravinth Manivannan +# Copyright © 2022 Alan Alexander Thomas # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as @@ -36,10 +37,9 @@ from oauth2_provider.models import get_application_model def register_util(t: TestCase, username: str): t.password = "asdklfja;ldkfja;df" - t.username = username - t.email = f"{t.username}@example.org" + t.email = f"{username}@vitap.ac.in" t.user = get_user_model().objects.create( - username=t.username, + username=username, email=t.email, ) t.user.set_password(t.password) @@ -48,7 +48,7 @@ def register_util(t: TestCase, username: str): def login_util(t: TestCase, c: Client, redirect_to: str): payload = { - "login": t.username, + "login": t.email, "password": t.password, } resp = c.post(reverse("accounts.login"), payload) @@ -102,3 +102,51 @@ class CreateOidCApplicaiton(TestCase): self.assertEqual(app.client_type, "confidential") self.assertEqual(app.authorization_grant_type, "authorization-code") self.assertEqual(app.algorithm, "HS256") + + +class RegistrationTest(TestCase): + def setUp(self): + self.username = "register_user" + self.password = "2i3j4;1qlk2asdf" + self.email = "register_user@vitap.ac.in" + + def test_register_template_works(self): + """ + Tests if register template renders + """ + resp = self.client.get(reverse("accounts:register")) + self.assertEqual(b"Register" in resp.content, True) + + def test_register_works(self): + """ + Tests if register works + """ + c = Client() + + # passwords don't match + msg = { + "password": self.password, + "email": self.email, + "password-confirm": self.email, + } + resp = c.post(reverse("accounts:register"), msg) + self.assertEqual(resp.status_code, 400) + + # register user + msg["password-confirm"] = self.password + resp = c.post(reverse("accounts:register"), msg) + self.assertEqual(resp.status_code, 200) + + user = get_user_model().objects.get(username=self.username) + + # duplicate email + resp = c.post(reverse("accounts:register"), msg) + self.assertEqual(resp.status_code, 400) + self.assertEqual(b"This email is already registered." in resp.content, True) + + msg["email"] = "12345@gmail.com" + resp = c.post(reverse("accounts:register"), msg) + self.assertEqual(resp.status_code, 400) + self.assertEqual( + b"We do not provide services for this domain yet." in resp.content, True + ) diff --git a/accounts/urls.py b/accounts/urls.py new file mode 100644 index 0000000..16592e4 --- /dev/null +++ b/accounts/urls.py @@ -0,0 +1,25 @@ +"""sso URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/4.1/topics/http/urls/ + +Exaimples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path +from . import views + +app_name = "accounts" +urlpatterns = [ + path("", views.index, name="accounts.index"), + path("register/", views.register, name="register"), +] diff --git a/accounts/views.py b/accounts/views.py index 91ea44a..53e0ce7 100644 --- a/accounts/views.py +++ b/accounts/views.py @@ -1,3 +1,97 @@ +# Copyright © 2022 Alan Alexander Thomas + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# +# License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from multiprocessing import get_context from django.shortcuts import render # Create your views here. +from re import template +from urllib import response +from django.shortcuts import render, redirect, get_object_or_404 +from django.contrib.auth.password_validation import validate_password +from django.contrib.auth import authenticate, login, logout, get_user_model +from django.http import HttpResponse, HttpResponseRedirect +from django.views.decorators.csrf import csrf_protect +from django.core.exceptions import ValidationError + +# Create your views here. +from django.http import HttpResponse + + +def index(request): + return HttpResponse("Hello World.") + + +@csrf_protect +def register(request): + # response = "You are at the Registration Page." + get_context = {} + if request.method == "GET": + if "next" in request.GET: + get_context["next"] = request.GET["next"] + return render(request, "accounts/register.html", get_context) + + context = {} + + # variables + email = request.POST["email"] + password = request.POST["password"] + password_confirm = request.POST["password-confirm"] + + # domain verification + domain_check = email.split("@") + if domain_check[1] != "vitap.ac.in": + context["error"] = { + "title": "Registration Failed", + "reason": "We do not provide services for this domain yet.", + } + return render(request, "accounts/register.html", status=400, context=context) + + # email verification + User = get_user_model() + if User.objects.filter(email=email).exists(): + context["error"] = { + "title": "Registration Failed", + "reason": "This email is already registered.", + } + return render(request, "accounts/register.html", status=400, context=context) + # password matching + if password != password_confirm: + context["error"] = { + "title": "Registration Failed", + "reason": "Passwords do not match.", + } + return render(request, "accounts/register.html", status=400, context=context) + + user = get_user_model()( + username=domain_check[0], + email=email, + ) + user.set_password(password) + + try: + user.full_clean() + validate_password(password, user=user) + except ValidationError as err: + reason = "" + for errors in err: + reason += errors + " " + context["error"] = {"title": "Registration Failed", "reason": reason} + print(reason) + return render(request, "accounts/register.html", status=400, context=context) + + user.save() + return HttpResponse("New acc. can be registered.") diff --git a/requirements.txt b/requirements.txt index d0903de..03ccf88 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ asgiref==3.5.2 astroid==2.11.7 +backports.zoneinfo==0.2.1 black==22.6.0 certifi==2022.6.15 cffi==1.15.1 @@ -29,7 +30,9 @@ pylint==2.14.5 pynvim==0.4.3 requests==2.28.1 sqlparse==0.4.2 +tblib==1.7.0 tomli==2.0.1 tomlkit==0.11.4 +typing_extensions==4.3.0 urllib3==1.26.11 wrapt==1.14.1 diff --git a/sso/urls.py b/sso/urls.py index 0b2bdcb..44fe01e 100644 --- a/sso/urls.py +++ b/sso/urls.py @@ -19,4 +19,5 @@ from django.urls import path, include urlpatterns = [ path("admin/", admin.site.urls), path("o/", include("oauth2_provider.urls", namespace="oauth2_provider")), + path("accounts/", include("accounts.urls")), ]