diff options
author | Philip Sargent <philip.sargent@gmail.com> | 2025-02-13 15:10:12 +0000 |
---|---|---|
committer | Philip Sargent <philip.sargent@gmail.com> | 2025-02-13 15:10:12 +0000 |
commit | 3fb99eb4be5f1c3199bdc2bab3c81f3195bf8710 (patch) | |
tree | f226a4dcf5a595fa846bcffab8e54c65b6881e9e | |
parent | 3a3e5765f921d30a10ca3eff3db616fb4b0d58fe (diff) | |
download | troggle-3fb99eb4be5f1c3199bdc2bab3c81f3195bf8710.tar.gz troggle-3fb99eb4be5f1c3199bdc2bab3c81f3195bf8710.tar.bz2 troggle-3fb99eb4be5f1c3199bdc2bab3c81f3195bf8710.zip |
lgoing/cookie interaction betetr
-rw-r--r-- | core/utils.py | 52 | ||||
-rw-r--r-- | core/views/editor_helpers.py | 126 | ||||
-rw-r--r-- | core/views/expo.py | 33 | ||||
-rw-r--r-- | parsers/users.py | 4 |
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}°{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}°{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" |