import json from django import forms from django.conf import settings from django.http import HttpResponseRedirect from django.shortcuts import render from django.core.exceptions import ValidationError from django.contrib.auth.models import User from troggle.core.models.troggle import DataIssue, Person from troggle.parsers.users import register_user, get_encryptor, ENCRYPTED_DIR, USERS_FILE from troggle.core.utils import ( add_commit, ) """ This is the new individual user login registration, instead of everyone signing in as "expo". This will be useful for the kanban expo organisation tool. """ todo = """ - Make all this work with New people who have never been on expo before - login automatically, and redirect to control panel ? """ def register(request, username=None): """To register a new user on the troggle system, similar to the "expo" user (with cavey:beery password) but specific to an individual """ current_user = request.user # if not logged in, this is 'AnonymousUser' warning = "" if request.method == "POST": form = register_form(request.POST) if form.is_valid(): un = form.cleaned_data["username"] pw= form.cleaned_data["password1"] email = form.cleaned_data["email"] expoers = User.objects.filter(username=un) if len(expoers) != 0: # this is a password re-set, not a new registration. So we need to check it is the same person. form_user = expoers[0] if current_user != form_user: print(f"## UNAUTHORIZED Password reset ## {current_user} {form_user}") # return render(request, "login/register.html", {"form": form, "unauthorized": True}) # create User in the system and refresh stored encrypted user list and git commit it: updated_user = register_user(un, email, password=pw, pwhash=None) save_users(request, updated_user, email) # to do, login automatically, and redirect to control panel ? return HttpResponseRedirect("/accounts/login/") else: if username: if not current_user.is_anonymous: warning = f"WARNING - you are logged-in as someone else '{current_user}'. You must logout and login again as '{username}' " print(f"REGISTER: {warning}") form = register_form(initial={"visible": "True", "username": username} ) elif current_user: form = register_form(initial={"visible": "True", "username": current_user.username}) else: form = register_form(initial={"visible": "True"}) return render(request, "login/register.html", {"form": form, "warning": warning}) def save_users(request, updated_user, email): f = get_encryptor() ru = [] print(f"\n + Saving users, encrypted emails, and password hashes") for u in User.objects.all(): if u.username in ["expo", "expoadmin"]: continue e_email = f.encrypt(u.email.encode("utf8")).decode() ru.append({"username":u.username, "email": e_email, "pwhash": u.password, "encrypted": True}) # print(u.username, e_email) original = f.decrypt(e_email).decode() print(f" - {u.username} - {original}") encryptedfile = settings.EXPOWEB / ENCRYPTED_DIR / USERS_FILE try: print(f"- Rewriting the entire encrypted set of registered users to disc ") write_users(ru, encryptedfile, updated_user, email) except: message = f'! - Users encrypted data saving failed - \n!! Permissions failure ?! on attempting to save file "{encryptedfile}"' print(message) return render(request, "errors/generic.html", {"message": message}) def write_users(registered_users, encryptedfile, updated_user, email): jsondict = { "registered_users": registered_users } try: if settings.DEVSERVER: with open(encryptedfile, 'w', encoding='utf-8') as json_f: json.dump(jsondict, json_f, indent=1) except Exception as e: print(f" ! Exception dumping json <{e}>") raise commit_msg = f"Online (re-)registration of a troggle User" editor = f"{updated_user.username} <{email}>" try: add_commit(encryptedfile, commit_msg, editor) except Exception as e: print(f" ! Exception doing git add/commit <{e}>") raise return True class register_form(forms.Form): # not a model-form, just a form-form username = forms.CharField(strip=True, required=True, label="Username", widget=forms.TextInput( attrs={"size": 35, "placeholder": "e.g. anathema-device", "style": "vertical-align: text-top;"} )) email = forms.CharField(strip=True, required=True, label="email", widget=forms.TextInput( attrs={"size": 35, "placeholder": "e.g. anathema@potatohut.expo", "style": "vertical-align: text-top;"} )) password1 = forms.CharField(strip=True, required=True, label="Troggle password", widget=forms.TextInput( attrs={"size": 30, "placeholder": "your new login password", "style": "vertical-align: text-top;"} )) password2 = forms.CharField(strip=True, required=True, label="Re-type your troggle password", widget=forms.TextInput( attrs={"size": 30, "placeholder": "same as the password above", "style": "vertical-align: text-top;"} ) ) def clean(self): cleaned_data = super().clean() pw1 = cleaned_data.get("password1") pw2 = cleaned_data.get("password2") if pw1 != pw2: raise ValidationError( "Retyped password does not match initial password: please fix this." ) un = cleaned_data.get("username") if un in ["expo", "expoadmin"]: raise ValidationError( "Sorry, please do not try to be clever. This username is hard-coded and you can't edit it here. We were students once, too." ) expoers = Person.objects.filter(slug=un) if len(expoers) == 0: raise ValidationError( "Sorry, we are not registering new people yet. Try again next week. We are still getting the bugs out of this.." ) if len(expoers) != 1: raise ValidationError( "Sorry, that troggle identifier has duplicates. Contact a nerd on the Nerd email list, or (better) the Matrix website chat." )