summaryrefslogtreecommitdiffstats
path: root/core/views/user_registration.py
blob: fe9f1260fcc6cabeb0e03b3259dfc740d7a859e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
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."
            )