summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--_deploy/debian_server160
-rw-r--r--core/models/troggle.py10
-rw-r--r--core/utils.py19
-rw-r--r--core/views/expo.py20
-rw-r--r--core/views/other.py2
-rw-r--r--core/views/signup.py41
-rw-r--r--parsers/users.py13
-rw-r--r--templates/login/signup.html4
8 files changed, 65 insertions, 204 deletions
diff --git a/_deploy/debian_server b/_deploy/debian_server
deleted file mode 100644
index 3c5293e..0000000
--- a/_deploy/debian_server
+++ /dev/null
@@ -1,160 +0,0 @@
-import os
-import sys
-import urllib.parse
-from pathlib import Path
-
-"""Settings for a troggle installation which may vary among different
-installations: for development or deployment, in a docker image or
-python virtual environment (venv), on ubuntu, debian or in Windows
-System for Linux (WSL), on the main server or in the potato hut,
-using SQLite or mariaDB.
-
-It sets the directory locations for the major parts of the system so
-that e.g. expofiles can be on a different filesystem.
-
-This file is included at the end of the main troggle/settings.py file so that
-it overwrites defaults in that file.
-
-NOTE this file is vastly out of sync with troggle/_deploy/wsl/localsettings.py
-which is the most recent version used in active maintenance. There should be
-essential differences, but there and many, many non-essential differences which
-should be eliminated for clarity and to use modern idioms. 8 March 2023.
-"""
-
-print(" * importing troggle/localsettings.py")
-
-# DO NOT check this file into the git repo - it contains real passwords.
-
-EXPOFILESREMOTE = False # if True, then re-routes urls in expofiles to remote sever
-#SECURE_SSL_REDIRECT = True # breaks 7 tests in test suite 301 not 200 (or 302) and runserver fails completely
-
-DATABASES = {
- 'default': {
- 'ENGINE': 'django.db.backends.mysql', # 'postgresql_psycopg2', 'mysql', 'sqlite3' or 'oracle'.
- 'NAME' : 'troggle', # Or path to database file if using sqlite3.
- 'USER' : 'expo', # Not used with sqlite3.
- 'PASSWORD' : 'uFqP56B4XleeyIW', # Not used with sqlite3.
- 'HOST' : '', # Set to empty string for localhost. Not used with sqlite3.
- 'PORT' : '', # Set to empty string for default. Not used with sqlite3.
- }
-}
-
-
-EXPOUSER = 'expo'
-EXPOUSERPASS = '161:gosser'
-EXPOADMINUSER = 'expoadmin'
-EXPOADMINUSERPASS = 'gosser:161'
-EXPOUSER_EMAIL = 'wookey@wookware.org'
-EXPOADMINUSER_EMAIL = 'wookey@wookware.org'
-
-REPOS_ROOT_PATH = '/home/expo/'
-sys.path.append(REPOS_ROOT_PATH)
-sys.path.append(REPOS_ROOT_PATH + 'troggle')
-# Define the path to the django app (troggle in this case)
-PYTHON_PATH = REPOS_ROOT_PATH + 'troggle/'
-
-
-PHOTOS_YEAR = "2023"
-# add in 358 when they don't make it crash horribly
-NOTABLECAVESHREFS = [ "290", "291", "359", "264", "258", "204", "76", "107"]
-
-TEMPLATES = [
- {
- 'BACKEND': 'django.template.backends.django.DjangoTemplates',
- 'DIRS': [
- PYTHON_PATH + "templates"
- ],
- 'OPTIONS': {
- 'debug': 'DEBUG',
- 'context_processors': [
- # django.template.context_processors.csrf, # is always enabled and cannot be removed, sets csrf_token
- 'django.contrib.auth.context_processors.auth', # knowledge of logged-on user & permissions
- 'core.context.troggle_context', # in core/troggle.py
- 'django.template.context_processors.debug',
- #'django.template.context_processors.request', # copy of current request, added in trying to make csrf work
- 'django.template.context_processors.i18n',
- 'django.template.context_processors.media', # includes a variable MEDIA_URL
- 'django.template.context_processors.static', # includes a variable STATIC_URL
- 'django.template.context_processors.tz',
- 'django.contrib.messages.context_processors.messages',
- ],
- 'loaders': [
- 'django.template.loaders.filesystem.Loader',
- 'django.template.loaders.app_directories.Loader', #For each app, inc admin, in INSTALLED_APPS, loader looks for /templates
- # insert your own TEMPLATE_LOADERS here
- ]
- },
- },
-]
-
-PUBLIC_SITE = True
-
-# This should be False for normal running
-DEBUG = True
-CACHEDPAGES = True # experimental page cache for a handful of page types
-
-
-# executables:
-CAVERN = 'cavern' # for parsing .svx files and producing .2d files
-SURVEXPORT = 'survexport' # for parsing .3d files and producing .pos files
-
-PV = "python" + str(sys.version_info.major) + "." + str(sys.version_info.minor)
-LIBDIR = Path(REPOS_ROOT_PATH) / 'lib' / PV
-
-EXPOWEB = Path(REPOS_ROOT_PATH + 'expoweb/')
-SURVEYS = REPOS_ROOT_PATH
-SURVEY_SCANS = REPOS_ROOT_PATH + 'expofiles/surveyscans/'
-FILES = REPOS_ROOT_PATH + 'expofiles'
-PHOTOS_ROOT = REPOS_ROOT_PATH + 'expofiles/photos/'
-
-TROGGLE_PATH = Path(__file__).parent
-TEMPLATE_PATH = TROGGLE_PATH / 'templates'
-MEDIA_ROOT = TROGGLE_PATH / 'media'
-JSLIB_ROOT = TROGGLE_PATH / 'media' / 'jslib' # used for CaveViewer JS utility
-
-
-CAVEDESCRIPTIONS = EXPOWEB / "cave_data"
-ENTRANCEDESCRIPTIONS = EXPOWEB / "entrance_data"
-
-
-PYTHON_PATH = REPOS_ROOT_PATH + 'troggle/'
-
-
-#URL_ROOT = 'http://expo.survex.com/'
-URL_ROOT = '/'
-DIR_ROOT = Path("") #this should end in / if a value is given
-EXPOWEB_URL = '/'
-SURVEYS_URL = '/survey_scans/'
-
-REPOS_ROOT_PATH = Path(REPOS_ROOT_PATH)
-
-SURVEX_DATA = REPOS_ROOT_PATH / "loser"
-DRAWINGS_DATA = REPOS_ROOT_PATH / "drawings"
-
-
-EXPOFILES = REPOS_ROOT_PATH / "expofiles"
-SCANS_ROOT = EXPOFILES / "surveyscans"
-PHOTOS_ROOT = EXPOFILES / "photos"
-
-#EXPOFILES = urllib.parse.urljoin(REPOS_ROOT_PATH, 'expofiles/')
-PHOTOS_URL = urllib.parse.urljoin(URL_ROOT, '/photos/')
-
-# MEDIA_URL is used by urls.py in a regex. See urls.py & core/views_surveys.py
-MEDIA_URL = '/site_media/'
-
-
-STATIC_URL = urllib.parse.urljoin(URL_ROOT , '/static/') # used by Django admin pages. Do not delete.
-JSLIB_URL = urllib.parse.urljoin(URL_ROOT , '/javascript/') # always fails, try to revive it ?
-# STATIC_ROOT removed after merging content into MEDIA_ROOT. See urls.py & core/views/surveys.py
-
-#TINY_MCE_MEDIA_ROOT = STATIC_ROOT + '/tiny_mce/' # not needed while TinyMCE not installed
-#TINY_MCE_MEDIA_URL = STATIC_URL + '/tiny_mce/' # not needed while TinyMCE not installed
-
-LOGFILE = '/var/log/troggle/troggle.log'
-IMPORTLOGFILE = '/var/log/troggle/import.log'
-
-# Sanitise these to be strings as Django seems to be particularly sensitive to crashing if they aren't
-STATIC_URL = str(STATIC_URL) + "/"
-MEDIA_URL = str(MEDIA_URL) + "/"
-
-print(" + finished importing troggle/localsettings.py")
diff --git a/core/models/troggle.py b/core/models/troggle.py
index 6155347..62fe9c1 100644
--- a/core/models/troggle.py
+++ b/core/models/troggle.py
@@ -78,7 +78,12 @@ class Expedition(TroggleModel):
return reverse("expedition", args=[self.year])
class Person(TroggleModel):
- """single Person, can go on many years"""
+ """single Person, can go on expo many years
+
+ Note that the class "User" and the class "Group
+ are standrd Django classes
+ definied in django.contrib.auth.models
+ """
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
@@ -100,8 +105,7 @@ class Person(TroggleModel):
def get_absolute_url(self):
# we do not use URL_ROOT any more.
return reverse("person", kwargs={"slug": self.slug})
- return reverse("person", kwargs={"first_name": self.first_name, "last_name": self.last_name})
-
+
class Meta:
verbose_name_plural = "People"
ordering = ("orderref",) # "Wookey" makes too complex for: ('last_name', 'first_name')
diff --git a/core/utils.py b/core/utils.py
index 33872b3..d88f39f 100644
--- a/core/utils.py
+++ b/core/utils.py
@@ -157,6 +157,25 @@ def current_expo():
else:
return settings.EPOCH.year # this is 1970
+def is_identified_user(user):
+ if user.is_anonymous:
+ return False
+ if user.username in ["expo", "expoadmin"]:
+ return False
+ return True
+
+def get_git_string(user):
+ if not is_identified_user(user):
+ return None
+ else:
+ people = Person.objects.filter(user=user)
+ if len(people) != 1:
+ # someone like "fluffy-bunny" not associated with a Person
+ return None
+ person = people[0]
+ return f"{person.fullname} <{user.email}>"
+
+
def parse_aliases(aliasfile):
"""Reads a long text string containing pairs of strings:
(alias, target)
diff --git a/core/views/expo.py b/core/views/expo.py
index 89215a4..63f1d33 100644
--- a/core/views/expo.py
+++ b/core/views/expo.py
@@ -19,7 +19,9 @@ from troggle.core.utils import (
current_expo,
get_cookie,
git_string,
+ get_git_string,
write_and_commit,
+ is_identified_user
)
from troggle.core.views.editor_helpers import HTMLarea
from troggle.core.views.uploads import edittxtpage
@@ -455,15 +457,17 @@ def editexpopage(request, path):
print("### File not found ### ", filepath)
filefound = False
- editor = get_cookie(request)
-
+ current_user = request.user
+ if identified_login := is_identified_user(current_user):
+ editor = get_git_string(current_user)
+ else:
+ editor = get_cookie(request)
+
if request.method == "POST": # If the form has been submitted...
pageform = ExpoPageForm(request.POST) # A form bound to the POST data
if pageform.is_valid(): # Form valid therefore write file
editor = pageform.cleaned_data["who_are_you"]
editor = git_string(editor)
- # print("### \n", str(pageform)[0:300])
- # print("### \n csrfmiddlewaretoken: ",request.POST['csrfmiddlewaretoken'])
if filefound:
headmatch = re.match(r"(.*)<title>.*</title>(.*)", head, re.DOTALL + re.IGNORECASE)
if headmatch:
@@ -490,7 +494,7 @@ def editexpopage(request, path):
if not filefound or result != html: # Check if content changed at all
edit_response = HttpResponseRedirect(reverse("expopage", args=[path])) # Redirect after POST
edit_response.set_cookie('editor_id', editor, max_age=COOKIE_MAX_AGE) # cookie expires after COOKIE_MAX_AGE seconds
- print(f"Cookie set: {editor} for {COOKIE_MAX_AGE/3600} hours")
+ print(f"Cookie set: {editor} for {COOKIE_MAX_AGE/(24*3600)} days")
try:
change_message = pageform.cleaned_data["change_message"]
editor = pageform.cleaned_data["who_are_you"]
@@ -507,9 +511,9 @@ def editexpopage(request, path):
(title,) = m.groups()
else:
title = ""
- pageform = ExpoPageForm(initial={"who_are_you":editor, "html": body, "title": title})
+ pageform = ExpoPageForm(initial={"identified_login": identified_login, "who_are_you":editor, "html": body, "title": title})
else:
- pageform = ExpoPageForm(initial={"who_are_you":editor})
+ pageform = ExpoPageForm(initial={"identified_login": identified_login, "who_are_you":editor})
return render(
@@ -540,6 +544,8 @@ class ExpoPageForm(forms.Form):
"style": "vertical-align: text-top;"}
)
)
+ identified_login = forms.BooleanField(widget=forms.CheckboxInput(attrs={"onclick":"return false"})) # make it readonly
+
who_are_you = forms.CharField(
widget=forms.Textarea(
attrs={"cols": 90, "rows": 1, "placeholder": "You have edited this page, who are you ? e.g. 'Animal <mta@gasthof.expo>'",
diff --git a/core/views/other.py b/core/views/other.py
index ab2f8a7..a0a2a0c 100644
--- a/core/views/other.py
+++ b/core/views/other.py
@@ -163,7 +163,7 @@ def controlpanel(request):
return render(
request,
"controlPanel.html",
- {"error": ' - Needs "expoadmin" logon. \nLogout and login again.',
+ {"error": ' - Needs "expoadmin" or superuser logon. \nLogout and login again.',
"year": current_expo()}
)
diff --git a/core/views/signup.py b/core/views/signup.py
index 4b7e398..e46ca49 100644
--- a/core/views/signup.py
+++ b/core/views/signup.py
@@ -8,21 +8,19 @@ from django.shortcuts import redirect, render
from django.urls import reverse
import troggle.settings as settings
+from troggle.core.models.troggle import DataIssue, Person
+from troggle.core.views.editor_helpers import HTMLarea
from troggle.core.utils import (
COOKIE_MAX_AGE,
WriteAndCommitError,
+ add_commit,
current_expo,
get_cookie,
+ get_git_string,
git_string,
+ is_identified_user,
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,
- write_and_commit,
- current_expo
-)
from troggle.parsers.users import get_encryptor, ENCRYPTED_DIR, how_many_previous_expos
@@ -51,27 +49,17 @@ def signupok(request):
{"year": SIGNUP_YEAR, "dates": SIGNUP_DATES, "signup_user": signup_user, "signedup_people": signedup_people},
)
+
def signup(request):
"""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.
+ who is being signed up. You can't signup someone else.
"""
signup_user = request.user
-
- if signup_user.is_anonymous:
- personal_login = False
- 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}>"
+ identified_login = is_identified_user(signup_user)
+
+ if identified_login:
+ editor = get_git_string(signup_user)
else:
editor = f"troggle <signup_anon@austria.expo>"
@@ -89,7 +77,7 @@ def signup(request):
print(f" # Signup form INVALID\n{pageform.errors} ")
return render(
request, "login/signup.html",
- {"form": pageform, "personal_login": personal_login,
+ {"form": pageform, "identified_login": identified_login,
"year": SIGNUP_YEAR, "dates": SIGNUP_DATES,
}
)
@@ -107,16 +95,15 @@ def signup(request):
"top_tent_cap": 2,
"base_tent_cap": 3,
}
- if personal_login:
+ if identified_login:
initial_context["name"] = signup_person.fullname
initial_context["email"] = signup_user.email
initial_context["experience"] = experience
-
pageform = ExpoSignupForm(initial=initial_context)
return render(
request, "login/signup.html",
- {"form": pageform, "personal_login": personal_login,
+ {"form": pageform, "identified_login": identified_login,
"year": SIGNUP_YEAR, "dates": SIGNUP_DATES,
},
)
diff --git a/parsers/users.py b/parsers/users.py
index 97d06a0..30b491b 100644
--- a/parsers/users.py
+++ b/parsers/users.py
@@ -22,11 +22,11 @@ Passwords are only ever stored as hashes using the standard Django functions.
todo = """
- Not fully tested, needs experience
-- Need to write to BierBook for signups
-
- Need to check/register with lists.wookware.org for email
"""
+SUPER_USERS = ["philip-sargent"] # list of userids who get the same rights as "expoadmin" i.e. the Django control panel
+
USERS_FILE = "users.json"
ENCRYPTED_DIR = "encrypted"
@@ -54,8 +54,13 @@ def register_user(u, email, password=None, pwhash=None, fullname=""):
# user.set_password(None) # use Django special setting for invalid password, but then FAILS to send password reset email
user.set_password("secret") # Why is the Django logic broken. Hmph.
print(f" # setting INVALID password for user {u}, must be reset by password_reset")
- user.is_staff = False
- user.is_superuser = False
+ if u in SUPER_USERS:
+ user.is_staff = True
+ user.is_superuser = True
+ print(f"** {u} is SUPER and can access everything on the Django control panel")
+ else:
+ user.is_staff = False
+ user.is_superuser = False
user.save()
print(f" - receated and reset user '{user}'")
except Exception as e:
diff --git a/templates/login/signup.html b/templates/login/signup.html
index 68b681d..815c2ec 100644
--- a/templates/login/signup.html
+++ b/templates/login/signup.html
@@ -45,7 +45,7 @@ Loser Expo {{year}} SIGN-UP Form
<p>Submitting this form will subscribe you to the expo mailing list
if you are not already subscribed.
</p>
- {% if personal_login %}
+ {% if identified_login %}
{% else %}
<button class="fancybutton" style="padding: 0.5em 25px; font-size: 100%;" onclick="window.location.href='/accounts/register/'" value = "Go to">
You need to register a personal login before you can signup to attend &rarr;
@@ -166,7 +166,7 @@ Loser Expo {{year}} SIGN-UP Form
<h2>All done?</h2>
<!-- <p>Click the <b>Preview</b> button below to review your submission.</p> -->
<div style="text-align: center">
- {% if personal_login %}
+ {% if identified_login %}
<button class="fancybutton" style="padding: 0.5em 25px; font-size: 100%;" type = "submit" >
Submit &rarr;
</button>