mirror of
https://expo.survex.com/repositories/troggle/.git
synced 2026-02-11 06:56:49 +00:00
Use logon not cookie when editing pages
This commit is contained in:
@@ -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")
|
||||
@@ -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')
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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>'",
|
||||
|
||||
@@ -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()}
|
||||
|
||||
)
|
||||
|
||||
@@ -8,20 +8,18 @@ from django.shortcuts import redirect, render
|
||||
from django.urls import reverse
|
||||
|
||||
import troggle.settings as settings
|
||||
from troggle.core.utils import (
|
||||
COOKIE_MAX_AGE,
|
||||
WriteAndCommitError,
|
||||
current_expo,
|
||||
get_cookie,
|
||||
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 (
|
||||
COOKIE_MAX_AGE,
|
||||
WriteAndCommitError,
|
||||
add_commit,
|
||||
current_expo,
|
||||
get_cookie,
|
||||
get_git_string,
|
||||
git_string,
|
||||
is_identified_user,
|
||||
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,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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 →
|
||||
@@ -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 →
|
||||
</button>
|
||||
|
||||
Reference in New Issue
Block a user