diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 65b51eb5a3e17941d1ddcc4a9e3e482057f49656..14767b904c6b9cca072df11e148fc6fe0f3b62c8 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -162,17 +162,6 @@ py37-django111: - - - - - - - - - - - safety: stage: lint before_script: diff --git a/src/hope/forms.py b/src/hope/forms.py new file mode 100644 index 0000000000000000000000000000000000000000..3fe600ee6a16016d1d82dd6f82d2747626fc8a76 --- /dev/null +++ b/src/hope/forms.py @@ -0,0 +1,12 @@ +from django import forms +from django.contrib.auth.forms import UserCreationForm + +from .models import User + + +class SignUpForm(UserCreationForm): + email = forms.EmailField(label='Email', max_length=254) + + class Meta: + model = User + fields = ('username', 'email', 'password1', 'password2', ) diff --git a/src/hope/models.py b/src/hope/models.py new file mode 100644 index 0000000000000000000000000000000000000000..e78c2bbb8ec4ad12db98c6016928218072144ec8 --- /dev/null +++ b/src/hope/models.py @@ -0,0 +1,8 @@ +from django.db import models +from django.contrib.auth.models import AbstractUser + +from cerberus_ac.models import RoleMixin + + +class User(AbstractUser, RoleMixin): + email_confirmed = models.BooleanField(default=False) diff --git a/src/hope/static/hope/css/base.css b/src/hope/static/hope/css/base.css new file mode 100644 index 0000000000000000000000000000000000000000..b1be4347cc0a1ab52e7ae369959f0b447bbb9d7f --- /dev/null +++ b/src/hope/static/hope/css/base.css @@ -0,0 +1,7 @@ +html, body { + height: 100%; +} + +.container-fluid { + height: 100%; +} diff --git a/src/hope/static/hope/package.json b/src/hope/static/hope/package.json new file mode 100644 index 0000000000000000000000000000000000000000..7f54079f9a69438add2bc128e5a3bdfc19546926 --- /dev/null +++ b/src/hope/static/hope/package.json @@ -0,0 +1,10 @@ +{ + "name": "static", + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "dependencies": { + "bootstrap": "^3.3.7", + "jquery": "^3.2.1" + } +} diff --git a/src/hope/templates/hope/account_activated.html b/src/hope/templates/hope/account_activated.html new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/hope/templates/hope/account_activation_email.html b/src/hope/templates/hope/account_activation_email.html new file mode 100644 index 0000000000000000000000000000000000000000..bc2dccf16b5ce74b99cff86f7a6109b5a1155acf --- /dev/null +++ b/src/hope/templates/hope/account_activation_email.html @@ -0,0 +1,7 @@ +{% autoescape off %} +Hi {{ user.username }}, + +Please click on the link below to confirm your registration: + +http://{{ domain }}{% url 'activate' uidb64=uid token=token %} +{% endautoescape %} diff --git a/src/hope/templates/hope/account_activation_invalid.html b/src/hope/templates/hope/account_activation_invalid.html new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/src/hope/templates/hope/account_activation_sent.html b/src/hope/templates/hope/account_activation_sent.html new file mode 100644 index 0000000000000000000000000000000000000000..4778fc2bee620172819d50c9ded6827bcf3ba3ee --- /dev/null +++ b/src/hope/templates/hope/account_activation_sent.html @@ -0,0 +1,6 @@ +{% extends "base.html" %} + +{% block content %} + An email has been sent to the specified email address. + Please click on the link inside the email to activate your account. +{% endblock %} diff --git a/src/hope/templates/hope/base.html b/src/hope/templates/hope/base.html new file mode 100644 index 0000000000000000000000000000000000000000..462cdcc399ab1ef3560c6e0b2501bbf852f4f7ef --- /dev/null +++ b/src/hope/templates/hope/base.html @@ -0,0 +1,63 @@ +{% load i18n static %} + + + + + + + + + + +{# #} + + + {% block title %}{{cookiecutter.package_name}}{% endblock %} + + + + + + + + + + +
+ + + + + + {% block content %} + {% endblock %} + +
+ + + + + + + + diff --git a/src/hope/templates/hope/home.html b/src/hope/templates/hope/home.html new file mode 100644 index 0000000000000000000000000000000000000000..d0ebebc287c615e6e44cffacd3c2560398e81da6 --- /dev/null +++ b/src/hope/templates/hope/home.html @@ -0,0 +1,17 @@ +{% extends 'base.html' %} + +{% block title %}Hope{% endblock %} +{% block navbar_home %}active{% endblock %} + +{% block content %} +
+

Welcome to Hope

+

(Put Hope description here)

+ {% if not user.is_authenticated %} + Sign-in + Sign-up + {% else %} + Sign-out + {% endif %} +
+{% endblock %} diff --git a/src/hope/templates/hope/signin.html b/src/hope/templates/hope/signin.html new file mode 100644 index 0000000000000000000000000000000000000000..339aa297cad6b62b9d1ba222de1b4554987c0a2b --- /dev/null +++ b/src/hope/templates/hope/signin.html @@ -0,0 +1,15 @@ +{% extends 'base.html' %} +{% load bootstrap %} + +{% block title %}Sign in{% endblock %} + +{% block content %} +

Login

+
+ {% csrf_token %} + {{ form|bootstrap }} +
+ +
+
+{% endblock %} diff --git a/src/hope/templates/hope/signout.html b/src/hope/templates/hope/signout.html new file mode 100644 index 0000000000000000000000000000000000000000..774107d75919c65bab556fcf5b866563046249e6 --- /dev/null +++ b/src/hope/templates/hope/signout.html @@ -0,0 +1,7 @@ +{% extends 'base.html' %} + +{% block title %}Signed out{% endblock %} + +{% block content %} +

Yo have been signed out.

+{% endblock %} diff --git a/src/hope/templates/hope/signup.html b/src/hope/templates/hope/signup.html new file mode 100644 index 0000000000000000000000000000000000000000..447a901295fc0d2bb59fc79df7dd0c8114d91f94 --- /dev/null +++ b/src/hope/templates/hope/signup.html @@ -0,0 +1,15 @@ +{% extends 'base.html' %} +{% load bootstrap %} + +{% block title %}Sign up{% endblock %} + +{% block content %} +

Sign up

+
+ {% csrf_token %} + {{ form|bootstrap }} +
+ +
+
+{% endblock %} diff --git a/src/hope/tokens.py b/src/hope/tokens.py new file mode 100644 index 0000000000000000000000000000000000000000..4f7d88151b7ebbb83a107117e58507194b1017b4 --- /dev/null +++ b/src/hope/tokens.py @@ -0,0 +1,13 @@ +from django.contrib.auth.tokens import PasswordResetTokenGenerator +from django.utils import six + + +class AccountActivationTokenGenerator(PasswordResetTokenGenerator): + def _make_hash_value(self, user, timestamp): + return ( + six.text_type(user.pk) + six.text_type(timestamp) + + six.text_type(user.email_confirmed) + ) + + +account_activation_token = AccountActivationTokenGenerator() diff --git a/src/hope/urls.py b/src/hope/urls.py new file mode 100644 index 0000000000000000000000000000000000000000..55322637d345e5d6c729cd9d52624b1b3a75d826 --- /dev/null +++ b/src/hope/urls.py @@ -0,0 +1,18 @@ +from django.conf.urls import url +from django.contrib.auth import views as auth_views + +from . import views + +urlpatterns = [ + url(r'^signup/$', views.signup, name='signup'), + url(r'^signin/$', auth_views.login, + {'template_name': 'hope/signin.html'}, name='signin'), + url(r'^signout/$', auth_views.logout, + {'template_name': 'hope/signout.html'}, name='signout'), + url(r'^account_activation_sent/$', + views.account_activation_sent, name='account_activation_sent'), + url(r'^activate/' + r'(?P[0-9A-Za-z_\-]+)/' + r'(?P[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$', + views.activate, name='activate') +] diff --git a/src/hope/views.py b/src/hope/views.py new file mode 100644 index 0000000000000000000000000000000000000000..826c6b0d4783a7fb7ff56e0150ba482620c761e5 --- /dev/null +++ b/src/hope/views.py @@ -0,0 +1,54 @@ +from django.contrib.auth import login +from django.contrib.sites.shortcuts import get_current_site +from django.shortcuts import render, redirect +from django.template.loader import render_to_string +from django.utils.encoding import force_bytes, force_text +from django.utils.http import urlsafe_base64_encode, urlsafe_base64_decode + +from .forms import SignUpForm +from .models import User +from .tokens import account_activation_token + + +def signup(request): + if request.method == 'POST': + form = SignUpForm(request.POST) + if form.is_valid(): + user = form.save(commit=False) + user.is_active = False + user.save() + current_site = get_current_site(request) + subject = 'Activate Your MySite Account' + message = render_to_string('account_activation_email.html', { + 'user': user, + 'domain': current_site.domain, + 'uid': urlsafe_base64_encode(force_bytes(user.pk)), + 'token': account_activation_token.make_token(user), + }) + user.email_user(subject, message) + return redirect('account_activation_sent') + else: + form = SignUpForm() + return render(request, '{{cookiecutter.package_name}}/signup.html', {'form': form}) + + +def activate(request, uidb64, token): + try: + uid = force_text(urlsafe_base64_decode(uidb64)) + user = User.objects.get(pk=uid) + except (TypeError, ValueError, OverflowError, User.DoesNotExist): + user = None + + if user is not None and account_activation_token.check_token(user, token): + user.is_active = True + user.email_confirmed = True + user.save() + login(request, user) + # TODO: add a message with django message app + return redirect('home') + else: + return render(request, 'account_activation_invalid.html') + + +def account_activation_sent(request): + return render(request, 'account_activation_sent.html')