from flask import Flask, render_template, request, redirect, jsonify, url_for, render_template_string from flask_sqlalchemy import SQLAlchemy from sqlalchemy.exc import SQLAlchemyError from flask_marshmallow import Marshmallow from flask_bootstrap import Bootstrap from wtforms import SubmitField, StringField, HiddenField, SelectField, IntegerField, TextAreaField, validators from flask_wtf import FlaskForm from status import st, Status 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 socket # pylint: disable=no-member ####################################### Flask App globals ####################################### PROD_HOST="pa_web" hostname = socket.gethostname() print( "Running on: {}".format( hostname) ) app = Flask(__name__) ### what is this value? I gather I should change it? app.config['SQLALCHEMY_DATABASE_URI'] = DB_URL app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False 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) ma = Marshmallow(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 ################################### from settings import Settings from files import Entry, GetJM_Message, ClearJM_Message from person import Person from refimg import Refimg from job import Job, GetNumActiveJobs from ai import aistats from path import StoragePathNames ####################################### GLOBALS ####################################### # allow jinja2 to call these python functions directly app.jinja_env.add_extension('jinja2.ext.loopcontrols') app.jinja_env.globals['ClearStatus'] = st.ClearStatus app.jinja_env.globals['GetAlert'] = st.GetAlert app.jinja_env.globals['GetMessage'] = st.GetMessage app.jinja_env.globals['GetNumActiveJobs'] = GetNumActiveJobs app.jinja_env.globals['GetJM_Message'] = GetJM_Message app.jinja_env.globals['ClearJM_Message'] = ClearJM_Message app.jinja_env.globals['CreateSelect'] = CreateSelect app.jinja_env.globals['CreateFoldersSelect'] = CreateFoldersSelect app.jinja_env.globals['LocationIcon'] = LocationIcon 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 @app.route("/", methods=["GET"]) @login_required 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") @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 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) else: app.run(host="0.0.0.0", debug=True)