mirror of
https://expo.survex.com/repositories/troggle/.git
synced 2025-03-29 21:51:51 +00:00
Signup form now saving data (and encrypting it)
This commit is contained in:
parent
c479345b6c
commit
0d105d40da
@ -135,7 +135,6 @@ def make_new_expo_dir(year):
|
||||
if not p.is_file():
|
||||
write_and_commit( [(p, content, "utf8")], f"Auto new year {ff} file creation", "Auto New Year <make_new_expo_dir@troggle.expo>")
|
||||
|
||||
|
||||
def current_expo():
|
||||
"""Returns the current expo year, but also checks if the most recent expo year is the same
|
||||
as this year. If it is not, then it creates an empty Expedition and fixes some files and
|
||||
|
@ -23,19 +23,10 @@ class login_required_if_public(object):
|
||||
def __call__(self, *args, **kwargs):
|
||||
return self.f(*args, **kwargs)
|
||||
|
||||
|
||||
# This is copied from CUYC.cuy.website.view.auth
|
||||
# If we want to do the whole online-email thing, we would also need to copy across the code in these
|
||||
# imported files and delete what is superfluous.
|
||||
# Or we could just load the latest version of django-registration app.
|
||||
# from cuy.club.models import Member, Message
|
||||
# from ..forms import WebsiteLoginForm, WebsiteRegisterForm
|
||||
# from ...common import mail_site_error
|
||||
# from .generic import user_is_active
|
||||
|
||||
"""The login and logout functions.
|
||||
This is also where we would manage registration: for people wanting to create and validate their individual
|
||||
logon accounts/forgottenpassword"""
|
||||
|
||||
TO DO : check that we don't have another set of these active somewhere
|
||||
"""
|
||||
|
||||
############################
|
||||
# Authentication Functions #
|
||||
|
@ -1,8 +1,8 @@
|
||||
import os
|
||||
import re
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
import django.forms as forms
|
||||
from django.contrib.auth.models import User
|
||||
from django.http import HttpResponse, HttpResponseRedirect
|
||||
from django.shortcuts import redirect, render
|
||||
from django.urls import reverse
|
||||
@ -16,62 +16,174 @@ from troggle.core.utils import (
|
||||
git_string,
|
||||
write_and_commit,
|
||||
)
|
||||
from troggle.core.models.troggle import DataIssue, Person
|
||||
from troggle.core.views.editor_helpers import HTMLarea
|
||||
|
||||
from troggle.core.utils import (
|
||||
add_commit,
|
||||
)
|
||||
from troggle.parsers.users import get_encryptor, ENCRYPTED_DIR
|
||||
|
||||
"""The new user signup form and expo user management system in 2025.
|
||||
"""
|
||||
SIGNUPS_FILE = "signups.json"
|
||||
SIGNEDUP = "SIGNEDUP"
|
||||
SIGNUP_YEAR = "2025"
|
||||
SIGNUP_DATES = "30th June - 3rd August"
|
||||
|
||||
def signupok(request):
|
||||
signup_user = request.user
|
||||
|
||||
return render(
|
||||
request, "login/signupok.html",
|
||||
{"year": SIGNUP_YEAR, "dates": SIGNUP_DATES, "signup_user": signup_user },
|
||||
)
|
||||
|
||||
def signup(request):
|
||||
current_user = request.user
|
||||
"""Display and processes the applicant signup form for the forthcoming expo
|
||||
The user must be logged-on as a personal login and that is
|
||||
who is being sighned up. You can't signup someone else.
|
||||
"""
|
||||
signup_user = request.user
|
||||
|
||||
personal_login = True
|
||||
if current_user.is_anonymous:
|
||||
if signup_user.is_anonymous:
|
||||
personal_login = False
|
||||
elif current_user.username in ["expo", "expoadmin"]:
|
||||
elif signup_user.username in ["expo", "expoadmin"]:
|
||||
personal_login = False
|
||||
|
||||
else:
|
||||
personal_login = True
|
||||
|
||||
if personal_login:
|
||||
people = Person.objects.filter(user=signup_user)
|
||||
if len(people) != 1:
|
||||
# someone like "fluffy-bunny" not associated with a Person
|
||||
return HttpResponseRedirect("/accounts/login/?next=/signup")
|
||||
signup_person = people[0]
|
||||
editor = f"{signup_person.fullname} <{signup_user.email}>"
|
||||
|
||||
if request.method == "POST": # If the form has been submitted...
|
||||
pageform = ExpoSignupForm(request.POST) # A form bound to the POST data
|
||||
if pageform.is_valid():
|
||||
print(f"form OK")
|
||||
who = pageform.cleaned_data["name"]
|
||||
who = git_string(name)
|
||||
print(f"{who=}")
|
||||
clean = pageform.cleaned_data
|
||||
print(f" # Signup form OK {clean['name']}")
|
||||
save_signups(editor, signup_person.slug, clean)
|
||||
return HttpResponseRedirect("/signupok")
|
||||
|
||||
else:
|
||||
print(f" # Signup form INVALID\n{pageform.errors} ")
|
||||
return render(
|
||||
request,
|
||||
"login/signup.html",
|
||||
request, "login/signup.html",
|
||||
{"form": pageform, "personal_login": personal_login,
|
||||
"year": "2025", "dates": "30th June - 3rd August",
|
||||
"year": SIGNUP_YEAR, "dates": SIGNUP_DATES,
|
||||
}
|
||||
)
|
||||
else:
|
||||
pageform = ExpoSignupForm(initial={"allergies":"None",
|
||||
initial_context = {"allergies":"None",
|
||||
"medication":"None",
|
||||
"medic_info":"None",
|
||||
"veggie": "mostly",
|
||||
"student": "no",
|
||||
"top_tent_cap": 2,
|
||||
"base_tent_cap": 3,
|
||||
})
|
||||
}
|
||||
if personal_login:
|
||||
initial_context["name"] = signup_person.fullname
|
||||
initial_context["email"] = signup_user.email
|
||||
pageform = ExpoSignupForm(initial=initial_context)
|
||||
return render(
|
||||
request,
|
||||
"login/signup.html",
|
||||
{"form": pageform,
|
||||
"year": "2025", "dates": "30th June - 3rd August",
|
||||
request, "login/signup.html",
|
||||
{"form": pageform, "personal_login": personal_login,
|
||||
"year": SIGNUP_YEAR, "dates": SIGNUP_DATES,
|
||||
},
|
||||
)
|
||||
|
||||
def read_signups():
|
||||
print(f" + READ signups")
|
||||
f = get_encryptor()
|
||||
signups_dir = settings.EXPOWEB / ENCRYPTED_DIR / current_expo()
|
||||
if not signups_dir.is_dir():
|
||||
signups_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
signupsfile = signups_dir / SIGNUPS_FILE
|
||||
if not signupsfile.is_file():
|
||||
return { SIGNEDUP: {} } # dict where e.g. {"philip-sargent": encrypted_form_data, more users etc.}
|
||||
|
||||
with open(signupsfile, 'r', encoding='utf-8') as json_f:
|
||||
message = ""
|
||||
try:
|
||||
signups_single_dict = json.load(json_f)
|
||||
except FileNotFoundError:
|
||||
message = f"File {signupsfile} not found!"
|
||||
except json.JSONDecodeError:
|
||||
message = f"Invalid JSON format! - JSONDecodeError for {signupsfile}"
|
||||
except Exception as e:
|
||||
message = f"! Troggle USERs. Failed to load {signupsfile} JSON file. Exception <{e}>"
|
||||
if message:
|
||||
print(message)
|
||||
DataIssue.objects.update_or_create(parser="_signups", message=message, url="") ###########################
|
||||
return { SIGNEDUP: {} }
|
||||
signups_dict = signups_single_dict[SIGNEDUP]
|
||||
# print("ALL:",signups_dict)
|
||||
signups_clear ={}
|
||||
for su, content in signups_dict.items():
|
||||
clear_text = f.decrypt(content).decode()
|
||||
print(f"\n - C signups_dict {su} - {clear_text}")
|
||||
signups_clear[su] = clear_text
|
||||
|
||||
return signups_clear
|
||||
|
||||
|
||||
def save_signups(editor, person_slug, clean):
|
||||
# print(f" + SAVE: Saving all signups")
|
||||
f = get_encryptor()
|
||||
signups_clear = read_signups()
|
||||
# print(f" SAVE: {len(signups_clear)} signups read")
|
||||
|
||||
signups_clear[person_slug] = clean
|
||||
|
||||
signups_crypt = {}
|
||||
for su in signups_clear:
|
||||
# re-encrypt everything
|
||||
signups_crypt[su] = f.encrypt(json.dumps(signups_clear[su]).encode("utf8")).decode()
|
||||
|
||||
print(f" SAVE after adding: {len(signups_crypt)} signups")
|
||||
encryptedfile = settings.EXPOWEB / ENCRYPTED_DIR / current_expo() / SIGNUPS_FILE
|
||||
try:
|
||||
print(f"- Rewriting the entire encrypted set of signups to disc ")
|
||||
write_signups(signups_crypt, encryptedfile, editor)
|
||||
except:
|
||||
message = f'! - Users encrypted data saving failed - \n!! Permissions failure ?! on attempting to save file "{encryptedfile}"'
|
||||
print(message)
|
||||
raise
|
||||
return render(request, "errors/generic.html", {"message": message})
|
||||
|
||||
def write_signups(signups, encryptedfile, editor):
|
||||
jsondict = { SIGNEDUP: signups }
|
||||
try:
|
||||
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 signup to next expo"
|
||||
try:
|
||||
add_commit(encryptedfile, commit_msg, editor)
|
||||
except Exception as e:
|
||||
print(f" ! Exception doing git add/commit <{e}>")
|
||||
raise
|
||||
return True
|
||||
|
||||
|
||||
class ExpoSignupForm(forms.Form):
|
||||
name = forms.CharField(label='Full name', max_length=100, widget=forms.TextInput(attrs={'tabindex': 1, 'placeholder': 'Anathema Device'}))
|
||||
address = forms.CharField(widget=forms.Textarea(attrs={'rows': 7, 'cols': 20, 'tabindex': 2, 'placeholder': 'The Airfield,\nTadfield'}))
|
||||
phone = forms.CharField(max_length=15, widget=forms.TextInput(attrs={'tabindex': 3, 'placeholder': '+44.1234567890'}))
|
||||
email = forms.EmailField(widget=forms.TextInput(attrs={'tabindex': 4, 'placeholder': 'a.device@potatohut.expo'}))
|
||||
|
||||
kinname = forms.CharField(label='Next of Kin name', max_length=100, widget=forms.TextInput(attrs={'tabindex': 5, 'placeholder': 'Newton Pulsifer'}))
|
||||
kinaddress = forms.CharField(widget=forms.Textarea(attrs={'rows': 7, 'cols': 20, 'tabindex': 6, 'placeholder': 'c/o The Old Ship Inn,\nLower Tadfield'}))
|
||||
kinphone = forms.CharField(max_length=15, widget=forms.TextInput(attrs={'tabindex': 7, 'placeholder': '+44.0987654321'}))
|
||||
kinemail = forms.EmailField(widget=forms.TextInput(attrs={'tabindex': 8, 'placeholder': 'n.pulsifer@basecamp.expo'}))
|
||||
kin_name = forms.CharField(label='Next of Kin name', max_length=100, widget=forms.TextInput(attrs={'tabindex': 5, 'placeholder': 'Newton Pulsifer'}))
|
||||
kin_address = forms.CharField(widget=forms.Textarea(attrs={'rows': 7, 'cols': 20, 'tabindex': 6, 'placeholder': 'c/o The Old Ship Inn,\nLower Tadfield'}))
|
||||
kin_phone = forms.CharField(max_length=15, widget=forms.TextInput(attrs={'tabindex': 7, 'placeholder': '+44.0987654321'}))
|
||||
kin_email = forms.EmailField(widget=forms.TextInput(attrs={'tabindex': 8, 'placeholder': 'n.pulsifer@basecamp.expo'}))
|
||||
relation = forms.CharField(label='Relation to you', max_length=100, widget=forms.TextInput(attrs={'tabindex': 9, 'placeholder': 'Beau'}))
|
||||
|
||||
VEGGIE_CHOICES = [
|
||||
|
@ -177,7 +177,6 @@ def load_people_expos():
|
||||
print("", flush=True)
|
||||
ensure_users_are_persons()
|
||||
|
||||
|
||||
def ensure_users_are_persons():
|
||||
# Just ensure this is up to date.
|
||||
print(f"# ensure_users_are_persons()")
|
||||
|
@ -75,6 +75,10 @@ Loser Expo 2025 SIGN-UP Form
|
||||
</button>
|
||||
{% endif %}
|
||||
<hr>
|
||||
<span style="color:red; font-family: monospace; font-weight: bold;">
|
||||
{{ form.errors }} <br /> <!-- why are the field errors not being reported against the field as a red outline?? -->
|
||||
{{ form.non_field_errors }} <!-- form validation errors appear here, and also at the top of the form-->
|
||||
</span>
|
||||
<form action="{% url 'signup' %}" method="post">
|
||||
{% csrf_token %}
|
||||
|
||||
@ -89,25 +93,25 @@ Loser Expo 2025 SIGN-UP Form
|
||||
<td align="right"><i>Full</i> name:</td>
|
||||
<td>{{ form.name }}</td>
|
||||
<td align="right">Name:</td>
|
||||
<td>{{ form.kinname }}</td>
|
||||
<td>{{ form.kin_name }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">Address:</td>
|
||||
<td>{{ form.address }}</td>
|
||||
<td align="right">Address:</td>
|
||||
<td>{{ form.kinaddress }}</td>
|
||||
<td>{{ form.kin_address }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">Phone:</td>
|
||||
<td>{{ form.phone }}</td>
|
||||
<td align="right">Phone:</td>
|
||||
<td>{{ form.kinphone }}</td>
|
||||
<td>{{ form.kin_phone }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">Email:</td>
|
||||
<td>{{ form.email }}</td>
|
||||
<td align="right">Email:</td>
|
||||
<td>{{ form.kinemail }}</td>
|
||||
<td>{{ form.kin_email }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2"></td>
|
||||
|
40
templates/login/signupok.html
Normal file
40
templates/login/signupok.html
Normal file
@ -0,0 +1,40 @@
|
||||
<!-- frontpage.html - this text visible because this template has been included -->
|
||||
{% extends "base.html" %}
|
||||
|
||||
|
||||
{% block title %}Cambridge Expeditions to Austria{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<title>Loser Expo {{year}} Sign-up Form Completed</title>
|
||||
|
||||
<h1>Expo {{year}} {{dates}}</h1>
|
||||
|
||||
|
||||
<div id="col1">
|
||||
<h3>You have signed up to attend the next Expo</h3>
|
||||
<p class="indent">
|
||||
You have signed up as {{signup_user.username}} - {{signup_user.email}}
|
||||
<p class="indent">
|
||||
Your signup has been registered. Please now register your email on the email announcements list if
|
||||
you have not already done so:
|
||||
<ul>
|
||||
<li><a href="https://lists.wookware.org/cgi-bin/mailman/listinfo/expo">lists.wookware.org : expo</a>
|
||||
</ul>
|
||||
</p>
|
||||
<p class="indent">
|
||||
This is the beginning of becoming part of the team for Expo {{year}}. There are training events and
|
||||
organisation to do, kit-lists to organise, and your dates on expo need to be agreed with Expo. We
|
||||
particularly need adequate manpower to de-rig the caves and pack up at the end of Expo.
|
||||
<p class="indent">
|
||||
You next jobs to do: see the <a href="/kanboard/board/2">Expo Kanboard</a>.
|
||||
<br />
|
||||
<!-- <img src="/expofiles/photos/2007/selected/eishoehle5nial.jpg">-->
|
||||
<figure align=center>
|
||||
<img src="/expofiles/photos/2007/selected/eishoehle4nial.jpg" width="250px">
|
||||
<figcaption>Nial in <a href="/expofiles/photos/2007/selected/">Eishohle in 2007</a>.</figcaption>
|
||||
</figure>
|
||||
{% endblock content %}
|
||||
|
||||
{% block margins %}
|
||||
|
||||
{% endblock margins %}
|
3
urls.py
3
urls.py
@ -57,7 +57,7 @@ from troggle.core.views.other import controlpanel, exportlogbook, frontpage, tod
|
||||
from troggle.core.views.prospect import prospecting
|
||||
from troggle.core.views.user_registration import register, newregister, reset_done, ExpoPasswordResetForm
|
||||
from troggle.core.views.scans import allscans, cavewallets, scansingle, walletslistperson, walletslistyear
|
||||
from troggle.core.views.signup import signup
|
||||
from troggle.core.views.signup import signup, signupok
|
||||
from troggle.core.views.uploads import dwgupload, expofilerename, gpxupload, photoupload
|
||||
from troggle.core.views.wallets_edit import walletedit
|
||||
|
||||
@ -144,6 +144,7 @@ trogglepatterns = [
|
||||
path('logbookedit/', logbookedit, name='logbookedit'),
|
||||
path('logbookedit/<slug:slug>', logbookedit, name='logbookedit'),
|
||||
path('signup', signup, name='signup'),
|
||||
path('signupok', signupok, name='signupok'),
|
||||
|
||||
# Renaming an uploaded file
|
||||
path('expofilerename/<path:filepath>', expofilerename, name='expofilerename'),
|
||||
|
Loading…
x
Reference in New Issue
Block a user