first quick pass of user menu in navbar which shows simple read only prefs content, and a logout option that works
This commit is contained in:
22
BUGs
22
BUGs
@@ -1,7 +1,27 @@
|
|||||||
### Next: 80
|
### Next: 81
|
||||||
BUG-56: when making a viewing list of AI:mich, (any search?) and going past the page_size, it gets the wrong data from the DB for the 'next' entry
|
BUG-56: when making a viewing list of AI:mich, (any search?) and going past the page_size, it gets the wrong data from the DB for the 'next' entry
|
||||||
BUG-60: entries per page (in folders view) ignores pagesize, and this also contributes to BUG-56 I think
|
BUG-60: entries per page (in folders view) ignores pagesize, and this also contributes to BUG-56 I think
|
||||||
BUG-74: search/others? remembers start/offset, and if you reset view (e.g. another search) it doesnt show first page of results
|
BUG-74: search/others? remembers start/offset, and if you reset view (e.g. another search) it doesnt show first page of results
|
||||||
BUG-77: when moving folders out from a parent folder (storage/2020 off-camera-to-oct), it did not delete the empty 2020 off-camera-to-oct folder
|
BUG-77: when moving folders out from a parent folder (storage/2020 off-camera-to-oct), it did not delete the empty 2020 off-camera-to-oct folder
|
||||||
-- something odd happened here, not sure it is a bug, maybe dodgy data at the time in the DB?
|
-- something odd happened here, not sure it is a bug, maybe dodgy data at the time in the DB?
|
||||||
BUG-79: changing size does not post back the OPT change, so doesn't save to prefs (unless you change say how_many after size)
|
BUG-79: changing size does not post back the OPT change, so doesn't save to prefs (unless you change say how_many after size)
|
||||||
|
BUG-80: viewed AI:fikkers, and next, next, etc. got this:
|
||||||
|
ESC[36mpaweb |ESC[0m [2022-01-16 01:19:34,305] ERROR in app: Exception on /viewlist [POST]
|
||||||
|
ESC[36mpaweb |ESC[0m Traceback (most recent call last):
|
||||||
|
ESC[36mpaweb |ESC[0m File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 2070, in wsgi_app
|
||||||
|
ESC[36mpaweb |ESC[0m response = self.full_dispatch_request()
|
||||||
|
ESC[36mpaweb |ESC[0m File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 1515, in full_dispatch_request
|
||||||
|
ESC[36mpaweb |ESC[0m rv = self.handle_user_exception(e)
|
||||||
|
ESC[36mpaweb |ESC[0m File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 1513, in full_dispatch_request
|
||||||
|
ESC[36mpaweb |ESC[0m rv = self.dispatch_request()
|
||||||
|
ESC[36mpaweb |ESC[0m File "/usr/local/lib/python3.8/dist-packages/flask/app.py", line 1499, in dispatch_request
|
||||||
|
ESC[36mpaweb |ESC[0m return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
|
||||||
|
ESC[36mpaweb |ESC[0m File "/usr/local/lib/python3.8/dist-packages/flask_login/utils.py", line 272, in decorated_view
|
||||||
|
ESC[36mpaweb |ESC[0m return func(*args, **kwargs)
|
||||||
|
ESC[36mpaweb |ESC[0m File "/code/files.py", line 494, in viewlist
|
||||||
|
ESC[36mpaweb |ESC[0m entries=GetEntries( OPT )
|
||||||
|
ESC[36mpaweb |ESC[0m File "/code/files.py", line 272, in GetEntries
|
||||||
|
ESC[36mpaweb |ESC[0m for path in OPT.paths:
|
||||||
|
ESC[36mpaweb |ESC[0m TypeError: 'NoneType' object is not iterable
|
||||||
|
|
||||||
|
IT is caused by next'ing past the end of how_many, so its prob. related to BUG-56 above
|
||||||
|
|||||||
9
TODO
9
TODO
@@ -6,9 +6,6 @@
|
|||||||
|
|
||||||
*** Need to double-check scheduled jobs running in PROD (can use new pa_job_manager.log)
|
*** Need to double-check scheduled jobs running in PROD (can use new pa_job_manager.log)
|
||||||
|
|
||||||
* have a user img in rhs of navbar, as drop-down showing logged in user and allowing to view prefs as they are in DB
|
|
||||||
(maybe set them as well, might want to tweak them one day?)
|
|
||||||
|
|
||||||
* only show say last week of jobs, or last 50? and archive the rest into an archived_jobs table
|
* only show say last week of jobs, or last 50? and archive the rest into an archived_jobs table
|
||||||
need scheduled jobs:
|
need scheduled jobs:
|
||||||
- [DONE] force scans of import/storage paths
|
- [DONE] force scans of import/storage paths
|
||||||
@@ -27,11 +24,13 @@
|
|||||||
|
|
||||||
* when hitting back button to a search, it doesnt handle the post, etc.
|
* when hitting back button to a search, it doesnt handle the post, etc.
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
window.history.pushState(null, "", window.location.href);
|
|
||||||
window.onpopstate = function() {
|
window.onpopstate = function() {
|
||||||
window.history.pushState(null, "", window.location.href);
|
# this seems to work, but feels like no protection at all???
|
||||||
|
# (what about back when it goes onto a POST of deleting a file!)
|
||||||
|
window.history.back()
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
-- maybe window.history.replace() is needed on unsafe URLs?
|
||||||
|
|
||||||
* delete folder
|
* delete folder
|
||||||
|
|
||||||
|
|||||||
@@ -204,4 +204,7 @@
|
|||||||
<path fill-rule="evenodd" d="M11.36 14.098c-1.137 0-1.708-.657-1.762-1.278h1.004c.058.223.343.45.773.45.824 0 1.164-.829 1.133-1.856h-.059c-.148.39-.57.742-1.261.742-.91 0-1.72-.613-1.72-1.758 0-1.148.848-1.835 1.973-1.835 1.09 0 2.063.636 2.063 2.687 0 1.867-.723 2.848-2.145 2.848zm.062-2.735c.504 0 .933-.336.933-.972 0-.633-.398-1.008-.94-1.008-.52 0-.927.375-.927 1 0 .64.418.98.934.98z"/>
|
<path fill-rule="evenodd" d="M11.36 14.098c-1.137 0-1.708-.657-1.762-1.278h1.004c.058.223.343.45.773.45.824 0 1.164-.829 1.133-1.856h-.059c-.148.39-.57.742-1.261.742-.91 0-1.72-.613-1.72-1.758 0-1.148.848-1.835 1.973-1.835 1.09 0 2.063.636 2.063 2.687 0 1.867-.723 2.848-2.145 2.848zm.062-2.735c.504 0 .933-.336.933-.972 0-.633-.398-1.008-.94-1.008-.52 0-.927.375-.927 1 0 .64.418.98.934.98z"/>
|
||||||
<path d="M4.5 13.5a.5.5 0 0 1-1 0V3.707L2.354 4.854a.5.5 0 1 1-.708-.708l2-1.999.007-.007a.498.498 0 0 1 .7.006l2 2a.5.5 0 1 1-.707.708L4.5 3.707V13.5z"/>
|
<path d="M4.5 13.5a.5.5 0 0 1-1 0V3.707L2.354 4.854a.5.5 0 1 1-.708-.708l2-1.999.007-.007a.498.498 0 0 1 .7.006l2 2a.5.5 0 1 1-.707.708L4.5 3.707V13.5z"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
<svg id="user" viewBox="0 0 16 16">
|
||||||
|
<path d="M3 14s-1 0-1-1 1-4 6-4 6 3 6 4-1 1-1 1H3zm5-6a3 3 0 1 0 0-6 3 3 0 0 0 0 6z"/>
|
||||||
|
</svg>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 25 KiB |
23
main.py
23
main.py
@@ -14,7 +14,7 @@ from shared import CreateSelect, CreateFoldersSelect, LocationIcon, DB_URL, PROD
|
|||||||
|
|
||||||
# for ldap auth
|
# for ldap auth
|
||||||
from flask_ldap3_login import LDAP3LoginManager
|
from flask_ldap3_login import LDAP3LoginManager
|
||||||
from flask_login import LoginManager, login_user, login_required, UserMixin, current_user
|
from flask_login import LoginManager, login_user, login_required, UserMixin, current_user, logout_user
|
||||||
from flask_ldap3_login.forms import LDAPLoginForm
|
from flask_ldap3_login.forms import LDAPLoginForm
|
||||||
|
|
||||||
|
|
||||||
@@ -73,6 +73,7 @@ app.jinja_env.globals['CreateSelect'] = CreateSelect
|
|||||||
app.jinja_env.globals['CreateFoldersSelect'] = CreateFoldersSelect
|
app.jinja_env.globals['CreateFoldersSelect'] = CreateFoldersSelect
|
||||||
app.jinja_env.globals['LocationIcon'] = LocationIcon
|
app.jinja_env.globals['LocationIcon'] = LocationIcon
|
||||||
app.jinja_env.globals['NEWEST_LOG_LIMIT'] = NEWEST_LOG_LIMIT
|
app.jinja_env.globals['NEWEST_LOG_LIMIT'] = NEWEST_LOG_LIMIT
|
||||||
|
app.jinja_env.globals['current_user'] = current_user
|
||||||
|
|
||||||
|
|
||||||
# Declare a User Loader for Flask-Login.
|
# Declare a User Loader for Flask-Login.
|
||||||
@@ -132,9 +133,29 @@ def login():
|
|||||||
|
|
||||||
return render_template("login.html", form=form)
|
return render_template("login.html", form=form)
|
||||||
|
|
||||||
|
@app.route('/logout')
|
||||||
|
@login_required
|
||||||
|
def logout():
|
||||||
|
logout_user()
|
||||||
|
return redirect('/login')
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if hostname == PROD_HOST:
|
if hostname == PROD_HOST:
|
||||||
app.run(ssl_context=('/etc/letsencrypt/live/pa.depaoli.id.au/cert.pem', '/etc/letsencrypt/live/pa.depaoli.id.au/privkey.pem'), host="0.0.0.0", debug=False)
|
app.run(ssl_context=('/etc/letsencrypt/live/pa.depaoli.id.au/cert.pem', '/etc/letsencrypt/live/pa.depaoli.id.au/privkey.pem'), host="0.0.0.0", debug=False)
|
||||||
else:
|
else:
|
||||||
app.run(host="0.0.0.0", debug=True)
|
app.run(host="0.0.0.0", debug=True)
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# This func creates a new filter in jinja2 to test to hand back the username
|
||||||
|
# from the ldap dn
|
||||||
|
################################################################################
|
||||||
|
@app.template_filter('Username')
|
||||||
|
def _jinja2_filter_parentpath(dn):
|
||||||
|
|
||||||
|
# pull apart a dn (uid=xxx,dn=yyy,etc), and return the xxx
|
||||||
|
username=str(dn)
|
||||||
|
s=username.index('=')
|
||||||
|
s+=1
|
||||||
|
f=username.index(',')
|
||||||
|
return username[s:f]
|
||||||
|
|
||||||
|
|||||||
13
options.py
13
options.py
@@ -1,5 +1,6 @@
|
|||||||
from settings import Settings, SettingsRBPath, SettingsIPath, SettingsSPath
|
from settings import Settings, SettingsRBPath, SettingsIPath, SettingsSPath
|
||||||
from flask_login import current_user
|
from flask import request, render_template, redirect, url_for
|
||||||
|
from flask_login import login_required, current_user
|
||||||
from main import db, app, ma
|
from main import db, app, ma
|
||||||
from shared import PA
|
from shared import PA
|
||||||
|
|
||||||
@@ -145,3 +146,13 @@ class Options(PA):
|
|||||||
|
|
||||||
db.session.add(pref)
|
db.session.add(pref)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
|
|
||||||
|
################################################################################
|
||||||
|
# /prefs -> GET only -> prints out list of all prefs (simple for now)
|
||||||
|
################################################################################
|
||||||
|
@app.route("/prefs", methods=["GET"])
|
||||||
|
@login_required
|
||||||
|
def prefs():
|
||||||
|
prefs = PA_PREF.query.filter( PA_PREF.pa_user_dn==current_user.dn ).all()
|
||||||
|
return render_template("prefs.html", prefs=prefs )
|
||||||
|
|
||||||
|
|||||||
@@ -114,6 +114,15 @@
|
|||||||
<input class="form-control" type="search" placeholder="by file, date (YYYMMDD) or tag" aria-label="Search" name="search_term">
|
<input class="form-control" type="search" placeholder="by file, date (YYYMMDD) or tag" aria-label="Search" name="search_term">
|
||||||
<button class="btn btn-outline-success" type="submit">Search</button>
|
<button class="btn btn-outline-success" type="submit">Search</button>
|
||||||
</form>
|
</form>
|
||||||
|
<div class="nav-item dropdown">
|
||||||
|
<a class="nav-link dropdown-toggle" href="#" id="navbarDropdownMenuLink" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||||
|
<svg width="20" height="20" fill="currentColor"><use xlink:href="{{url_for('internal', filename='icons.svg')}}#user"/></svg>
|
||||||
|
</a>
|
||||||
|
<div class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdownMenuLink">
|
||||||
|
<div><a class="dropdown-item" href="{{url_for('prefs')}}">{{current_user|Username}}</a></div>
|
||||||
|
<div><a class="dropdown-item" href="{{url_for('logout')}}">Logout</a></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div class="navbar-nav">
|
</div class="navbar-nav">
|
||||||
</div class="collapse navbar-collapse">
|
</div class="collapse navbar-collapse">
|
||||||
</div class="container-fluid">
|
</div class="container-fluid">
|
||||||
|
|||||||
Reference in New Issue
Block a user