From d7fd6b00ae6845e5dfb7263a4f440e7ab36c145c Mon Sep 17 00:00:00 2001 From: Philip Sargent <philip.sargent@klebos.com> Date: Sat, 5 Mar 2022 17:05:15 +0000 Subject: [PATCH] Detect unwriteable file permissions earlier --- core/models/caves.py | 5 +++-- core/views/expo.py | 13 +++++++------ core/views/uploads.py | 3 +++ templates/expopage.html | 16 ++++++++-------- templates/menu.html | 3 ++- urls.py | 8 ++++++-- 6 files changed, 29 insertions(+), 19 deletions(-) diff --git a/core/models/caves.py b/core/models/caves.py index 6a07748..0a4cc3e 100644 --- a/core/models/caves.py +++ b/core/models/caves.py @@ -42,7 +42,8 @@ def writetrogglefile(filepath, filecontent): '''Set permissions to rw-rw-r-- and commit the new saved file to git Callers to cave.writeDataFile() or entrance.writeDataFile() should handle the exception PermissionsError explicitly ''' - # see also core/views/expo.py editexpopage() + # GIT see also core/views/expo.py editexpopage() + # GIT see also core/views/uploads.py dwgupload() filepath = Path(filepath) cwd = filepath.parent filename = filepath.name @@ -56,7 +57,7 @@ def writetrogglefile(filepath, filecontent): #os.chmod(filepath, 0o664) # set file permissions to rw-rw-r-- # should replace .call with .run and capture_output=True call([git, "add", filename], cwd=cwd) - call([git, "commit", "-m", 'Troggle online cave or entrance edit'], cwd=cwd) + call([git, "commit", "-m", f'Troggle online: cave or entrance edit -{filename}'], cwd=cwd) class Area(TroggleModel): diff --git a/core/views/expo.py b/core/views/expo.py index 3a89269..c6ef01b 100644 --- a/core/views/expo.py +++ b/core/views/expo.py @@ -142,7 +142,7 @@ def expowebpage(request, expowebpath, path): if m: editable = False else: - editable = True + editable = os.access(Path(expowebpath / path), os.W_OK) # are file permissions writeable? has_menu = False menumatch = re.match(r'(.*)<div id="menu">', body, re.DOTALL + re.IGNORECASE) @@ -253,7 +253,7 @@ def getmimetype(path): @ensure_csrf_cookie def editexpopage(request, path): '''Manages the 'Edit this Page' capability for expo handbook and other html pages. - Relies on javascript to provide the in-browser editing environment. + Relies on HTML5 or javascript to provide the in-browser editing environment. ''' try: # if a cave not a webpage at all. @@ -310,7 +310,8 @@ def editexpopage(request, path): cwd = filepath.parent filename = filepath.name git = settings.GIT - # see also core/models/cave.py writetrogglefile() + # GIT see also core/models/cave.py writetrogglefile() + # GIT see also core/views/uploads.py dwgupload() try: with open(filepath, "w") as f: print(f'WRITING{cwd}---{filename} ') @@ -328,11 +329,11 @@ def editexpopage(request, path): message = f'CANNOT git on server for this file {filename}. Edits saved but not added to git.\n\n' + msgdata return render(request,'errors/generic.html', {'message': message}) - cp_commit = subprocess.run([git, "commit", "-m", 'Edit this page'], cwd=cwd, capture_output=True, text=True) - # This produces return code = 1 if it commits OK, but if the repo still needs to be pushed to origin/expoweb + cp_commit = subprocess.run([git, "commit", "-m", f'Troggle online: Edit this page - {filename}'], cwd=cwd, capture_output=True, text=True) + # This produces return code = 1 if it commits OK, but when the repo still needs to be pushed to origin/expoweb if cp_commit.returncode != 0 and cp_commit.stdout != 'nothing to commit, working tree clean': msgdata = 'Ask a nerd to fix this.\n\n' + cp_commit.stderr + '\n\n' + cp_commit.stdout + '\n\nreturn code: ' + str(cp_commit.returncode) - message = f'Eror code with git on server for this file {filename}. Edits saved, added to git but NOT committed.\n\n' + msgdata + message = f'Error code with git on server for this file {filename}. Edits saved, added to git, but NOT committed.\n\n' + msgdata return render(request,'errors/generic.html', {'message': message}) except subprocess.SubprocessError: diff --git a/core/views/uploads.py b/core/views/uploads.py index b5b5168..2f3e053 100644 --- a/core/views/uploads.py +++ b/core/views/uploads.py @@ -144,6 +144,9 @@ def dwgupload(request, folder=None, gitdisable='no'): actual_saved = [] refused = [] + + # GIT see also core/views/expo.py editexpopage() + # GIT see also core/models/cave.py writetrogglefile() if gitdisable != 'yes': # set in url 'dwguploadnogit/' git = settings.GIT else: diff --git a/templates/expopage.html b/templates/expopage.html index fb706bc..fab3bc1 100644 --- a/templates/expopage.html +++ b/templates/expopage.html @@ -4,13 +4,13 @@ {% block bodyattrs %}{% if homepage %} id="homepage"{% endif %}{% endblock %} {% block body %} {{ body|safe }} -{% if homepage %} - {% if editable %} - <a href="{% url "editexpopage" path %}">Edit</a> - {% endif %} - {% else %} - {% if not has_menu %} - {% include "menu.html" %} +{% if homepage %} + {% if editable %} + <a href="{% url "editexpopage" path %}">Edit</a> {% endif %} - {% endif %} +{% else %} + {% if not has_menu %} + {% include "menu.html" %} + {% endif %} +{% endif %} {% endblock %} diff --git a/templates/menu.html b/templates/menu.html index c22b38d..502a31b 100644 --- a/templates/menu.html +++ b/templates/menu.html @@ -11,7 +11,8 @@ <li><form name=P method=get action="/search" target="_top"> <input id="omega-autofocus" type=search name=P size=8 autofocus> <input type=submit value="Search"></li> -{% if editable %}<li><a href="{% url "editexpopage" path %}" class="editlink"><strong>Edit this page</strong></a></li>{% endif %} +{% if editable %}<li><a href="{% url "editexpopage" path %}" class="editlink"><strong>Edit this page</strong></a></li> +{% else %}<a href="/handbook/computing/hbmanual1.html#auto">This page not editable</a></li>{% endif %} {% if cave_editable %}<li><a href="{% url "edit_cave" cave.slug %}" class="editlink"><strong>Edit this cave</strong></a></li>{% endif %} </ul> {% endif %} diff --git a/urls.py b/urls.py index 1aaa303..77f9c8d 100644 --- a/urls.py +++ b/urls.py @@ -71,6 +71,9 @@ else: # accounts/reset/<uidb64>/<token>/ [name='password_reset_confirm'] # accounts/reset/done/ [name='password_reset_complete'] +# BUT many of these are set up by opinionated Django even if 'django.contrib.auth.urls' is NOT included. +# Some overlap with 'admin.site.urls' needs to be investigated. + trogglepatterns = [ path('expofiles/', include(expofilesurls)), # intercepted by Apache, if it is running. path('expofiles', include(expofilesurls)), # curious interaction with the include() here, not just a slash problem. @@ -171,7 +174,7 @@ trogglepatterns = [ re_path(r'^cave/(?P<cave_id>[^/]+)/(?P<year>\d\d\d\d)-(?P<qm_id>\d*)(?P<grade>[ABCDX]?)?$', caves.qm, name="qm"), # Prospecting Guide document - re_path(r'^prospecting_guide/$', prospecting), + re_path(r'^prospecting_guide/$', prospecting), # disabled. Bad links, incompatible image package use and very, very out of date. # This next set are all intercepted by Apache, if it is running. re_path(r'^photos/(?P<subpath>.*)$', mediapage, {'doc_root': settings.PHOTOS_ROOT}, name="mediapage"), # photo galleries @@ -203,7 +206,8 @@ urlpatterns = [ # Alias /robots.txt /home/expo/troggle/media/robots.txt # does not exist! # Alias /favicon.ico /home/expo/troggle/media/favicon.ico # comes from /expoweb/* when running runserver # Alias /javascript /home/expo/troggle/media/jslib # empty -# Alias /search ? # teh text search thinggy +# Alias /search ? # the Xapian text search thinggy +# Alias /kanboard ? # the Kanban Trello-clone thinggy # Copy of old standard apache configurations: # Alias /expofiles /home/expo/expofiles