cleanup
This commit is contained in:
parent
5bfa305c41
commit
ea107a28dd
|
@ -1,26 +1,25 @@
|
||||||
""" Server-package
|
""" Server-package
|
||||||
|
|
||||||
Initialize app, cors, database and bcrypt (for passwordhashing) and added it to the application.
|
Initialize app, CORS, database and add it to the application.
|
||||||
Initialize also a singelton for the AccesTokenControler and start the Thread.
|
Initialize also a singleton for the AccessTokenController and start the Thread.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from pathlib import Path
|
import yaml
|
||||||
_modpath = Path(__file__).parent
|
|
||||||
|
|
||||||
from flask import Flask
|
|
||||||
from flask_cors import CORS
|
|
||||||
import pkg_resources, yaml
|
|
||||||
|
|
||||||
from logging.config import dictConfig
|
|
||||||
|
|
||||||
with (_modpath/'logging.yml').open(mode='rb') as file:
|
|
||||||
config = yaml.safe_load(file.read())
|
|
||||||
dictConfig(config)
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
|
import pkg_resources
|
||||||
|
from flask import Flask
|
||||||
|
from pathlib import Path
|
||||||
|
from flask_cors import CORS
|
||||||
|
from logging.config import dictConfig
|
||||||
from werkzeug.local import LocalProxy
|
from werkzeug.local import LocalProxy
|
||||||
|
|
||||||
|
_module_path = Path(__file__).parent
|
||||||
logger = LocalProxy(lambda: logging.getLogger(__name__))
|
logger = LocalProxy(lambda: logging.getLogger(__name__))
|
||||||
|
|
||||||
|
with (_module_path / 'logging.yml').open(mode='rb') as file:
|
||||||
|
config = yaml.safe_load(file.read())
|
||||||
|
logging.config.dictConfig(config)
|
||||||
|
|
||||||
|
|
||||||
def create_app():
|
def create_app():
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
@ -33,14 +32,15 @@ def create_app():
|
||||||
db.init_app(app)
|
db.init_app(app)
|
||||||
|
|
||||||
for entry_point in pkg_resources.iter_entry_points('flaschengeist.auth'):
|
for entry_point in pkg_resources.iter_entry_points('flaschengeist.auth'):
|
||||||
logger.debug('Found authentification plugin: %s', entry_point.name)
|
logger.debug('Found authentication plugin: %s', entry_point.name)
|
||||||
if entry_point.name == config['FLASCHENGEIST']['AUTH']:
|
if entry_point.name == config['FLASCHENGEIST']['AUTH']:
|
||||||
app.config['FG_AUTH_BACKEND'] = entry_point.load()()
|
app.config['FG_AUTH_BACKEND'] = entry_point.load()()
|
||||||
app.config['FG_AUTH_BACKEND'].configure(config[entry_point.name] if config.has_section(entry_point.name) else {})
|
app.config['FG_AUTH_BACKEND'].configure(
|
||||||
logger.info('Loaded authentification plugin > %s <', entry_point.name)
|
config[entry_point.name] if config.has_section(entry_point.name) else {})
|
||||||
|
logger.info('Loaded authentication plugin > %s <', entry_point.name)
|
||||||
break
|
break
|
||||||
if not app.config['FG_AUTH_BACKEND']:
|
if not app.config['FG_AUTH_BACKEND']:
|
||||||
logger.error('No authentification plugin configured or authentification plugin not found')
|
logger.error('No authentication plugin configured or authentication plugin not found')
|
||||||
|
|
||||||
logger.info('Search for plugins')
|
logger.info('Search for plugins')
|
||||||
for entry_point in pkg_resources.iter_entry_points('flaschengeist.plugin'):
|
for entry_point in pkg_resources.iter_entry_points('flaschengeist.plugin'):
|
||||||
|
@ -50,9 +50,3 @@ def create_app():
|
||||||
app.register_blueprint(entry_point.load()())
|
app.register_blueprint(entry_point.load()())
|
||||||
|
|
||||||
return app
|
return app
|
||||||
#app.register_blueprint(baruser)
|
|
||||||
#app.register_blueprint(finanzer)
|
|
||||||
#app.register_blueprint(user)
|
|
||||||
#app.register_blueprint(vorstand)
|
|
||||||
#app.register_blueprint(gastrouser)
|
|
||||||
#app.register_blueprint(registration)
|
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
[FLASCHENGEIST]
|
[FLASCHENGEIST]
|
||||||
# Set lifetime of session (idle time until you get logged out)
|
# Select authentication provider (builtin: auth_plain, auth_ldap)
|
||||||
AccessTokenLifetime = 1800
|
|
||||||
# Select authentification provider
|
|
||||||
AUTH = auth_plain
|
AUTH = auth_plain
|
||||||
|
# Enable if you run flaschengeist behind a proxy, e.g. nginx + gunicorn
|
||||||
|
# PROXY = false
|
||||||
|
# Set root path, prefixes all routes
|
||||||
|
# ROOT = /
|
||||||
|
|
||||||
[DATABASE]
|
[DATABASE]
|
||||||
USER =
|
USER =
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
class Auth():
|
class Auth:
|
||||||
def configure(self, config):
|
def configure(self, config):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -7,14 +7,14 @@ class Auth():
|
||||||
user User class containing at least the uid
|
user User class containing at least the uid
|
||||||
pw given password
|
pw given password
|
||||||
|
|
||||||
HAS TO BE IMPLEMENTED!
|
MUST BE IMPLEMENTED!
|
||||||
|
|
||||||
should return False if not found or invalid credentials
|
should return False if not found or invalid credentials
|
||||||
should return True if success
|
should return True if success
|
||||||
"""
|
"""
|
||||||
return False
|
raise NotImplementedError
|
||||||
|
|
||||||
def updateUser(self, user):
|
def update_user(self, user):
|
||||||
"""
|
"""
|
||||||
user User class
|
user User class
|
||||||
|
|
||||||
|
@ -22,11 +22,10 @@ class Auth():
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def modifyUser(self, user):
|
def modify_user(self, user):
|
||||||
"""
|
"""
|
||||||
user User class
|
user User class
|
||||||
|
|
||||||
If backend is using (writeable) external data, then update the external database with the user provided.
|
If backend is using (writeable) external data, then update the external database with the user provided.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ def _login():
|
||||||
try:
|
try:
|
||||||
logger.debug("search {{ {} }} in database".format(username))
|
logger.debug("search {{ {} }} in database".format(username))
|
||||||
main_controller = mc.MainController()
|
main_controller = mc.MainController()
|
||||||
user = main_controller.loginUser(username, password)
|
user = main_controller.login_user(username, password)
|
||||||
logger.debug("user is {{ {} }}".format(user))
|
logger.debug("user is {{ {} }}".format(user))
|
||||||
token = access_controller.create(user, user_agent=request.user_agent)
|
token = access_controller.create(user, user_agent=request.user_agent)
|
||||||
logger.debug("access token is {{ {} }}".format(token))
|
logger.debug("access token is {{ {} }}".format(token))
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
from ldap3.core.exceptions import LDAPException
|
||||||
|
|
||||||
import flaschengeist.modules as modules
|
import flaschengeist.modules as modules
|
||||||
from flaschengeist import logger
|
from flaschengeist import logger
|
||||||
from flask import current_app as app
|
from flask import current_app as app
|
||||||
|
@ -39,11 +41,11 @@ class AuthLDAP(modules.Auth):
|
||||||
try:
|
try:
|
||||||
r = self.ldap.authenticate(user.uid, password, 'uid', self.dn)
|
r = self.ldap.authenticate(user.uid, password, 'uid', self.dn)
|
||||||
return r == True
|
return r == True
|
||||||
except Exception as err:
|
except LDAPException as err:
|
||||||
logger.warning("Exception while login into ldap", exc_info=True)
|
logger.warning("Exception while login into ldap", exc_info=True)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def modifyUser(self, user):
|
def modify_user(self, user):
|
||||||
try:
|
try:
|
||||||
ldap_conn = self.ldap.bind(user.uid, password)
|
ldap_conn = self.ldap.bind(user.uid, password)
|
||||||
if attributes:
|
if attributes:
|
||||||
|
@ -66,7 +68,7 @@ class AuthLDAP(modules.Auth):
|
||||||
"username exists on ldap, rechange username on database", exc_info=True)
|
"username exists on ldap, rechange username on database", exc_info=True)
|
||||||
db.changeUsername(user, user.uid)
|
db.changeUsername(user, user.uid)
|
||||||
raise Exception(err)
|
raise Exception(err)
|
||||||
except LDAPExcetpion as err:
|
except LDAPException as err:
|
||||||
if 'username' in attributes:
|
if 'username' in attributes:
|
||||||
db.changeUsername(user, user.uid)
|
db.changeUsername(user, user.uid)
|
||||||
raise Exception(err)
|
raise Exception(err)
|
||||||
|
@ -105,7 +107,7 @@ class AuthLDAP(modules.Auth):
|
||||||
debug.warning("exception in modify user data from ldap", exc_info=True)
|
debug.warning("exception in modify user data from ldap", exc_info=True)
|
||||||
raise LDAPExcetpion("Something went wrong in LDAP: {}".format(err))
|
raise LDAPExcetpion("Something went wrong in LDAP: {}".format(err))
|
||||||
|
|
||||||
def updateUser(self, user):
|
def update_user(self, user):
|
||||||
self.ldap.connection.search('ou=user,{}'.format(self.dn), '(uid={})'.format(user.uid), SUBTREE,
|
self.ldap.connection.search('ou=user,{}'.format(self.dn), '(uid={})'.format(user.uid), SUBTREE,
|
||||||
attributes=['uid', 'givenName', 'sn', 'mail'])
|
attributes=['uid', 'givenName', 'sn', 'mail'])
|
||||||
r = self.ldap.connection.response[0]['attributes']
|
r = self.ldap.connection.response[0]['attributes']
|
||||||
|
|
|
@ -5,23 +5,25 @@ import os
|
||||||
import flaschengeist.modules as modules
|
import flaschengeist.modules as modules
|
||||||
|
|
||||||
|
|
||||||
|
def _hash_password(password):
|
||||||
|
salt = hashlib.sha256(os.urandom(60)).hexdigest().encode('ascii')
|
||||||
|
pass_hash = hashlib.pbkdf2_hmac('sha3-512', password.encode('utf-8'), salt, 100000)
|
||||||
|
pass_hash = binascii.hexlify(pass_hash)
|
||||||
|
return (salt + pass_hash).decode('ascii')
|
||||||
|
|
||||||
|
|
||||||
|
def _verify_password(stored_password, provided_password):
|
||||||
|
salt = stored_password[:64]
|
||||||
|
stored_password = stored_password[64:]
|
||||||
|
pass_hash = hashlib.pbkdf2_hmac('sha3-512', provided_password.encode('utf-8'), salt.encode('ascii'), 100000)
|
||||||
|
pass_hash = binascii.hexlify(pass_hash).decode('ascii')
|
||||||
|
return pass_hash == stored_password
|
||||||
|
|
||||||
|
|
||||||
class AuthPlain(modules.Auth):
|
class AuthPlain(modules.Auth):
|
||||||
def login(self, user, password):
|
def login(self, user, password):
|
||||||
if not user:
|
if not user:
|
||||||
return False
|
return False
|
||||||
if 'password' in user.attributes:
|
if 'password' in user.attributes:
|
||||||
return self._verify_password(user.attributes['password'].value, password)
|
return _verify_password(user.attributes['password'].value, password)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _hash_password(self, password):
|
|
||||||
salt = hashlib.sha256(os.urandom(60)).hexdigest().encode('ascii')
|
|
||||||
pass_hash = hashlib.pbkdf2_hmac('sha3-512', password.encode('utf-8'), salt, 100000)
|
|
||||||
pass_hash = binascii.hexlify(pass_hash)
|
|
||||||
return (salt + pass_hash).decode('ascii')
|
|
||||||
|
|
||||||
def _verify_password(self, stored_password, provided_password):
|
|
||||||
salt = stored_password[:64]
|
|
||||||
stored_password = stored_password[64:]
|
|
||||||
pass_hash = hashlib.pbkdf2_hmac('sha3-512', provided_password.encode('utf-8'), salt.encode('ascii'), 100000)
|
|
||||||
pass_hash = binascii.hexlify(pass_hash).decode('ascii')
|
|
||||||
return pass_hash == stored_password
|
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
import configparser
|
|
||||||
import os
|
import os
|
||||||
|
import configparser
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from .. import _modpath, logger
|
from werkzeug.middleware.proxy_fix import ProxyFix
|
||||||
|
from .. import _module_path, logger
|
||||||
|
|
||||||
default = {
|
default = {
|
||||||
'FLASCHENGEIST': {
|
|
||||||
'AccessTokenLifeTime': 1800
|
|
||||||
},
|
|
||||||
'MAIL': {
|
'MAIL': {
|
||||||
'CRYPT': 'SSL/STARTLS'
|
'CRYPT': 'SSL/STARTLS'
|
||||||
}
|
}
|
||||||
|
@ -14,7 +12,7 @@ default = {
|
||||||
|
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
config.read_dict(default)
|
config.read_dict(default)
|
||||||
paths = [_modpath, Path.home()/".config"]
|
paths = [_module_path, Path.home()/".config"]
|
||||||
if 'FLASCHENGEIST_CONF' in os.environ:
|
if 'FLASCHENGEIST_CONF' in os.environ:
|
||||||
paths.append(Path(os.environ.get("FLASCHENGEIST_CONF")))
|
paths.append(Path(os.environ.get("FLASCHENGEIST_CONF")))
|
||||||
for loc in paths:
|
for loc in paths:
|
||||||
|
@ -23,7 +21,8 @@ for loc in paths:
|
||||||
config.read_file(source)
|
config.read_file(source)
|
||||||
except IOError:
|
except IOError:
|
||||||
pass
|
pass
|
||||||
# Always enable this buildin plugins!
|
|
||||||
|
# Always enable this builtin plugins!
|
||||||
config.read_dict({
|
config.read_dict({
|
||||||
'auth': {
|
'auth': {
|
||||||
'enabled': True
|
'enabled': True
|
||||||
|
@ -43,120 +42,8 @@ def configure_app(app):
|
||||||
database=config['DATABASE']['database']
|
database=config['DATABASE']['database']
|
||||||
)
|
)
|
||||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
|
||||||
|
|
||||||
#class ConifgParser():
|
if config.has_option("FLASCHENGEIST", "ROOT"):
|
||||||
# def __init__(self, file='config.yml'):
|
app.config["APPLICATION_ROOT"] = config["FLASCHENGEIST"]["ROOT"]
|
||||||
# self.file = file
|
if config.getboolean("FLASCHENGEIST", "PROXY", fallback=False):
|
||||||
# with open(file, 'r') as f:
|
app.wsgi_app = ProxyFix(app.wsgi_app, x_proto=1, x_host=1)
|
||||||
# self.config = yaml.safe_load(f)
|
|
||||||
#
|
|
||||||
# if 'Database' not in self.config:
|
|
||||||
# self.__error__(
|
|
||||||
# 'Wrong Configuration for Database. You should configure databaseconfig with "URL", "user", "passwd", "database"')
|
|
||||||
# if 'URL' not in self.config['Database'] or 'user' not in self.config['Database'] or 'passwd' not in self.config['Database'] or 'database' not in self.config['Database']:
|
|
||||||
# self.__error__(
|
|
||||||
# 'Wrong Configuration for Database. You should configure databaseconfig with "URL", "user", "passwd", "database"')
|
|
||||||
#
|
|
||||||
# self.db = self.config['Database']
|
|
||||||
# logger.debug("Set Databaseconfig: {}".format(self.db))
|
|
||||||
#
|
|
||||||
# if 'LDAP' not in self.config:
|
|
||||||
# self.__error__(
|
|
||||||
# 'Wrong Configuration for LDAP. You should configure ldapconfig with "URL" and "BIND_DN"')
|
|
||||||
# if 'URL' not in self.config['LDAP'] or 'DN' not in self.config['LDAP']:
|
|
||||||
# self.__error__(
|
|
||||||
# 'Wrong Configuration for LDAP. You should configure ldapconfig with "URL" and "BIND_DN"')
|
|
||||||
# if 'PORT' not in self.config['LDAP']:
|
|
||||||
# logger.info(
|
|
||||||
# 'No Config for port in LDAP found. Set it to default: {}'.format(389))
|
|
||||||
# self.config['LDAP']['PORT'] = 389
|
|
||||||
# if 'ADMIN_DN' not in self.config['LDAP']:
|
|
||||||
# logger.info(
|
|
||||||
# 'No Config for ADMIN_DN in LDAP found. Set it to default {}. (Maybe Password reset not working)'.format(None)
|
|
||||||
# )
|
|
||||||
# self.config['LDAP']['ADMIN_DN'] = None
|
|
||||||
# if 'ADMIN_SECRET' not in self.config['LDAP']:
|
|
||||||
# logger.info(
|
|
||||||
# 'No Config for ADMIN_SECRET in LDAP found. Set it to default {}. (Maybe Password reset not working)'.format(None)
|
|
||||||
# )
|
|
||||||
# self.config['LDAP']['ADMIN_SECRET'] = None
|
|
||||||
# if 'USER_DN' not in self.config['LDAP']:
|
|
||||||
# logger.info(
|
|
||||||
# 'No Config for USER_DN in LDAP found. Set it to default {}. (Maybe Password reset not working)'.format(None)
|
|
||||||
# )
|
|
||||||
# self.config['LDAP']['USER_DN'] = None
|
|
||||||
# if 'BIND_DN' not in self.config['LDAP']:
|
|
||||||
# logger.info(
|
|
||||||
# 'No Config for BIND_DN in LDAP found. Set it to default {}. (Maybe Password reset not working)'.format(None)
|
|
||||||
# )
|
|
||||||
# self.config['LDAP']['BIND_DN'] = None
|
|
||||||
# if 'BIND_SECRET' not in self.config['LDAP']:
|
|
||||||
# logger.info(
|
|
||||||
# 'No Config for BIND_SECRET in LDAP found. Set it to default {}. (Maybe Password reset not working)'.format(None)
|
|
||||||
# )
|
|
||||||
# self.config['LDAP']['BIND_SECRET'] = None
|
|
||||||
# if 'SSL' not in self.config['LDAP']:
|
|
||||||
# logger.info(
|
|
||||||
# 'No Config for SSL in LDAP found. Set it to default {}. (Maybe Password reset not working)'.format(False)
|
|
||||||
# )
|
|
||||||
# self.config['LDAP']['SSL'] = False
|
|
||||||
# else:
|
|
||||||
# self.config['LDAP']['SSL'] = bool(self.config['LDAP']['SSL'])
|
|
||||||
# self.ldap = self.config['LDAP']
|
|
||||||
# logger.debug("Set LDAPconfig: {}".format(self.ldap))
|
|
||||||
# if 'AccessTokenLifeTime' in self.config:
|
|
||||||
# self.accessTokenLifeTime = int(self.config['AccessTokenLifeTime'])
|
|
||||||
# logger.info("Set AccessTokenLifeTime: {}".format(
|
|
||||||
# self.accessTokenLifeTime))
|
|
||||||
# else:
|
|
||||||
# self.accessTokenLifeTime = default['AccessTokenLifeTime']
|
|
||||||
# logger.info("No Config for AccessTokenLifetime found. Set it to default: {}".format(
|
|
||||||
# self.accessTokenLifeTime))
|
|
||||||
#
|
|
||||||
# if 'Mail' not in self.config:
|
|
||||||
# self.config['Mail'] = default['Mail']
|
|
||||||
# logger.info('No Conifg for Mail found. Set it to defaul: {}'.format(
|
|
||||||
# self.config['Mail']))
|
|
||||||
# if 'URL' not in self.config['Mail']:
|
|
||||||
# self.config['Mail']['URL'] = default['Mail']['URL']
|
|
||||||
# logger.info("No Config for URL in Mail found. Set it to default")
|
|
||||||
# if 'port' not in self.config['Mail']:
|
|
||||||
# self.config['Mail']['port'] = default['Mail']['port']
|
|
||||||
# logger.info("No Config for port in Mail found. Set it to default")
|
|
||||||
# else:
|
|
||||||
# self.config['Mail']['port'] = int(self.config['Mail']['port'])
|
|
||||||
# logger.info("No Conifg for port in Mail found. Set it to default")
|
|
||||||
# if 'user' not in self.config['Mail']:
|
|
||||||
# self.config['Mail']['user'] = default['Mail']['user']
|
|
||||||
# logger.info("No Config for user in Mail found. Set it to default")
|
|
||||||
# if 'passwd' not in self.config['Mail']:
|
|
||||||
# self.config['Mail']['passwd'] = default['Mail']['passwd']
|
|
||||||
# logger.info("No Config for passwd in Mail found. Set it to default")
|
|
||||||
# if 'email' not in self.config['Mail']:
|
|
||||||
# self.config['Mail']['email'] = default['Mail']['email']
|
|
||||||
# logger.info("No Config for email in Mail found. Set it to default")
|
|
||||||
# if 'crypt' not in self.config['Mail']:
|
|
||||||
# self.config['Mail']['crypt'] = default['Mail']['crypt']
|
|
||||||
# logger.info("No Config for crypt in Mail found. Set it to default")
|
|
||||||
# self.mail = self.config['Mail']
|
|
||||||
# logger.debug('Set Mailconfig: {}'.format(self.mail))
|
|
||||||
#
|
|
||||||
# def getLDAP(self):
|
|
||||||
# return self.ldap
|
|
||||||
#
|
|
||||||
# def getDatabase(self):
|
|
||||||
# return self.db
|
|
||||||
#
|
|
||||||
# def getAccessToken(self):
|
|
||||||
# return self.accessTokenLifeTime
|
|
||||||
#
|
|
||||||
# def getMail(self):
|
|
||||||
# return self.mail
|
|
||||||
#
|
|
||||||
# def __error__(self, msg):
|
|
||||||
# logger.error(msg, exc_info=True)
|
|
||||||
# sys.exit(-1)
|
|
||||||
#
|
|
||||||
#
|
|
||||||
#if __name__ == '__main__':
|
|
||||||
# ConifgParser()
|
|
||||||
|
|
|
@ -7,14 +7,14 @@ from flaschengeist import logger
|
||||||
|
|
||||||
|
|
||||||
class Base:
|
class Base:
|
||||||
def loginUser(self, username, password):
|
def login_user(self, username, password):
|
||||||
logger.info("login user {{ {} }}".format(username))
|
logger.info("login user {{ {} }}".format(username))
|
||||||
user = User.query.filter_by(uid=username).first()
|
user = User.query.filter_by(uid=username).first()
|
||||||
if user is None:
|
if user is None:
|
||||||
user = User(uid=username)
|
user = User(uid=username)
|
||||||
if current_app.config['FG_AUTH_BACKEND'].login(user, password):
|
if current_app.config['FG_AUTH_BACKEND'].login(user, password):
|
||||||
db.session.add(user)
|
db.session.add(user)
|
||||||
current_app.config['FG_AUTH_BACKEND'].updateUser(user)
|
current_app.config['FG_AUTH_BACKEND'].update_user(user)
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
return user
|
return user
|
||||||
raise PermissionDenied()
|
raise PermissionDenied()
|
||||||
|
|
Loading…
Reference in New Issue