diff --git a/embark/embark/settings/deploy.py b/embark/embark/settings/deploy.py index b250efa5..04c47d6c 100644 --- a/embark/embark/settings/deploy.py +++ b/embark/embark/settings/deploy.py @@ -23,10 +23,6 @@ # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/3.2/howto/deployment/checklist/ -# HASHID_FIELD_SALT = os.environ.get('HASHID_SALT') -# HASHID_FIELD_MIN_LENGTH = os.environ.get('HASHID_FIELD_MIN_LENGTH', 7) -# HASHID_FIELD_ENABLE_HASHID_OBJECT = os.environ.get('HASHID_FIELD_ENABLE_HASHID_OBJECT', False) -# HASHID_FIELD_ENABLE_DESCRIPTOR = os.environ.get('HASHID_FIELD_ENABLE_DESCRIPTOR', False) SECRET_KEY = os.environ.get('SECRET_KEY') # SECURITY WARNING: don't run with debug turned on in production! @@ -34,6 +30,9 @@ ALLOWED_HOSTS = ['*'] +DOMAIN = "embark.local" +EMAIL_ACTIVE = False + # EMBA stuff # EMBA location EMBA_ROOT = os.path.join(BASE_DIR.parent, 'emba') diff --git a/embark/embark/settings/dev.py b/embark/embark/settings/dev.py index 3ccdad54..beb66775 100644 --- a/embark/embark/settings/dev.py +++ b/embark/embark/settings/dev.py @@ -21,6 +21,9 @@ EMBA_LOG_URL = 'emba_logs/' DEBUG = True +DOMAIN = "embark.local" +EMAIL_ACTIVE = False + INSTALLED_APPS = [ 'django.contrib.admin', diff --git a/embark/embark/urls.py b/embark/embark/urls.py index 4004ea17..c0cda493 100644 --- a/embark/embark/urls.py +++ b/embark/embark/urls.py @@ -17,12 +17,12 @@ __author__ = 'm-1-k-3, RaviChandra, Garima Chauhan, Maximilian Wagner, diegiesskanne' __license__ = 'MIT' -# from django.contrib import admin +from django.contrib import admin from django.urls import path, include from django.contrib.staticfiles.urls import staticfiles_urlpatterns urlpatterns = [ - # path('admin/', admin.site.urls), + path('admin/', admin.site.urls), path('', include('updater.urls')), path('', include('uploader.urls')), path('', include('users.urls')), diff --git a/embark/templates/user/activate.html b/embark/templates/user/activate.html new file mode 100644 index 00000000..e48695f8 --- /dev/null +++ b/embark/templates/user/activate.html @@ -0,0 +1,5 @@ +{% csrf_token %} +{% for field in form %} + +{{ field }} +{% endfor %} \ No newline at end of file diff --git a/embark/templates/user/email_template.html b/embark/templates/user/email_template.html new file mode 100644 index 00000000..e3e99f33 --- /dev/null +++ b/embark/templates/user/email_template.html @@ -0,0 +1,8 @@ +{% autoescape off %} +Dear {{ username }}, + +Please follow the link to confirm your registration, +http://{{ domain }}{% url 'activate' user_id=uid activation_token=token %} + +OR manually input the following token: {{ token }} +{% endautoescape %} \ No newline at end of file diff --git a/embark/users/forms.py b/embark/users/forms.py new file mode 100644 index 00000000..0f3691da --- /dev/null +++ b/embark/users/forms.py @@ -0,0 +1,14 @@ +from django import forms +from django.contrib.auth.forms import UserCreationForm +from users.models import User + + +class SignupForm(UserCreationForm): + class Meta: + model = User + fields = ('username', 'email', 'password1', 'password2') + + +class ActivationForm(forms.Form): + + token = forms.CharField(max_length=256, min_length=256) diff --git a/embark/users/models.py b/embark/users/models.py index 40a3c0ad..0a701f8a 100644 --- a/embark/users/models.py +++ b/embark/users/models.py @@ -5,7 +5,7 @@ import enum from django.db import models -from django.contrib.auth.models import AbstractUser +from django.contrib.auth.models import User as DjangoUser from django.conf import settings from lib.choice_enum import ChoiceIntEnum @@ -26,10 +26,7 @@ class Team(models.Model): modified = models.DateTimeField(auto_now=True, help_text='Date time when this entry was modified') -class User(AbstractUser): - is_active = models.BooleanField(default=True, help_text='User active or not') - created = models.DateTimeField(auto_now_add=True, help_text='Date time when this entry was created') - modified = models.DateTimeField(auto_now=True, help_text='Date time when this entry was modified') +class User(DjangoUser): timezone = models.CharField(max_length=32, choices=settings.TIMEZONES, default='UTC') diff --git a/embark/users/urls.py b/embark/users/urls.py index 39f8332f..a1011cb6 100644 --- a/embark/users/urls.py +++ b/embark/users/urls.py @@ -12,6 +12,7 @@ path(settings.LOGIN_URL, views.embark_login, name='embark-login'), path('user/', views.user_main, name='embark-user-main'), path('register/', views.register, name='embark-register'), + path('register/activate//', views.register, name='embark-activate-user'), path('logout/', views.embark_logout, name='embark-logout'), path('user/password_change/', views.password_change, name='embark-password-change'), path('user/acc_delete/', views.acc_delete, name='embark-acc-delete'), diff --git a/embark/users/views.py b/embark/users/views.py index 0957fbb1..1b03c81e 100644 --- a/embark/users/views.py +++ b/embark/users/views.py @@ -7,15 +7,20 @@ import logging from django.contrib.auth.decorators import login_required +from django.contrib.auth import authenticate, login, logout, get_user +from django.contrib.auth.tokens import default_token_generator +from django.contrib.sites.shortcuts import get_current_site +from django.contrib import messages from django.shortcuts import render, redirect from django.views.decorators.csrf import csrf_exempt from django.views.decorators.http import require_http_methods - -from django.contrib.auth import authenticate, login, logout, get_user -from django.contrib import messages +from django.template.loader import render_to_string from django.conf import settings from django.utils import timezone +from django.urls import reverse +from django.core.mail import send_mail +from users.forms import ActivationForm, SignupForm from users.models import User logger = logging.getLogger(__name__) @@ -32,29 +37,38 @@ def user_main(request): def register(request): if request.method == "POST": logger.debug(request.POST) - data = {k: v[0] for k, v in dict(request.POST).items()} - logger.debug(data) try: - body = {k: v[0] for k, v in dict(request.POST).items()} - try: - username = body['username'] - password = body['password'] - confirm_password = body['confirm_password'] - if password != confirm_password: - logger.debug('Passwords do not match') - messages.success(request, 'Passwords do not match.') - return render(request, 'user/register.html') + user = get_user(request) + signup_form = SignupForm(request.POST) + if signup_form.is_valid(): + username = signup_form.cleaned_data.get('username') + password = signup_form.cleaned_data.get('password') + email = signup_form.cleaned_data.get('email') logger.debug('Passwords match. Creating user') - user = User.objects.create(username=username) + user = User.objects.create(username=username, email=email) user.set_password(password) + user.is_active = False user.save() logger.debug('User created') - messages.success(request, 'Registration successful.') - return redirect('../../') - except KeyError: - logger.exception('Missing keys from data- Username, password, password_confirm') - messages.error(request, 'User data is missing/invalid.') - return render(request, 'user/register.html') + # TODO create email + token + token = default_token_generator.make_token(user) + current_site = get_current_site(request) + mail_subject = 'Activate your EMBArk account.' + message = render_to_string('email_template.html', context={ + 'user': user, + 'username': user.username, + 'domain': current_site.domain, + 'uid': user.id, + 'token': token, + }) + + if settings.EMAIL_ACTIVE: + send_mail(mail_subject, message, 'system@' + settings.DOMAIN, [email]) + messages.success(request, 'Registration successful. Please check your email to activate') + return redirect(reverse('embark-login')) + else: + logger.debug("Registered, redirecting to login") + activate_user(user.id, token) except builtins.Exception as error: logger.exception('Wide exception in Signup: %s', error) messages.error(request, 'Something went wrong when signing up the user.') @@ -230,3 +244,40 @@ def set_timezone(request): else: messages.error(request, 'Timezone could not be set') return redirect("..") + + +def activate_user(user, token): + """ + activates user with token + """ + if default_token_generator.check_token(user, token): + user.is_active = True + user.save() + return True + return False + + +@require_http_methods(["GET", "POST"]) +@login_required(login_url='/' + settings.LOGIN_URL) +def activate(request): + """ + activation page + form request + activates user through the usage of token + """ + if request.method == "POST": + logger.debug(request.POST) + try: + user = get_user(request) + activation_form = ActivationForm(request.POST) + if activation_form.is_valid(): + token = activation_form.cleand_data["token"] + if activate_user(user, token): + messages.success(request, str(user.username) + 'activated') + else: + messages.error(request, "Token invalid - maybe it expired?") + except ValueError as val_error: + logger.error(f"{val_error} in token {token}") + return redirect(reverse('embark-login')) + else: + activation_form = ActivationForm() + render(request, 'activate.html', {'activation-form': activation_form}) diff --git a/installer.sh b/installer.sh index f168bae3..8ce95b78 100755 --- a/installer.sh +++ b/installer.sh @@ -81,9 +81,9 @@ save_old_env(){ } write_env(){ - local SUPER_PW="embark" - local SUPER_EMAIL="idk@lol.com" - local SUPER_USER="superuser" + local SUPER_PW="$(openssl rand -base64 8)" + local SUPER_EMAIL="admin@embark.local" + local SUPER_USER="admin" local RANDOM_PW="" local DJANGO_SECRET_KEY="" local ENV_FILES=()