mysql adapter and ldap adapter
start adapetr for mysql not sqllite authenfication with ldap problem.. ldap and db is initialize in __init__.py when you initialize db, you initialize User and that requires ldap from __init__.py. But ldap is not initialize. if you initialize ldap, you initialize User and that requires db from __init__.py. But db is not initialize.
This commit is contained in:
parent
cd0def0c1b
commit
e8fc6c64b9
|
@ -8,6 +8,11 @@ import logging
|
||||||
from logging.handlers import WatchedFileHandler
|
from logging.handlers import WatchedFileHandler
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
|
MONEY = "moneymaster"
|
||||||
|
GASTRO = "gastro"
|
||||||
|
USER = "user"
|
||||||
|
BAR = "bar"
|
||||||
|
|
||||||
FORMATTER = logging.Formatter("%(asctime)s — %(name)s — %(levelname)s — %(message)s")
|
FORMATTER = logging.Formatter("%(asctime)s — %(name)s — %(levelname)s — %(message)s")
|
||||||
|
|
||||||
logFileHandler = WatchedFileHandler("testlog.log")
|
logFileHandler = WatchedFileHandler("testlog.log")
|
||||||
|
@ -29,6 +34,18 @@ def getLogger(logger_name):
|
||||||
LOGGER = getLogger(__name__)
|
LOGGER = getLogger(__name__)
|
||||||
LOGGER.info("Initialize App")
|
LOGGER.info("Initialize App")
|
||||||
|
|
||||||
|
class Singleton(type):
|
||||||
|
_instances = {}
|
||||||
|
def __call__(cls, *args, **kwargs):
|
||||||
|
if cls not in cls._instances:
|
||||||
|
cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
|
||||||
|
return cls._instances[cls]
|
||||||
|
from .controller.databaseController import DatabaseController
|
||||||
|
db = DatabaseController()
|
||||||
|
from .controller.ldapController import LDAPController
|
||||||
|
ldapController = LDAPController()
|
||||||
|
|
||||||
|
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
from flask_sqlalchemy import SQLAlchemy
|
from flask_sqlalchemy import SQLAlchemy
|
||||||
from flask_bcrypt import Bcrypt
|
from flask_bcrypt import Bcrypt
|
||||||
|
@ -41,7 +58,7 @@ app = Flask(__name__)
|
||||||
CORS(app)
|
CORS(app)
|
||||||
# app.config['SECRET_KEY'] = '0a657b97ef546da90b2db91862ad4e29'
|
# app.config['SECRET_KEY'] = '0a657b97ef546da90b2db91862ad4e29'
|
||||||
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
|
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db'
|
||||||
db = SQLAlchemy(app)
|
#db = SQLAlchemy(app)
|
||||||
bcrypt = Bcrypt(app)
|
bcrypt = Bcrypt(app)
|
||||||
accesTokenController = AccesTokenController("GERUECHT")
|
accesTokenController = AccesTokenController("GERUECHT")
|
||||||
accesTokenController.start()
|
accesTokenController.start()
|
||||||
|
@ -49,16 +66,13 @@ accesTokenController.start()
|
||||||
# login_manager.login_view = 'login'
|
# login_manager.login_view = 'login'
|
||||||
# login_manager.login_message_category = 'info'
|
# login_manager.login_message_category = 'info'
|
||||||
|
|
||||||
MONEY = "moneymaster"
|
|
||||||
GASTRO = "gastro"
|
|
||||||
USER = "user"
|
|
||||||
BAR = "bar"
|
|
||||||
|
|
||||||
|
|
||||||
from geruecht import routes
|
from geruecht import routes
|
||||||
from geruecht.baruser.routes import baruser
|
#from geruecht.baruser.routes import baruser
|
||||||
from geruecht.finanzer.routes import finanzer
|
#from geruecht.finanzer.routes import finanzer
|
||||||
|
|
||||||
LOGGER.info("Registrate bluebrints")
|
#LOGGER.info("Registrate bluebrints")
|
||||||
app.register_blueprint(baruser)
|
#app.register_blueprint(baruser)
|
||||||
app.register_blueprint(finanzer)
|
#app.register_blueprint(finanzer)
|
||||||
|
|
|
@ -6,8 +6,9 @@ from threading import Thread
|
||||||
import hashlib
|
import hashlib
|
||||||
import logging
|
import logging
|
||||||
from logging.handlers import WatchedFileHandler
|
from logging.handlers import WatchedFileHandler
|
||||||
|
from geruecht import Singleton
|
||||||
|
|
||||||
class AccesTokenController(Thread):
|
class AccesTokenController(Thread, metaclass=Singleton):
|
||||||
""" Control all createt AccesToken
|
""" Control all createt AccesToken
|
||||||
|
|
||||||
This Class create, delete, find and manage AccesToken.
|
This Class create, delete, find and manage AccesToken.
|
||||||
|
@ -16,12 +17,6 @@ class AccesTokenController(Thread):
|
||||||
tokenList: List of currents AccessToken
|
tokenList: List of currents AccessToken
|
||||||
lifetime: Variable for the Lifetime of one AccessToken in seconds.
|
lifetime: Variable for the Lifetime of one AccessToken in seconds.
|
||||||
"""
|
"""
|
||||||
class __OnlyOne:
|
|
||||||
def __init__(self, arg):
|
|
||||||
self.val = arg
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return repr(self) + self.val
|
|
||||||
instance = None
|
instance = None
|
||||||
tokenList = None
|
tokenList = None
|
||||||
lifetime = 60
|
lifetime = 60
|
||||||
|
@ -32,10 +27,6 @@ class AccesTokenController(Thread):
|
||||||
Initialize Thread and set tokenList empty.
|
Initialize Thread and set tokenList empty.
|
||||||
"""
|
"""
|
||||||
LOGGER.info("Initialize AccessTokenController")
|
LOGGER.info("Initialize AccessTokenController")
|
||||||
if not AccesTokenController.instance:
|
|
||||||
AccesTokenController.instance = AccesTokenController.__OnlyOne(arg)
|
|
||||||
else:
|
|
||||||
AccesTokenController.instance.val = arg
|
|
||||||
|
|
||||||
LOGGER.debug("Build Logger for VerificationThread")
|
LOGGER.debug("Build Logger for VerificationThread")
|
||||||
|
|
||||||
|
@ -87,7 +78,7 @@ class AccesTokenController(Thread):
|
||||||
"""
|
"""
|
||||||
LOGGER.info("Create AccessToken")
|
LOGGER.info("Create AccessToken")
|
||||||
now = datetime.ctime(datetime.now())
|
now = datetime.ctime(datetime.now())
|
||||||
token = hashlib.md5((now + user.password).encode('utf-8')).hexdigest()
|
token = hashlib.md5((now + user.dn).encode('utf-8')).hexdigest()
|
||||||
accToken = AccessToken(user, token)
|
accToken = AccessToken(user, token)
|
||||||
LOGGER.debug("Add AccessToken {} to current Tokens".format(accToken))
|
LOGGER.debug("Add AccessToken {} to current Tokens".format(accToken))
|
||||||
self.tokenList.append(accToken)
|
self.tokenList.append(accToken)
|
||||||
|
@ -115,17 +106,20 @@ class AccesTokenController(Thread):
|
||||||
|
|
||||||
Verify that the AccesToken are not out of date. If one AccessToken out of date it will be deletet from tokenList.
|
Verify that the AccesToken are not out of date. If one AccessToken out of date it will be deletet from tokenList.
|
||||||
"""
|
"""
|
||||||
|
valid_time=120
|
||||||
LOGGER.info("Start Thread for verification that the AccessToken are not out of date.")
|
LOGGER.info("Start Thread for verification that the AccessToken are not out of date.")
|
||||||
while True:
|
while True:
|
||||||
|
self.LOGGER.debug("Name: {}".format(self.getName()))
|
||||||
self.LOGGER.debug("Start to iterate through List of current Tokens")
|
self.LOGGER.debug("Start to iterate through List of current Tokens")
|
||||||
for accToken in self.tokenList:
|
for accToken in self.tokenList:
|
||||||
|
|
||||||
self.LOGGER.debug("Check if AccessToken {} is out of date".format(accToken))
|
self.LOGGER.debug("Check if AccessToken {} is out of date".format(accToken))
|
||||||
if (datetime.now() - accToken.timestamp).seconds > 7200:
|
if (datetime.now() - accToken.timestamp).seconds > valid_time:
|
||||||
print("delete", accToken)
|
print("delete", accToken)
|
||||||
self.LOGGER.info("Delete AccessToken {} from List of current Tokens".format(accToken))
|
self.LOGGER.info("Delete AccessToken {} from List of current Tokens".format(accToken))
|
||||||
self.tokenList.remove(accToken)
|
self.tokenList.remove(accToken)
|
||||||
else:
|
else:
|
||||||
self.LOGGER.debug("AccessToken {} is up to date. {} seconds left".format(accToken, 7200 - (datetime.now() - accToken.timestamp).seconds))
|
self.LOGGER.debug("AccessToken {} is up to date. {} seconds left".format(accToken, valid_time - (datetime.now() - accToken.timestamp).seconds))
|
||||||
self.LOGGER.debug("List of current Tokens: {}".format(self.tokenList))
|
self.LOGGER.debug("List of current Tokens: {}".format(self.tokenList))
|
||||||
self.LOGGER.info("Wait 10 Seconds")
|
self.LOGGER.info("Wait 10 Seconds")
|
||||||
time.sleep(10)
|
time.sleep(10)
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
import pymysql
|
||||||
|
from geruecht import Singleton
|
||||||
|
from geruecht.model.user import User
|
||||||
|
|
||||||
|
class DatabaseController(metaclass=Singleton):
|
||||||
|
'''
|
||||||
|
DatabaesController
|
||||||
|
|
||||||
|
Connect to the Database and execute sql-executions
|
||||||
|
'''
|
||||||
|
|
||||||
|
def __init__(self, url='192.168.5.108', user='wu5', password='E1n$tein', database='geruecht'):
|
||||||
|
self.url = url
|
||||||
|
self.user = user
|
||||||
|
self.password = password
|
||||||
|
self.database = database
|
||||||
|
self.connect()
|
||||||
|
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
try:
|
||||||
|
self.db = pymysql.connect(self.url, self.user, self.password, self.database, cursorclass=pymysql.cursors.DictCursor)
|
||||||
|
except Exception as err:
|
||||||
|
raise err
|
||||||
|
|
||||||
|
def getAllUser(self):
|
||||||
|
cursor = self.db.cursor()
|
||||||
|
|
||||||
|
def getUser(self, username):
|
||||||
|
self.connect()
|
||||||
|
retVal = None
|
||||||
|
cursor = self.db.cursor()
|
||||||
|
cursor.execute("select * from user where cn='{}'".format(username))
|
||||||
|
data = cursor.fetchone()
|
||||||
|
if data:
|
||||||
|
retVal = User(data)
|
||||||
|
self.db.close()
|
||||||
|
return retVal
|
||||||
|
|
||||||
|
|
||||||
|
def insertUser(self, data):
|
||||||
|
self.connect()
|
||||||
|
cursor = self.db.cursor()
|
||||||
|
try:
|
||||||
|
cursor.execute("insert into user (cn, dn, firstname, lastname, `group`) VALUES ('{}','{}','{}','{}','{}')".format(
|
||||||
|
data['cn'], data['dn'], data['givenName'], data['sn'], data['group']))
|
||||||
|
self.db.commit()
|
||||||
|
except Exception as err:
|
||||||
|
self.db.rollback()
|
||||||
|
self.db.close()
|
||||||
|
raise err
|
||||||
|
self.db.close()
|
||||||
|
|
||||||
|
def updateUser(self, data):
|
||||||
|
self.connect()
|
||||||
|
cursor = self.db.cursor()
|
||||||
|
try:
|
||||||
|
cursor.execute("update user dn='{}', firstname='{}', lastname='{}', group='{}' where cn='{}'".format(
|
||||||
|
data['dn'], data['givenName'], data['sn'], data['group'], data['cn']))
|
||||||
|
self.db.commit()
|
||||||
|
except Exception as err:
|
||||||
|
self.db.rollback()
|
||||||
|
self.db.close()
|
||||||
|
raise err
|
||||||
|
self.db.close()
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
db = DatabaseController(user='tim')
|
|
@ -0,0 +1,56 @@
|
||||||
|
import ldap
|
||||||
|
from geruecht import MONEY, USER, GASTRO, BAR, Singleton
|
||||||
|
|
||||||
|
class LDAPController(metaclass=Singleton):
|
||||||
|
'''
|
||||||
|
Authentification over LDAP. Create Account on-the-fly
|
||||||
|
'''
|
||||||
|
|
||||||
|
def __init__(self, url="ldap://192.168.5.108", dn='dc=ldap,dc=example,dc=local'):
|
||||||
|
self.url = url
|
||||||
|
self.dn = dn
|
||||||
|
self.connect()
|
||||||
|
|
||||||
|
def connect(self):
|
||||||
|
try:
|
||||||
|
self.client = ldap.initialize(self.url, bytes_mode=False)
|
||||||
|
except Exception as err:
|
||||||
|
raise err
|
||||||
|
|
||||||
|
def login(self, username, password):
|
||||||
|
self.connect()
|
||||||
|
try:
|
||||||
|
self.client.bind_s("cn={},ou=user,{}".format(username, self.dn), password)
|
||||||
|
self.client.unbind_s()
|
||||||
|
except:
|
||||||
|
self.client.unbind_s()
|
||||||
|
raise Exception("Invalid Password or Username")
|
||||||
|
|
||||||
|
def getUserData(self, username):
|
||||||
|
self.connect()
|
||||||
|
search_data = self.client.search_s('ou=user,{}'.format(self.dn), ldap.SCOPE_SUBTREE, 'cn={}'.format(username), ['cn', 'givenName', 'sn'])
|
||||||
|
retVal = search_data[0][1]
|
||||||
|
for k,v in retVal.items():
|
||||||
|
retVal[k] = v[0].decode('utf-8')
|
||||||
|
retVal['dn'] = self.dn
|
||||||
|
return retVal
|
||||||
|
|
||||||
|
|
||||||
|
def getGroup(self, username):
|
||||||
|
self.connect()
|
||||||
|
groups_data = self.client.search_s('ou=group,{}'.format(self.dn), ldap.SCOPE_SUBTREE, 'memberUID={}'.format(username), ['cn'])
|
||||||
|
if len(groups_data) == 0:
|
||||||
|
return USER
|
||||||
|
else:
|
||||||
|
data = groups_data[0][1]['cn'][0].decode('utf-8')
|
||||||
|
if data == 'finanzer':
|
||||||
|
return MONEY
|
||||||
|
elif data == 'gastro':
|
||||||
|
return GASTRO
|
||||||
|
elif data == 'bar':
|
||||||
|
return BAR
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
a = LDAPController()
|
||||||
|
a.getUserData('jhille')
|
|
@ -1,10 +1,9 @@
|
||||||
from geruecht import db
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from geruecht import getLogger
|
from geruecht import getLogger
|
||||||
|
|
||||||
LOGGER = getLogger(__name__)
|
LOGGER = getLogger(__name__)
|
||||||
|
|
||||||
class CreditList(db.Model):
|
class CreditList():
|
||||||
""" DataBase Object Credit List:
|
""" DataBase Object Credit List:
|
||||||
|
|
||||||
Attributes:
|
Attributes:
|
||||||
|
@ -17,7 +16,7 @@ class CreditList(db.Model):
|
||||||
user_id: id from the User.
|
user_id: id from the User.
|
||||||
"""
|
"""
|
||||||
LOGGER.debug("Initialize Geruecht")
|
LOGGER.debug("Initialize Geruecht")
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
id = db.Colum(db.Integer, primary_key=True)
|
||||||
|
|
||||||
jan_guthaben = db.Column(db.Integer, nullable=False, default=0)
|
jan_guthaben = db.Column(db.Integer, nullable=False, default=0)
|
||||||
jan_schulden = db.Column(db.Integer, nullable=False, default=0)
|
jan_schulden = db.Column(db.Integer, nullable=False, default=0)
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
from geruecht import db, bcrypt, getLogger
|
from geruecht import getLogger
|
||||||
from geruecht.model.creditList import CreditList
|
from geruecht import db
|
||||||
|
#from geruecht.model.creditList import CreditList
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
LOGGER = getLogger(__name__)
|
LOGGER = getLogger(__name__)
|
||||||
|
|
||||||
class User(db.Model):
|
class User():
|
||||||
""" Database Object for User
|
""" Database Object for User
|
||||||
|
|
||||||
Table for all safed User
|
Table for all safed User
|
||||||
|
@ -18,16 +19,16 @@ class User(db.Model):
|
||||||
group: Which group is the User? moneymaster, gastro, user or bar?
|
group: Which group is the User? moneymaster, gastro, user or bar?
|
||||||
password: salted hashed password for the User.
|
password: salted hashed password for the User.
|
||||||
"""
|
"""
|
||||||
id = db.Column(db.Integer, primary_key=True)
|
def __init__(self, data):
|
||||||
userID = db.Column(db.String, nullable=False, unique=True)
|
self.id = int(data['id'])
|
||||||
username = db.Column(db.String, nullable=False, unique=True)
|
self.cn = data['cn']
|
||||||
firstname = db.Column(db.String, nullable=False)
|
self.dn = data['dn']
|
||||||
lastname = db.Column(db.String, nullable=False)
|
self.firstname = data['firstname']
|
||||||
group = db.Column(db.String, nullable=False)
|
self.lastname = data['lastname']
|
||||||
password = db.Column(db.String, nullable=False)
|
self.group = data['group']
|
||||||
|
|
||||||
geruechte = db.relationship('CreditList', backref='user', lazy=True)
|
|
||||||
|
|
||||||
|
#geruechte = db.relationship('CreditList', backref='user', lazy=True)
|
||||||
|
'''
|
||||||
def createGeruecht(self, amount=0, year=datetime.now().year):
|
def createGeruecht(self, amount=0, year=datetime.now().year):
|
||||||
""" Create Geruecht
|
""" Create Geruecht
|
||||||
|
|
||||||
|
@ -153,7 +154,7 @@ class User(db.Model):
|
||||||
int year of the geruecht
|
int year of the geruecht
|
||||||
"""
|
"""
|
||||||
return geruecht.year
|
return geruecht.year
|
||||||
|
'''
|
||||||
def toJSON(self):
|
def toJSON(self):
|
||||||
""" Create Dic to dump in JSON
|
""" Create Dic to dump in JSON
|
||||||
|
|
||||||
|
@ -161,14 +162,19 @@ class User(db.Model):
|
||||||
A Dic with static Attributes.
|
A Dic with static Attributes.
|
||||||
"""
|
"""
|
||||||
dic = {
|
dic = {
|
||||||
"userId": self.userID,
|
"cn": self.cn,
|
||||||
"username": self.username,
|
"dn": self.dn,
|
||||||
"firstname": self.firstname,
|
"firstname": self.firstname,
|
||||||
"lastname": self.lastname,
|
"lastname": self.lastname,
|
||||||
"group": self.group,
|
"group": self.group,
|
||||||
}
|
}
|
||||||
return dic
|
return dic
|
||||||
|
|
||||||
|
def update(self):
|
||||||
|
data = ldap.getUserData(self.cn)
|
||||||
|
data['group'] = ldap.getGroup(self.cn)
|
||||||
|
db.updateUser(data)
|
||||||
|
|
||||||
def login(self, password):
|
def login(self, password):
|
||||||
""" Login for the User
|
""" Login for the User
|
||||||
|
|
||||||
|
@ -178,7 +184,14 @@ class User(db.Model):
|
||||||
A Bool. True if the password is correct and False if it isn't.
|
A Bool. True if the password is correct and False if it isn't.
|
||||||
"""
|
"""
|
||||||
LOGGER.debug("Login User {}".format(self))
|
LOGGER.debug("Login User {}".format(self))
|
||||||
return True if bcrypt.check_password_hash(self.password, password) else False
|
try:
|
||||||
|
from geruecht import ldapController as ldap
|
||||||
|
ldap.login(self.cn, password)
|
||||||
|
|
||||||
|
self.update()
|
||||||
|
return True
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "User({}, {}, {})".format(self.userID, self.username, self.group)
|
return "User({}, {}, {})".format(self.cn, self.dn, self.group)
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
from geruecht import app, db, accesTokenController, MONEY, BAR, USER, GASTRO, LOGGER
|
from geruecht import app, db, accesTokenController, MONEY, BAR, USER, GASTRO, LOGGER
|
||||||
|
from geruecht import ldapController as ldap
|
||||||
from geruecht.model.user import User
|
from geruecht.model.user import User
|
||||||
from geruecht.model.creditList import CreditList
|
#from geruecht.model.creditList import CreditList
|
||||||
from geruecht.model.priceList import PriceList
|
#from geruecht.model.priceList import PriceList
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from flask import request, jsonify
|
from flask import request, jsonify
|
||||||
|
|
||||||
|
@ -61,8 +62,24 @@ def _login():
|
||||||
LOGGER.debug("JSON from request: {}".format(data))
|
LOGGER.debug("JSON from request: {}".format(data))
|
||||||
username = data['username']
|
username = data['username']
|
||||||
password = data['password']
|
password = data['password']
|
||||||
|
LOGGER.info("search {} in database".format(username))
|
||||||
|
user = db.getUser(username)
|
||||||
|
if user is None:
|
||||||
|
LOGGER.info("User {} not found. Authenticate over LDAP and create User.")
|
||||||
|
try:
|
||||||
|
ldap.login(username, password)
|
||||||
|
LOGGER.info("Authentification successfull. Search Group")
|
||||||
|
group = ldap.getGroup(username)
|
||||||
|
LOGGER.info("Get userdata from LDAP")
|
||||||
|
user_data = ldap.getUserData(username)
|
||||||
|
user_data['group'] = group
|
||||||
|
LOGGER.info('Insert user {} into database')
|
||||||
|
db.insertUser(user_data)
|
||||||
|
|
||||||
|
except Exception as err:
|
||||||
|
raise err
|
||||||
LOGGER.info("{} try to log in".format(username))
|
LOGGER.info("{} try to log in".format(username))
|
||||||
user = User.query.filter_by(username=username).first()
|
user = db.getUser(username)
|
||||||
LOGGER.debug("User is {}".format(user))
|
LOGGER.debug("User is {}".format(user))
|
||||||
if user:
|
if user:
|
||||||
LOGGER.debug("Check login for User {}".format(user))
|
LOGGER.debug("Check login for User {}".format(user))
|
||||||
|
|
Loading…
Reference in New Issue