summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilip Sargent <philip.sargent@gmail.com>2025-02-13 15:10:12 +0000
committerPhilip Sargent <philip.sargent@gmail.com>2025-02-13 15:10:12 +0000
commit3fb99eb4be5f1c3199bdc2bab3c81f3195bf8710 (patch)
treef226a4dcf5a595fa846bcffab8e54c65b6881e9e
parent3a3e5765f921d30a10ca3eff3db616fb4b0d58fe (diff)
downloadtroggle-3fb99eb4be5f1c3199bdc2bab3c81f3195bf8710.tar.gz
troggle-3fb99eb4be5f1c3199bdc2bab3c81f3195bf8710.tar.bz2
troggle-3fb99eb4be5f1c3199bdc2bab3c81f3195bf8710.zip
lgoing/cookie interaction betetr
-rw-r--r--core/utils.py52
-rw-r--r--core/views/editor_helpers.py126
-rw-r--r--core/views/expo.py33
-rw-r--r--parsers/users.py4
4 files changed, 131 insertions, 84 deletions
diff --git a/core/utils.py b/core/utils.py
index 5e03971..26be1a0 100644
--- a/core/utils.py
+++ b/core/utils.py
@@ -168,25 +168,6 @@ 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)
@@ -233,14 +214,40 @@ def parse_aliases(aliasfile):
return [(None, None)], "Fail on file reading"
return aliases, report
+def get_editor(request):
+ current_user = request.user
+ if is_identified_user(current_user):
+ return get_git_string(current_user)
+ else:
+ return get_cookie(request)
+
+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 get_cookie(request):
"""The initial idea of having a default turned out to be a bad idea as people just ignore the field.
- if the default value is blank, then the form validation code makes the user type something in,
- so having a blank is best.
+ if the default value is blank, then the form validation code makes the user type something in.
+ So having a blank is best if the cookie is to be displayed as the first value seen on a form.
+ But if the cookie is to be stored, then "Unset" may be better.
"""
# NO_COOKIE_DEFAULT = 'Unset Cookie <hohlenforscher@potatohut.expo>'
# print(f"-- Getting cookie...")
- editor_id = request.COOKIES.get('editor_id', "") # if no cookie, then default string ""
+ editor_id = request.COOKIES.get('editor_id', "")
editor = git_string(editor_id) # belt and braces, should have been validity checked on saving already
# print(f"-- Cookie to be used: {editor=}")
return editor
@@ -268,7 +275,6 @@ def git_string(author_string):
print(f"++ Not git-compatible author string '{author_string}', replacing as '{editor}'")
return editor
-
def git_add(filename, cwd, commands=[]):
"""Add a file to the list of Staged files ready for a later git commit
"""
diff --git a/core/views/editor_helpers.py b/core/views/editor_helpers.py
index db5143b..834a4f6 100644
--- a/core/views/editor_helpers.py
+++ b/core/views/editor_helpers.py
@@ -17,8 +17,11 @@ from PIL import Image
import troggle.settings as settings
from troggle.core.utils import ( COOKIE_MAX_AGE,
- WriteAndCommitError, get_cookie, git_string, write_binary_file,
- write_and_commit, current_expo, random_slug, ensure_dir_exists
+ WriteAndCommitError, get_editor,
+ git_string,
+ write_binary_file, write_and_commit,
+ current_expo, random_slug, ensure_dir_exists,
+ is_identified_user
)
from .auth import login_required_if_public
@@ -115,47 +118,71 @@ def dms2dd(degrees, minutes, seconds, direction):
def extract_gps(dict):
"""Produce a set of annotations to add to an image description
+
+ The problem is that at any time one or more of the exif data points might
+ be missing from a particular photo, even GPSVersionID, so we need a lot
+ of data existence checking or it will crash.
"""
+ def is_present(gpsifd):
+ item = getattr(piexif.GPSIFD, gpsifd)
+ if item in dict:
+ print(f" {gpsifd} = {item}")
+ return dict[item]
+ return None
+
+ def extract(gpsifd):
+ if item:=is_present(gpsifd): # walrus
+ n, d = item
+ return n/d
+ return None
+
def rational(tup):
nom, denom = tup
return nom/denom
-
- def extract(gpsifd):
- print(piexif.GPSIFD)
- n, d = dict[getattr(piexif.GPSIFD, gpsifd)]
- return n/d
-
-
compass_points = ["N", "NE", "E", "SE", "S", "SW", "W", "NW", "N"]
- bearing = extract("GPSImgDirection")
- compass_lookup = round(bearing / 45)
- nsew = compass_points[compass_lookup]
- if dict[piexif.GPSIFD.GPSImgDirectionRef] == b"M":
- ref = "Magnetic"
- elif dict[piexif.GPSIFD.GPSImgDirectionRef] == b"T":
- ref = "True"
- direction = f"Direction of view: {nsew:2} ({bearing:.0f}&deg;{ref})"
+ if bearing := extract("GPSImgDirection"):
+ compass_lookup = round(bearing / 45)
+ nsew = compass_points[compass_lookup]
+ if item := is_present("GPSImgDirectionRef"):
+ if item == b"M":
+ ref = "Magnetic"
+ elif item == b"T":
+ ref = "True"
+ else:
+ ref =""
+ direction = f"Direction of view: {nsew:2} ({bearing:.0f}&deg;{ref})"
+ else:
+ direction = ""
-
- print(f"{dict[piexif.GPSIFD.GPSVersionID]=}")
+ if version := is_present("GPSVersionID"):
+ print(f"GPS exif {version=}")
-
+ if alt := extract("GPSAltitude"):
+ altitude = f"{alt:.0f}m above sea-level"
+ else:
+ altitude = ""
+
- alt = extract("GPSAltitude")
- altitude = f"{alt:.0f}m above sea-level"
- ds = dict[piexif.GPSIFD.GPSDateStamp]
- hf, mf, sf = dict[piexif.GPSIFD.GPSTimeStamp]
- h = rational(hf)
- m = rational(mf)
- s = rational(sf)
-
- timestamp_utc = f"{ds.decode()} {h:02.0f}:{m:02.0f}:{s:02.0f} +00:00 UTC"
+ if ds := is_present("GPSDateStamp"):
+ ds = ds.decode()
+ else:
+ ds = ""
+
+ if item := is_present("GPSTimeStamp"):
+ hf, mf, sf = item
+ h = rational(hf)
+ m = rational(mf)
+ s = rational(sf)
+ timestamp_utc = f"{ds} {h:02.0f}:{m:02.0f}:{s:02.0f} +00:00 UTC"
+ else:
+ timestamp_utc = f"{ds}"
+
print(direction)
print(altitude)
print(timestamp_utc)
- # location = dms2dd()
+ # location = dms2dd() # to do...
return f"{direction}<br />{altitude}</br />{timestamp_utc}<br />"
@@ -176,12 +203,18 @@ def new_image_form(request, path):
directory = get_dir(path)
# print(f"new_image_form(): {directory=} {path=}")
- editor = get_cookie(request)
+ identified_login = is_identified_user(request.user)
+ editor = get_editor(request)
# print(f"{django_settings.FILE_UPLOAD_MAX_MEMORY_SIZE=}")
# FILE_UPLOAD_MAX_MEMORY_SIZE = 0 # force uploaded files to be temporary in /tmp, not in-memory
if request.method == "POST":
# print(f"new_image_form(): POST ")
- form = NewWebImageForm(request.POST, request.FILES, directory=directory)
+ form = NewWebImageForm(request.POST, request.FILES, directory=directory)
+ if identified_login:
+ # disable editing the git id string as we get it from the logged-on user data
+ form.fields["who_are_you"].widget.attrs["readonly"]="readonly"
+ print(form.fields["who_are_you"].widget.attrs)
+
if form.is_valid():
# print(f"new_image_form(): form is valid ")
year = form.cleaned_data["year"]
@@ -271,14 +304,15 @@ def new_image_form(request, path):
# print(full_path, full_path.parent)
full_path.parent.mkdir(parents=True, exist_ok=True)
try:
- change_message = form.cleaned_data["change_message"]
+ # change_message = form.cleaned_data["change_message"]
write_and_commit(
[
(desc_path, image_page, "utf-8"),
(image_path, ib.getbuffer(), False),
(thumb_path, tb.getbuffer(), False),
],
- f"{change_message} - online adding of an image",
+ # f"{change_message} - online adding of an image",
+ f"Online adding of an image",
editor # this works, a new who_are_you typed on the Image form is used as the git comment
)
except WriteAndCommitError as e:
@@ -302,6 +336,11 @@ def new_image_form(request, path):
"year": "", "photographer": extract_git_name(editor),
"change_message": "Uploading photo"}
form = NewWebImageForm(directory=directory, initial=initial )
+ if identified_login:
+ # disable editing the git id string as we get it from the logged-on user data
+ form.fields["who_are_you"].widget.attrs["readonly"]="readonly"
+ print(form.fields["who_are_you"].widget.attrs)
+
# print(f"new_image_form(): POST and not POST ")
template = loader.get_template("new_image_form.html")
htmlform = template.render({"form": form, "path": path}, request)
@@ -322,6 +361,8 @@ def save_original_in_expofiles(f, year, photographer):
get recorded properly in original format.
Django does small files <2.5 MB in memory, which is a pain.
+
+ to do: also store a *.url file with the image file saying where it is used in the handbook.
"""
if photographer:
photographer = photographer.strip().replace(" ","")
@@ -376,15 +417,18 @@ class NewWebImageForm(forms.Form):
year = forms.CharField(
widget=forms.TextInput(attrs={"size": "60", "placeholder": "Year photo was taken"}), required=False
)
- change_message = forms.CharField(
- widget=forms.Textarea(attrs={"cols": 80, "rows": 3, "placeholder": "Describe the change made (for git)"}), required=False
- )
+ # change_message = forms.CharField(
+ # widget=forms.Textarea(attrs={"cols": 80, "rows": 3, "placeholder": "Describe the change made (for git)"}), required=False
+ # )
who_are_you = forms.CharField(
- widget=forms.TextInput(
- attrs={"size": 60, "placeholder": "You are editing this page, who are you ? e.g. 'Becka' or 'Animal <mta@gasthof.expo>'",
- "style": "vertical-align: text-top;"}
+ widget=forms.TextInput(attrs={"style": "font-size: 90%", "size": "75",
+ "placeholder": "Anathema Device <anathema@potatohut.expo>",
+ "title":"Type in your real name, and your email between angle-brackets."
+ }),
+ # label = "Editor",
)
- )
+
+
def __init__(self, *args, **kwargs):
self.directory = Path(kwargs.pop("directory"))
diff --git a/core/views/expo.py b/core/views/expo.py
index d492820..79ad46a 100644
--- a/core/views/expo.py
+++ b/core/views/expo.py
@@ -17,9 +17,10 @@ from troggle.core.utils import (
COOKIE_MAX_AGE,
WriteAndCommitError,
current_expo,
- get_cookie,
- git_string,
- get_git_string,
+ get_editor,
+ # get_cookie,
+ # git_string,
+ # get_git_string,
write_and_commit,
is_identified_user
)
@@ -462,11 +463,8 @@ def editexpopage(request, path):
print("### File not found ### ", filepath)
filefound = False
- current_user = request.user
- if identified_login := is_identified_user(current_user):
- editor = get_git_string(current_user)
- else:
- editor = get_cookie(request)
+ identified_login = is_identified_user(request.user)
+ editor = get_editor(request)
if request.method == "POST": # If the form has been submitted...
pageform = ExpoPageForm(request.POST) # A form bound to the POST data
@@ -503,9 +501,9 @@ def editexpopage(request, path):
print(f"Cookie set: {editor} for {COOKIE_MAX_AGE/(24*3600)} days")
try:
change_message = pageform.cleaned_data["change_message"]
- if not identified_login:
- editor = pageform.cleaned_data["who_are_you"]
- editor = git_string(editor)
+ # if not identified_login:
+ # editor = pageform.cleaned_data["who_are_you"]
+ # editor = git_string(editor)
write_and_commit([(filepath, result, "utf-8")], f"{change_message} - online edit of {path}", editor)
except WriteAndCommitError as e:
return render(request, "errors/generic.html", {"message": e.message})
@@ -556,9 +554,10 @@ class ExpoPageForm(forms.Form):
identified_login = forms.BooleanField(required=False,widget=forms.CheckboxInput(attrs={"onclick":"return false"})) # makes 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>'",
- "style": "vertical-align: text-top;"}
- ),
- label = "Editor"
- )
+ widget=forms.TextInput(attrs={"style": "font-size: 90%", "size": "75",
+ "placeholder": "Anathema Device <anathema@potatohut.expo>",
+ "title":"Type in your real name, and your email between angle-brackets."
+ }),
+ label = "Editor",
+ )
+ \ No newline at end of file
diff --git a/parsers/users.py b/parsers/users.py
index fd971fb..662e5ba 100644
--- a/parsers/users.py
+++ b/parsers/users.py
@@ -20,12 +20,10 @@ Passwords are only ever stored as hashes using the standard Django functions.
"""
todo = """
-- Not fully tested, needs experience
-
- 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
+SUPER_USERS = ["philip-sargent", "wookey"] # list of userids who get the same rights as "expoadmin" i.e. the Django control panel
USERS_FILE = "users.json"
ENCRYPTED_DIR = "encrypted"