added python ldap / login pages
This commit is contained in:
@@ -15,7 +15,7 @@ RUN truncate -s0 /tmp/preseed.cfg && \
|
|||||||
apt-get install -y tzdata
|
apt-get install -y tzdata
|
||||||
## cleanup of files from setup
|
## cleanup of files from setup
|
||||||
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
RUN rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||||
RUN apt-get update && apt-get -y install python3-pip python3-psycopg2 libpq-dev gunicorn mediainfo cmake libgl1-mesa-glx libglib2.0-0
|
RUN apt-get update && apt-get -y install python3-pip python3-psycopg2 libpq-dev gunicorn mediainfo cmake libgl1-mesa-glx libglib2.0-0 python3-ldap
|
||||||
COPY requirements.txt requirements.txt
|
COPY requirements.txt requirements.txt
|
||||||
RUN pip3 install -r requirements.txt
|
RUN pip3 install -r requirements.txt
|
||||||
RUN pip3 install --upgrade pillow --user
|
RUN pip3 install --upgrade pillow --user
|
||||||
|
|||||||
3
README
3
README
@@ -13,6 +13,9 @@ pip packages:
|
|||||||
* datetime
|
* datetime
|
||||||
* pytz
|
* pytz
|
||||||
* face_recognition
|
* face_recognition
|
||||||
|
* flask-login
|
||||||
|
* flask_login
|
||||||
|
* flask-ldap3-login
|
||||||
#### dlib (might need to install this before face_recognitioin, but it might not be needed, cmake clearly was)
|
#### dlib (might need to install this before face_recognitioin, but it might not be needed, cmake clearly was)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
2
ai.py
2
ai.py
@@ -8,6 +8,7 @@ from status import st, Status
|
|||||||
from files import Entry, File, FileRefimgLink
|
from files import Entry, File, FileRefimgLink
|
||||||
from person import Person, PersonRefimgLink
|
from person import Person, PersonRefimgLink
|
||||||
from refimg import Refimg
|
from refimg import Refimg
|
||||||
|
from flask_login import login_required, current_user
|
||||||
|
|
||||||
# pylint: disable=no-member
|
# pylint: disable=no-member
|
||||||
|
|
||||||
@@ -15,6 +16,7 @@ from refimg import Refimg
|
|||||||
# /aistats -> placholder for some sort of stats
|
# /aistats -> placholder for some sort of stats
|
||||||
################################################################################
|
################################################################################
|
||||||
@app.route("/aistats", methods=["GET", "POST"])
|
@app.route("/aistats", methods=["GET", "POST"])
|
||||||
|
@login_required
|
||||||
def aistats():
|
def aistats():
|
||||||
tmp=db.session.query(Entry,Person).join(File).join(FileRefimgLink).join(Refimg).join(PersonRefimgLink).join(Person).filter(FileRefimgLink.matched==True).all()
|
tmp=db.session.query(Entry,Person).join(File).join(FileRefimgLink).join(Refimg).join(PersonRefimgLink).join(Person).filter(FileRefimgLink.matched==True).all()
|
||||||
entries=[]
|
entries=[]
|
||||||
|
|||||||
15
files.py
15
files.py
@@ -16,6 +16,7 @@ import numpy
|
|||||||
import cv2
|
import cv2
|
||||||
import time
|
import time
|
||||||
import re
|
import re
|
||||||
|
from flask_login import login_required, current_user
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
# Local Class imports
|
# Local Class imports
|
||||||
@@ -225,6 +226,7 @@ def GetEntriesInFolderView( cwd, prefix, noo, offset, how_many ):
|
|||||||
# /file_list -> show detailed file list of files from import_path(s)
|
# /file_list -> show detailed file list of files from import_path(s)
|
||||||
################################################################################
|
################################################################################
|
||||||
@app.route("/file_list_ip", methods=["GET","POST"])
|
@app.route("/file_list_ip", methods=["GET","POST"])
|
||||||
|
@login_required
|
||||||
def file_list_ip():
|
def file_list_ip():
|
||||||
noo, grouping, how_many, offset, size, folders, cwd, root = ViewingOptions( request )
|
noo, grouping, how_many, offset, size, folders, cwd, root = ViewingOptions( request )
|
||||||
entries=[]
|
entries=[]
|
||||||
@@ -240,6 +242,7 @@ def file_list_ip():
|
|||||||
# /files -> show thumbnail view of files from import_path(s)
|
# /files -> show thumbnail view of files from import_path(s)
|
||||||
################################################################################
|
################################################################################
|
||||||
@app.route("/files_ip", methods=["GET", "POST"])
|
@app.route("/files_ip", methods=["GET", "POST"])
|
||||||
|
@login_required
|
||||||
def files_ip():
|
def files_ip():
|
||||||
|
|
||||||
noo, grouping, how_many, offset, size, folders, cwd, root = ViewingOptions( request )
|
noo, grouping, how_many, offset, size, folders, cwd, root = ViewingOptions( request )
|
||||||
@@ -261,6 +264,7 @@ def files_ip():
|
|||||||
# /files -> show thumbnail view of files from storage_path
|
# /files -> show thumbnail view of files from storage_path
|
||||||
################################################################################
|
################################################################################
|
||||||
@app.route("/files_sp", methods=["GET", "POST"])
|
@app.route("/files_sp", methods=["GET", "POST"])
|
||||||
|
@login_required
|
||||||
def files_sp():
|
def files_sp():
|
||||||
noo, grouping, how_many, offset, size, folders, cwd, root = ViewingOptions( request )
|
noo, grouping, how_many, offset, size, folders, cwd, root = ViewingOptions( request )
|
||||||
entries=[]
|
entries=[]
|
||||||
@@ -282,6 +286,7 @@ def files_sp():
|
|||||||
# /files -> show thumbnail view of files from storage_path
|
# /files -> show thumbnail view of files from storage_path
|
||||||
################################################################################
|
################################################################################
|
||||||
@app.route("/files_rbp", methods=["GET", "POST"])
|
@app.route("/files_rbp", methods=["GET", "POST"])
|
||||||
|
@login_required
|
||||||
def files_rbp():
|
def files_rbp():
|
||||||
noo, grouping, how_many, offset, size, folders, cwd, root = ViewingOptions( request )
|
noo, grouping, how_many, offset, size, folders, cwd, root = ViewingOptions( request )
|
||||||
entries=[]
|
entries=[]
|
||||||
@@ -303,6 +308,7 @@ def files_rbp():
|
|||||||
# /search -> show thumbnail view of files from import_path(s)
|
# /search -> show thumbnail view of files from import_path(s)
|
||||||
################################################################################
|
################################################################################
|
||||||
@app.route("/search", methods=["GET","POST"])
|
@app.route("/search", methods=["GET","POST"])
|
||||||
|
@login_required
|
||||||
def search():
|
def search():
|
||||||
|
|
||||||
noo, grouping, how_many, offset, size, folders, cwd, root = ViewingOptions( request )
|
noo, grouping, how_many, offset, size, folders, cwd, root = ViewingOptions( request )
|
||||||
@@ -321,6 +327,7 @@ def search():
|
|||||||
# /files/scannow -> allows us to force a check for new files
|
# /files/scannow -> allows us to force a check for new files
|
||||||
################################################################################
|
################################################################################
|
||||||
@app.route("/files/scannow", methods=["GET"])
|
@app.route("/files/scannow", methods=["GET"])
|
||||||
|
@login_required
|
||||||
def scannow():
|
def scannow():
|
||||||
job=NewJob("scannow" )
|
job=NewJob("scannow" )
|
||||||
st.SetAlert("success")
|
st.SetAlert("success")
|
||||||
@@ -331,6 +338,7 @@ def scannow():
|
|||||||
# /files/forcescan -> deletes old data in DB, and does a brand new scan
|
# /files/forcescan -> deletes old data in DB, and does a brand new scan
|
||||||
################################################################################
|
################################################################################
|
||||||
@app.route("/files/forcescan", methods=["GET"])
|
@app.route("/files/forcescan", methods=["GET"])
|
||||||
|
@login_required
|
||||||
def forcescan():
|
def forcescan():
|
||||||
job=NewJob("forcescan" )
|
job=NewJob("forcescan" )
|
||||||
st.SetAlert("success")
|
st.SetAlert("success")
|
||||||
@@ -341,6 +349,7 @@ def forcescan():
|
|||||||
# /files/scan_sp -> allows us to force a check for new files
|
# /files/scan_sp -> allows us to force a check for new files
|
||||||
################################################################################
|
################################################################################
|
||||||
@app.route("/files/scan_sp", methods=["GET"])
|
@app.route("/files/scan_sp", methods=["GET"])
|
||||||
|
@login_required
|
||||||
def scan_sp():
|
def scan_sp():
|
||||||
job=NewJob("scan_sp" )
|
job=NewJob("scan_sp" )
|
||||||
st.SetAlert("success")
|
st.SetAlert("success")
|
||||||
@@ -349,6 +358,7 @@ def scan_sp():
|
|||||||
|
|
||||||
|
|
||||||
@app.route("/fix_dups", methods=["POST"])
|
@app.route("/fix_dups", methods=["POST"])
|
||||||
|
@login_required
|
||||||
def fix_dups():
|
def fix_dups():
|
||||||
rows = db.engine.execute( "select e1.id as id1, f1.hash, d1.rel_path as rel_path1, d1.eid as did1, e1.name as fname1, p1.id as path1, p1.type_id as path_type1, e2.id as id2, d2.rel_path as rel_path2, d2.eid as did2, e2.name as fname2, p2.id as path2, p2.type_id as path_type2 from entry e1, file f1, dir d1, entry_dir_link edl1, path_dir_link pdl1, path p1, entry e2, file f2, dir d2, entry_dir_link edl2, path_dir_link pdl2, path p2 where e1.id = f1.eid and e2.id = f2.eid and d1.eid = edl1.dir_eid and edl1.entry_id = e1.id and edl2.dir_eid = d2.eid and edl2.entry_id = e2.id and p1.type_id != (select id from path_type where name = 'Bin') and p1.id = pdl1.path_id and pdl1.dir_eid = d1.eid and p2.type_id != (select id from path_type where name = 'Bin') and p2.id = pdl2.path_id and pdl2.dir_eid = d2.eid and f1.hash = f2.hash and e1.id != e2.id and f1.size_mb = f2.size_mb order by path1, rel_path1, fname1");
|
rows = db.engine.execute( "select e1.id as id1, f1.hash, d1.rel_path as rel_path1, d1.eid as did1, e1.name as fname1, p1.id as path1, p1.type_id as path_type1, e2.id as id2, d2.rel_path as rel_path2, d2.eid as did2, e2.name as fname2, p2.id as path2, p2.type_id as path_type2 from entry e1, file f1, dir d1, entry_dir_link edl1, path_dir_link pdl1, path p1, entry e2, file f2, dir d2, entry_dir_link edl2, path_dir_link pdl2, path p2 where e1.id = f1.eid and e2.id = f2.eid and d1.eid = edl1.dir_eid and edl1.entry_id = e1.id and edl2.dir_eid = d2.eid and edl2.entry_id = e2.id and p1.type_id != (select id from path_type where name = 'Bin') and p1.id = pdl1.path_id and pdl1.dir_eid = d1.eid and p2.type_id != (select id from path_type where name = 'Bin') and p2.id = pdl2.path_id and pdl2.dir_eid = d2.eid and f1.hash = f2.hash and e1.id != e2.id and f1.size_mb = f2.size_mb order by path1, rel_path1, fname1");
|
||||||
|
|
||||||
@@ -374,6 +384,7 @@ def fix_dups():
|
|||||||
return render_template("dups.html", DD=DD, pagesize=pagesize )
|
return render_template("dups.html", DD=DD, pagesize=pagesize )
|
||||||
|
|
||||||
@app.route("/rm_dups", methods=["POST"])
|
@app.route("/rm_dups", methods=["POST"])
|
||||||
|
@login_required
|
||||||
def rm_dups():
|
def rm_dups():
|
||||||
|
|
||||||
jex=[]
|
jex=[]
|
||||||
@@ -398,6 +409,7 @@ def rm_dups():
|
|||||||
return render_template("base.html")
|
return render_template("base.html")
|
||||||
|
|
||||||
@app.route("/restore_files", methods=["POST"])
|
@app.route("/restore_files", methods=["POST"])
|
||||||
|
@login_required
|
||||||
def restore_files():
|
def restore_files():
|
||||||
jex=[]
|
jex=[]
|
||||||
for el in request.form:
|
for el in request.form:
|
||||||
@@ -409,6 +421,7 @@ def restore_files():
|
|||||||
return render_template("base.html")
|
return render_template("base.html")
|
||||||
|
|
||||||
@app.route("/delete_files", methods=["POST"])
|
@app.route("/delete_files", methods=["POST"])
|
||||||
|
@login_required
|
||||||
def delete_files():
|
def delete_files():
|
||||||
jex=[]
|
jex=[]
|
||||||
for el in request.form:
|
for el in request.form:
|
||||||
@@ -420,6 +433,7 @@ def delete_files():
|
|||||||
return render_template("base.html")
|
return render_template("base.html")
|
||||||
|
|
||||||
@app.route("/move_files", methods=["POST"])
|
@app.route("/move_files", methods=["POST"])
|
||||||
|
@login_required
|
||||||
def move_files():
|
def move_files():
|
||||||
jex=[]
|
jex=[]
|
||||||
for el in request.form:
|
for el in request.form:
|
||||||
@@ -435,6 +449,7 @@ def move_files():
|
|||||||
# we create/use symlinks in static/ to reference the images to show
|
# we create/use symlinks in static/ to reference the images to show
|
||||||
################################################################################
|
################################################################################
|
||||||
@app.route("/static/<filename>")
|
@app.route("/static/<filename>")
|
||||||
|
@login_required
|
||||||
def custom_static(filename):
|
def custom_static(filename):
|
||||||
return send_from_directory("static/", filename)
|
return send_from_directory("static/", filename)
|
||||||
|
|
||||||
|
|||||||
5
job.py
5
job.py
@@ -6,9 +6,11 @@ from sqlalchemy import Sequence
|
|||||||
from sqlalchemy.exc import SQLAlchemyError
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
from status import st, Status
|
from status import st, Status
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
from flask_login import login_required, current_user
|
||||||
import pytz
|
import pytz
|
||||||
import socket
|
import socket
|
||||||
from shared import PA_JOB_MANAGER_HOST, PA_JOB_MANAGER_PORT
|
from shared import PA_JOB_MANAGER_HOST, PA_JOB_MANAGER_PORT
|
||||||
|
from flask_login import login_required, current_user
|
||||||
|
|
||||||
# pylint: disable=no-member
|
# pylint: disable=no-member
|
||||||
|
|
||||||
@@ -93,6 +95,7 @@ def NewJob(name, num_files="0", wait_for=None, jex=None ):
|
|||||||
# /jobs -> show current settings
|
# /jobs -> show current settings
|
||||||
################################################################################
|
################################################################################
|
||||||
@app.route("/jobs", methods=["GET"])
|
@app.route("/jobs", methods=["GET"])
|
||||||
|
@login_required
|
||||||
def jobs():
|
def jobs():
|
||||||
page_title='Job list'
|
page_title='Job list'
|
||||||
jobs = Job.query.order_by(Job.id.desc()).all()
|
jobs = Job.query.order_by(Job.id.desc()).all()
|
||||||
@@ -103,6 +106,7 @@ def jobs():
|
|||||||
# /job/<id> -> GET -> shows status/history of jobs
|
# /job/<id> -> GET -> shows status/history of jobs
|
||||||
################################################################################
|
################################################################################
|
||||||
@app.route("/job/<id>", methods=["GET"])
|
@app.route("/job/<id>", methods=["GET"])
|
||||||
|
@login_required
|
||||||
def joblog(id):
|
def joblog(id):
|
||||||
page_title='Show Job Details'
|
page_title='Show Job Details'
|
||||||
joblog = Job.query.get(id)
|
joblog = Job.query.get(id)
|
||||||
@@ -118,6 +122,7 @@ def joblog(id):
|
|||||||
# /job/<id> -> GET -> shows status/history of jobs
|
# /job/<id> -> GET -> shows status/history of jobs
|
||||||
################################################################################
|
################################################################################
|
||||||
@app.route("/wakeup", methods=["GET"])
|
@app.route("/wakeup", methods=["GET"])
|
||||||
|
@login_required
|
||||||
def wakeup():
|
def wakeup():
|
||||||
WakePAJobManager()
|
WakePAJobManager()
|
||||||
return render_template("base.html")
|
return render_template("base.html")
|
||||||
|
|||||||
89
main.py
89
main.py
@@ -1,4 +1,4 @@
|
|||||||
from flask import Flask, render_template, request, redirect, jsonify
|
from flask import Flask, render_template, request, redirect, jsonify, url_for, render_template_string
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
from sqlalchemy.exc import SQLAlchemyError
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
from flask_marshmallow import Marshmallow
|
from flask_marshmallow import Marshmallow
|
||||||
@@ -7,6 +7,13 @@ from wtforms import SubmitField, StringField, HiddenField, SelectField, IntegerF
|
|||||||
from flask_wtf import FlaskForm
|
from flask_wtf import FlaskForm
|
||||||
from status import st, Status
|
from status import st, Status
|
||||||
from shared import CreateSelect, CreateFoldersSelect, LocationIcon, DB_URL
|
from shared import CreateSelect, CreateFoldersSelect, LocationIcon, DB_URL
|
||||||
|
from flask_login import login_required, current_user
|
||||||
|
|
||||||
|
|
||||||
|
# for ldap auth
|
||||||
|
from flask_ldap3_login import LDAP3LoginManager
|
||||||
|
from flask_login import LoginManager, login_user, UserMixin, current_user
|
||||||
|
from flask_ldap3_login.forms import LDAPLoginForm
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
@@ -23,9 +30,30 @@ app = Flask(__name__)
|
|||||||
app.config['SQLALCHEMY_DATABASE_URI'] = DB_URL
|
app.config['SQLALCHEMY_DATABASE_URI'] = DB_URL
|
||||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||||
app.config.from_mapping( SECRET_KEY=b'\xd6\x04\xbdj\xfe\xed$c\x1e@\xad\x0f\x13,@G')
|
app.config.from_mapping( SECRET_KEY=b'\xd6\x04\xbdj\xfe\xed$c\x1e@\xad\x0f\x13,@G')
|
||||||
|
|
||||||
|
# ldap config vars: (the last one is required, or python ldap freaks out)
|
||||||
|
app.config['LDAP_HOST'] = 'mara.ddp.net'
|
||||||
|
app.config['LDAP_BASE_DN'] = 'dc=depaoli,dc=id,dc=au'
|
||||||
|
app.config['LDAP_USER_DN'] = 'ou=users'
|
||||||
|
app.config['LDAP_GROUP_DN'] = 'ou=groups'
|
||||||
|
app.config['LDAP_USER_RDN_ATTR'] = 'cn'
|
||||||
|
app.config['LDAP_USER_LOGIN_ATTR'] = 'uid'
|
||||||
|
app.config['LDAP_BIND_USER_DN'] = None
|
||||||
|
app.config['LDAP_BIND_USER_PASSWORD'] = None
|
||||||
|
app.config['LDAP_GROUP_OBJECT_FILTER'] = '(objectclass=posixGroup)'
|
||||||
|
|
||||||
db = SQLAlchemy(app)
|
db = SQLAlchemy(app)
|
||||||
ma = Marshmallow(app)
|
ma = Marshmallow(app)
|
||||||
Bootstrap(app)
|
Bootstrap(app)
|
||||||
|
login_manager = LoginManager(app) # Setup a Flask-Login Manager
|
||||||
|
ldap_manager = LDAP3LoginManager(app) # Setup a LDAP3 Login Manager.
|
||||||
|
login_manager.login_view = "login" # default login route, failed with url_for, so hard-coded
|
||||||
|
|
||||||
|
# Create a dictionary to store the users in when they authenticate
|
||||||
|
# This example stores users in memory.
|
||||||
|
users = {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
################################# Now, import non-book classes ###################################
|
################################# Now, import non-book classes ###################################
|
||||||
from settings import Settings
|
from settings import Settings
|
||||||
@@ -50,11 +78,70 @@ app.jinja_env.globals['CreateFoldersSelect'] = CreateFoldersSelect
|
|||||||
app.jinja_env.globals['LocationIcon'] = LocationIcon
|
app.jinja_env.globals['LocationIcon'] = LocationIcon
|
||||||
app.jinja_env.globals['StoragePathNames'] = StoragePathNames
|
app.jinja_env.globals['StoragePathNames'] = StoragePathNames
|
||||||
|
|
||||||
|
|
||||||
|
# Declare an Object Model for the user, and make it comply with the
|
||||||
|
# flask-login UserMixin mixin.
|
||||||
|
class User(UserMixin):
|
||||||
|
def __init__(self, dn, username, data):
|
||||||
|
self.dn = dn
|
||||||
|
self.username = username
|
||||||
|
self.data = data
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return self.dn
|
||||||
|
|
||||||
|
def get_id(self):
|
||||||
|
return self.dn
|
||||||
|
|
||||||
|
# Declare a User Loader for Flask-Login.
|
||||||
|
# Simply returns the User if it exists in our 'database', otherwise
|
||||||
|
# returns None.
|
||||||
|
@login_manager.user_loader
|
||||||
|
def load_user(id):
|
||||||
|
if id in users:
|
||||||
|
return users[id]
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Declare The User Saver for Flask-Ldap3-Login
|
||||||
|
# This method is called whenever a LDAPLoginForm() successfully validates.
|
||||||
|
# Here you have to save the user, and return it so it can be used in the
|
||||||
|
# login controller.
|
||||||
|
@ldap_manager.save_user
|
||||||
|
def save_user(dn, username, data, memberships):
|
||||||
|
user = User(dn, username, data)
|
||||||
|
users[dn] = user
|
||||||
|
return user
|
||||||
|
|
||||||
# default page, just the navbar
|
# default page, just the navbar
|
||||||
@app.route("/", methods=["GET"])
|
@app.route("/", methods=["GET"])
|
||||||
|
@login_required
|
||||||
def main_page():
|
def main_page():
|
||||||
|
# Redirect users who are not logged in.
|
||||||
|
if not current_user or current_user.is_anonymous:
|
||||||
|
return redirect(url_for('login'))
|
||||||
|
|
||||||
return render_template("base.html")
|
return render_template("base.html")
|
||||||
|
|
||||||
|
@app.route('/login', methods=['GET', 'POST'])
|
||||||
|
def login():
|
||||||
|
# Instantiate a LDAPLoginForm which has a validator to check if the user
|
||||||
|
# exists in LDAP.
|
||||||
|
form = LDAPLoginForm()
|
||||||
|
form.submit.label.text="Login"
|
||||||
|
|
||||||
|
if form.validate_on_submit():
|
||||||
|
# Successfully logged in, We can now access the saved user object
|
||||||
|
# via form.user.
|
||||||
|
login_user(form.user, remember=True) # Tell flask-login to log them in.
|
||||||
|
next = request.args.get("next")
|
||||||
|
if next:
|
||||||
|
return redirect(next) # Send them back where they came from
|
||||||
|
else:
|
||||||
|
return redirect('/')
|
||||||
|
|
||||||
|
return render_template("login.html", form=form)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
if hostname == PROD_HOST:
|
if hostname == PROD_HOST:
|
||||||
app.run(ssl_context=('/etc/letsencrypt/live/book.depaoli.id.au/cert.pem', '/etc/letsencrypt/live/book.depaoli.id.au/privkey.pem'), host="0.0.0.0", debug=False)
|
app.run(ssl_context=('/etc/letsencrypt/live/book.depaoli.id.au/cert.pem', '/etc/letsencrypt/live/book.depaoli.id.au/privkey.pem'), host="0.0.0.0", debug=False)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from sqlalchemy import Sequence
|
|||||||
from sqlalchemy.exc import SQLAlchemyError
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
from status import st, Status
|
from status import st, Status
|
||||||
from refimg import Refimg
|
from refimg import Refimg
|
||||||
|
from flask_login import login_required, current_user
|
||||||
|
|
||||||
# pylint: disable=no-member
|
# pylint: disable=no-member
|
||||||
|
|
||||||
@@ -56,6 +57,7 @@ class PersonForm(FlaskForm):
|
|||||||
# /persons -> GET only -> prints out list of all persons
|
# /persons -> GET only -> prints out list of all persons
|
||||||
################################################################################
|
################################################################################
|
||||||
@app.route("/persons", methods=["GET"])
|
@app.route("/persons", methods=["GET"])
|
||||||
|
@login_required
|
||||||
def persons():
|
def persons():
|
||||||
persons = Person.query.all()
|
persons = Person.query.all()
|
||||||
return render_template("persons.html", persons=persons)
|
return render_template("persons.html", persons=persons)
|
||||||
@@ -65,6 +67,7 @@ def persons():
|
|||||||
# /person -> GET/POST -> creates a new person type and when created, takes you back to /persons
|
# /person -> GET/POST -> creates a new person type and when created, takes you back to /persons
|
||||||
################################################################################
|
################################################################################
|
||||||
@app.route("/person", methods=["GET", "POST"])
|
@app.route("/person", methods=["GET", "POST"])
|
||||||
|
@login_required
|
||||||
def new_person():
|
def new_person():
|
||||||
form = PersonForm(request.form)
|
form = PersonForm(request.form)
|
||||||
page_title='Create new Person'
|
page_title='Create new Person'
|
||||||
@@ -90,6 +93,7 @@ def new_person():
|
|||||||
# person
|
# person
|
||||||
################################################################################
|
################################################################################
|
||||||
@app.route("/person/<id>", methods=["GET", "POST"])
|
@app.route("/person/<id>", methods=["GET", "POST"])
|
||||||
|
@login_required
|
||||||
def person(id):
|
def person(id):
|
||||||
form = PersonForm(request.form)
|
form = PersonForm(request.form)
|
||||||
page_title='Edit Person'
|
page_title='Edit Person'
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ from sqlalchemy import Sequence
|
|||||||
from sqlalchemy.exc import SQLAlchemyError
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
from status import st, Status
|
from status import st, Status
|
||||||
import os
|
import os
|
||||||
|
from flask_login import login_required, current_user
|
||||||
|
|
||||||
# pylint: disable=no-member
|
# pylint: disable=no-member
|
||||||
|
|
||||||
@@ -51,6 +52,7 @@ class RefimgForm(FlaskForm):
|
|||||||
# /refimgs -> GET only -> prints out list of all refimgs
|
# /refimgs -> GET only -> prints out list of all refimgs
|
||||||
################################################################################
|
################################################################################
|
||||||
@app.route("/refimgs", methods=["GET"])
|
@app.route("/refimgs", methods=["GET"])
|
||||||
|
@login_required
|
||||||
def refimgs():
|
def refimgs():
|
||||||
refimgs = Refimg.query.all()
|
refimgs = Refimg.query.all()
|
||||||
return render_template("refimgs.html", refimgs=refimgs)
|
return render_template("refimgs.html", refimgs=refimgs)
|
||||||
@@ -59,6 +61,7 @@ def refimgs():
|
|||||||
# /refimg -> GET/POST -> creates a new refimg type and when created, takes you back to /refimgs
|
# /refimg -> GET/POST -> creates a new refimg type and when created, takes you back to /refimgs
|
||||||
################################################################################
|
################################################################################
|
||||||
@app.route("/refimg", methods=["GET", "POST"])
|
@app.route("/refimg", methods=["GET", "POST"])
|
||||||
|
@login_required
|
||||||
def new_refimg():
|
def new_refimg():
|
||||||
form = RefimgForm(request.form)
|
form = RefimgForm(request.form)
|
||||||
page_title='Create new Reference Image'
|
page_title='Create new Reference Image'
|
||||||
@@ -88,6 +91,7 @@ def new_refimg():
|
|||||||
# refimg
|
# refimg
|
||||||
################################################################################
|
################################################################################
|
||||||
@app.route("/refimg/<id>", methods=["GET", "POST"])
|
@app.route("/refimg/<id>", methods=["GET", "POST"])
|
||||||
|
@login_required
|
||||||
def refimg(id):
|
def refimg(id):
|
||||||
form = RefimgForm(request.form)
|
form = RefimgForm(request.form)
|
||||||
page_title='Edit Reference Image'
|
page_title='Edit Reference Image'
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
flask
|
flask
|
||||||
|
flask_login
|
||||||
|
flask-ldap3-login
|
||||||
sqlalchemy
|
sqlalchemy
|
||||||
flask-sqlalchemy
|
flask-sqlalchemy
|
||||||
SQLAlchemy-serializer
|
SQLAlchemy-serializer
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ from main import db, app, ma
|
|||||||
from sqlalchemy import Sequence
|
from sqlalchemy import Sequence
|
||||||
from sqlalchemy.exc import SQLAlchemyError
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
from status import st, Status
|
from status import st, Status
|
||||||
|
from flask_login import login_required, current_user
|
||||||
|
|
||||||
# pylint: disable=no-member
|
# pylint: disable=no-member
|
||||||
|
|
||||||
@@ -45,6 +46,7 @@ class SettingsForm(FlaskForm):
|
|||||||
# /settings -> show current settings
|
# /settings -> show current settings
|
||||||
################################################################################
|
################################################################################
|
||||||
@app.route("/settings", methods=["GET", "POST"])
|
@app.route("/settings", methods=["GET", "POST"])
|
||||||
|
@login_required
|
||||||
def settings():
|
def settings():
|
||||||
form = SettingsForm(request.form)
|
form = SettingsForm(request.form)
|
||||||
page_title='Settings'
|
page_title='Settings'
|
||||||
|
|||||||
@@ -8,9 +8,9 @@
|
|||||||
|
|
||||||
{% for job in jobs %}
|
{% for job in jobs %}
|
||||||
{% if job.state == "Failed" %}
|
{% if job.state == "Failed" %}
|
||||||
row='<tr><td class="bg-danger"><a class="text-white" href="{{url_for('joblog', id=job.id)}}">Job #{{job.id}} - {{job.name}}</a>'
|
row='<tr><td class="table-danger"><a href="{{url_for('joblog', id=job.id)}}">Job #{{job.id}} - {{job.name}}</a>'
|
||||||
{% elif job.state == "Withdrawn" %}
|
{% elif job.state == "Withdrawn" %}
|
||||||
row='<tr><td class="bg-secondary"><a class="text-white" href="{{url_for('joblog', id=job.id)}}">Job #{{job.id}} - {{job.name}}</a>'
|
row='<tr><td class="table-secondary"><i><a href="{{url_for('joblog', id=job.id)}}">Job #{{job.id}} - {{job.name}}</a>'
|
||||||
{% else %}
|
{% else %}
|
||||||
row='<tr><td><a href="{{url_for('joblog', id=job.id)}}">Job #{{job.id}} - {{job.name}}</a>'
|
row='<tr><td><a href="{{url_for('joblog', id=job.id)}}">Job #{{job.id}} - {{job.name}}</a>'
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@@ -21,7 +21,12 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
{% endif %}
|
{% endif %}
|
||||||
row+= '</td><td>{{job.start_time}}</td><td>'
|
|
||||||
|
{% if job.state == "Withdrawn" %}
|
||||||
|
row+= '</td><td>{{job.start_time}}</i></td><td>'
|
||||||
|
{% else %}
|
||||||
|
row+= '</td><td>{{job.start_time}}</td><td>'
|
||||||
|
{% endif %}
|
||||||
{% if job.pa_job_state != "Completed" %}
|
{% if job.pa_job_state != "Completed" %}
|
||||||
{% if job.num_files and job.num_files > 0 %}
|
{% if job.num_files and job.num_files > 0 %}
|
||||||
{% set prog=(job.current_file_num/job.num_files*100)|round|int %}
|
{% set prog=(job.current_file_num/job.num_files*100)|round|int %}
|
||||||
|
|||||||
Reference in New Issue
Block a user