diff --git a/.gitignore b/.gitignore index 716695e..ed93d09 100644 --- a/.gitignore +++ b/.gitignore @@ -116,4 +116,13 @@ dmypy.json .pyre/ #ide -.idea \ No newline at end of file +.idea + +.vscode/ +*.log + +# custom +test_pricelist/ +test_project/ +config.yml +geruecht.config.yml diff --git a/geruecht/__init__.py b/geruecht/__init__.py index a514acd..2687a9a 100644 --- a/geruecht/__init__.py +++ b/geruecht/__init__.py @@ -1,17 +1,59 @@ -from flask import Flask, g -from flask_sqlalchemy import SQLAlchemy -from flask_bcrypt import Bcrypt -from flask_login import LoginManager +""" Server-package + Initialize app, cors, database and bcrypt (for passwordhashing) and added it to the application. + Initialize also a singelton for the AccesTokenControler and start the Thread. +""" +from .logger import getDebugLogger +from geruecht.controller import dbConfig, ldapConfig +from flask_mysqldb import MySQL +from flask_ldapconn import LDAPConn +import ssl + +DEBUG = getDebugLogger() +DEBUG.info("Initialize App") + +from flask import Flask +from flask_cors import CORS + +DEBUG.info("Build APP") app = Flask(__name__) +CORS(app) app.config['SECRET_KEY'] = '0a657b97ef546da90b2db91862ad4e29' -app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///site.db' -db = SQLAlchemy(app) -bcrypt = Bcrypt(app) -login_manager = LoginManager(app) -login_manager.login_view = 'login' -login_manager.login_message_category = 'info' +app.config['MYSQL_HOST'] = dbConfig['URL'] +app.config['MYSQL_USER'] = dbConfig['user'] +app.config['MYSQL_PASSWORD'] = dbConfig['passwd'] +app.config['MYSQL_DB'] = dbConfig['database'] +app.config['MYSQL_CURSORCLASS'] = 'DictCursor' +app.config['LDAP_SERVER'] = ldapConfig['URL'] +app.config['LDAP_PORT'] = ldapConfig['PORT'] +if ldapConfig['BIND_DN']: + app.config['LDAP_BINDDN'] = ldapConfig['BIND_DN'] +else: + app.config['LDAP_BINDDN'] = ldapConfig['DN'] +if ldapConfig['BIND_SECRET']: + app.config['LDAP_SECRET'] = ldapConfig['BIND_SECRET'] +app.config['LDAP_USE_TLS'] = False +app.config['LDAP_USE_SSL'] = ldapConfig['SSL'] +app.config['LDAP_TLS_VERSION'] = ssl.PROTOCOL_TLSv1_2 +app.config['LDAP_REQUIRE_CERT'] = ssl.CERT_NONE +app.config['FORCE_ATTRIBUTE_VALUE_AS_LIST'] = True +ldap = LDAPConn(app) +db = MySQL(app) -from geruecht import routes \ No newline at end of file +from geruecht import routes +from geruecht.baruser.routes import baruser +from geruecht.finanzer.routes import finanzer +from geruecht.user.routes import user +from geruecht.vorstand.routes import vorstand +from geruecht.gastro.routes import gastrouser +from geruecht.registration_route import registration + +DEBUG.info("Registrate bluebrints") +app.register_blueprint(baruser) +app.register_blueprint(finanzer) +app.register_blueprint(user) +app.register_blueprint(vorstand) +app.register_blueprint(gastrouser) +app.register_blueprint(registration) diff --git a/geruecht/baruser/__init__.py b/geruecht/baruser/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/geruecht/baruser/routes.py b/geruecht/baruser/routes.py new file mode 100644 index 0000000..dc7c383 --- /dev/null +++ b/geruecht/baruser/routes.py @@ -0,0 +1,224 @@ +from flask import Blueprint, request, jsonify +import geruecht.controller.ldapController as lc +import geruecht.controller.mainController as mc +import geruecht.controller.accesTokenController as ac +from datetime import datetime +from geruecht.model import BAR, MONEY, USER, VORSTAND, EXTERN +from geruecht.decorator import login_required +from geruecht.logger import getDebugLogger, getCreditLogger + +debug = getDebugLogger() +creditL = getCreditLogger() + +baruser = Blueprint("baruser", __name__) + +ldap = lc.LDAPController() +mainController = mc.MainController() +accesTokenController = ac.AccesTokenController() + + +@baruser.route("/bar") +@login_required(groups=[BAR], bar=True) +def _bar(**kwargs): + """ Main function for Baruser + + Returns JSON-file with all Users, who hast amounts in this month. + + Returns: + JSON-File with Users, who has amounts in this month + or ERROR 401 Permission Denied + """ + debug.info("/bar") + try: + dic = {} + users = mainController.getAllUsersfromDB() + for user in users: + geruecht = None + geruecht = user.getGeruecht(datetime.now().year) + if geruecht is not None: + all = geruecht.getSchulden() + if all != 0: + if all >= 0: + type = 'credit' + else: + type = 'amount' + dic[user.uid] = {"username": user.uid, + "firstname": user.firstname, + "lastname": user.lastname, + "amount": all, + "locked": user.locked, + "type": type, + "limit": user.limit, + "autoLock": user.autoLock + } + dic[user.uid]['last_seen'] = {"year": user.last_seen.year, "month": user.last_seen.month, "day": user.last_seen.day, "hour": user.last_seen.hour, "minute": user.last_seen.minute, "second": user.last_seen.second} if user.last_seen else None + debug.debug("return {{ {} }}".format(dic)) + return jsonify(dic) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@baruser.route("/baradd", methods=['POST']) +@login_required(groups=[BAR], bar=True) +def _baradd(**kwargs): + """ Function for Baruser to add amount + + This function added to the user with the posted userID the posted amount. + + Returns: + JSON-File with userID and the amount + or ERROR 401 Permission Denied + """ + debug.info("/baradd") + try: + data = request.get_json() + userID = data['userId'] + amount = int(data['amount']) + amountl = amount + date = datetime.now() + mainController.addAmount( + userID, amount, year=date.year, month=date.month, bar=True) + user = mainController.getUser(userID) + geruecht = user.getGeruecht(year=date.year) + month = geruecht.getMonth(month=date.month) + amount = abs(month[0] - month[1]) + all = geruecht.getSchulden() + if all >= 0: + type = 'credit' + else: + type = 'amount' + dic = user.toJSON() + dic['amount'] = all + dic['type'] = type + dic['last_seen'] = {"year": user.last_seen.year, "month": user.last_seen.month, "day": user.last_seen.day, "hour": user.last_seen.hour, "minute": user.last_seen.minute, "second": user.last_seen.second} if user.last_seen else None + debug.debug("return {{ {} }}".format(dic)) + creditL.info("{} Baruser {} {} fügt {} {} {} € Schulden hinzu.".format( + date, kwargs['accToken'].user.firstname, kwargs['accToken'].user.lastname, user.firstname, user.lastname, amountl/100)) + return jsonify(dic) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@baruser.route("/barGetUsers") +@login_required(groups=[BAR, MONEY], bar=True) +def _getUsers(**kwargs): + """ Get Users without amount + + This Function returns all Users, who hasn't an amount in this month. + + Returns: + JSON-File with Users + or ERROR 401 Permission Denied + """ + debug.info("/barGetUsers") + try: + retVal = {} + retVal = ldap.getAllUser() + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@baruser.route("/bar/storno", methods=['POST']) +@login_required(groups=[BAR], bar=True) +def _storno(**kwargs): + """ Function for Baruser to storno amount + + This function added to the user with the posted userID the posted amount. + + Returns: + JSON-File with userID and the amount + or ERROR 401 Permission Denied + """ + debug.info("/bar/storno") + try: + data = request.get_json() + userID = data['userId'] + amount = int(data['amount']) + amountl = amount + date = datetime.now() + mainController.addCredit( + userID, amount, year=date.year, month=date.month) + user = mainController.getUser(userID) + geruecht = user.getGeruecht(year=date.year) + month = geruecht.getMonth(month=date.month) + amount = abs(month[0] - month[1]) + all = geruecht.getSchulden() + if all >= 0: + type = 'credit' + else: + type = 'amount' + dic = user.toJSON() + dic['amount'] = all + dic['type'] = type + dic['last_seen'] = {"year": user.last_seen.year, "month": user.last_seen.month, "day": user.last_seen.day, + "hour": user.last_seen.hour, "minute": user.last_seen.minute, + "second": user.last_seen.second} if user.last_seen else None + debug.debug("return {{ {} }}".format(dic)) + creditL.info("{} Baruser {} {} storniert {} € von {} {}".format( + date, kwargs['accToken'].user.firstname, kwargs['accToken'].user.lastname, amountl/100, user.firstname, user.lastname)) + return jsonify(dic) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@baruser.route("/barGetUser", methods=['POST']) +@login_required(groups=[BAR], bar=True) +def _getUser(**kwargs): + debug.info("/barGetUser") + try: + data = request.get_json() + username = data['userId'] + user = mainController.getUser(username) + amount = user.getGeruecht(datetime.now().year).getSchulden() + if amount >= 0: + type = 'credit' + else: + type = 'amount' + + retVal = user.toJSON() + retVal['amount'] = amount + retVal['type'] = type + + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@baruser.route("/search", methods=['GET']) +@login_required(groups=[BAR, MONEY, USER, VORSTAND], bar=True) +def _search(**kwargs): + debug.info("/search") + try: + retVal = ldap.getAllUser() + for user in retVal: + if user['username'] == 'extern': + retVal.remove(user) + break + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + +@baruser.route("/bar/lock", methods=['GET', 'POST']) +@login_required(groups=[BAR], bar=True) +def _lockbar(**kwargs): + + debug.info('/bar/lock') + accToken = kwargs['accToken'] + if request.method == "POST": + data = request.get_json() + accToken.lock_bar = data['value'] + accToken = accesTokenController.updateAccessToken(accToken) + accToken = accesTokenController.validateAccessToken(accToken.token, [USER, EXTERN]) + debug.debug('return {{ "value": {} }}'.format(accToken.lock_bar)) + return jsonify({'value': accToken.lock_bar}) + diff --git a/geruecht/config.yml.example b/geruecht/config.yml.example new file mode 100644 index 0000000..62a16a2 --- /dev/null +++ b/geruecht/config.yml.example @@ -0,0 +1,22 @@ +AccessTokenLifeTime: 1800 +Database: + URL: + user: + passwd: + database: +LDAP: + URL: + DN: + BIND_DN: + BIND_SECRET: + SSL: + USER_DN: + ADMIN_DN: + ADMIN_SECRET: +Mail: + URL: + port: + user: + passwd: + email: + crypt: SSL/STARTLS \ No newline at end of file diff --git a/geruecht/configparser.py b/geruecht/configparser.py new file mode 100644 index 0000000..1fbe90c --- /dev/null +++ b/geruecht/configparser.py @@ -0,0 +1,134 @@ +import yaml +import sys +from .logger import getDebugLogger +DEBUG = getDebugLogger() + +default = { + 'AccessTokenLifeTime': 1800, + 'Mail': { + 'URL': '', + 'port': 0, + 'user': '', + 'passwd': '', + 'email': '', + 'crypt': 'STARTTLS' + } +} + + +class ConifgParser(): + def __init__(self, file='config.yml'): + self.file = file + with open(file, 'r') as f: + 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'] + DEBUG.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']: + DEBUG.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']: + DEBUG.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']: + DEBUG.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']: + DEBUG.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']: + DEBUG.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']: + DEBUG.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']: + DEBUG.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'] + DEBUG.info("Set LDAPconfig: {}".format(self.ldap)) + if 'AccessTokenLifeTime' in self.config: + self.accessTokenLifeTime = int(self.config['AccessTokenLifeTime']) + DEBUG.info("Set AccessTokenLifeTime: {}".format( + self.accessTokenLifeTime)) + else: + self.accessTokenLifeTime = default['AccessTokenLifeTime'] + DEBUG.info("No Config for AccessTokenLifetime found. Set it to default: {}".format( + self.accessTokenLifeTime)) + + if 'Mail' not in self.config: + self.config['Mail'] = default['Mail'] + DEBUG.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'] + DEBUG.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'] + DEBUG.info("No Config for port in Mail found. Set it to default") + else: + self.config['Mail']['port'] = int(self.config['Mail']['port']) + DEBUG.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'] + DEBUG.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'] + DEBUG.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'] + DEBUG.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'] + DEBUG.info("No Config for crypt in Mail found. Set it to default") + self.mail = self.config['Mail'] + DEBUG.info('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): + DEBUG.error(msg, exc_info=True) + sys.exit(-1) + + +if __name__ == '__main__': + ConifgParser() diff --git a/geruecht/controller/__init__.py b/geruecht/controller/__init__.py new file mode 100644 index 0000000..b7f1734 --- /dev/null +++ b/geruecht/controller/__init__.py @@ -0,0 +1,21 @@ +from geruecht.logger import getDebugLogger +from geruecht.configparser import ConifgParser +import os + +print(os.getcwd()) + +config = ConifgParser('geruecht/config.yml') + +LOGGER = getDebugLogger() + +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] + +dbConfig = config.getDatabase() +ldapConfig = config.getLDAP() +accConfig = config.getAccessToken() +mailConfig = config.getMail() diff --git a/geruecht/controller/accesTokenController.py b/geruecht/controller/accesTokenController.py new file mode 100644 index 0000000..bec7703 --- /dev/null +++ b/geruecht/controller/accesTokenController.py @@ -0,0 +1,129 @@ +from geruecht.model.accessToken import AccessToken +import geruecht.controller as gc +import geruecht.controller.mainController as mc +import geruecht.controller.databaseController as dc +from geruecht.model import BAR +from datetime import datetime, timedelta +import hashlib +from . import Singleton +from geruecht.logger import getDebugLogger + +debug = getDebugLogger() + +mainController = mc.MainController() +db = dc.DatabaseController() + +class AccesTokenController(metaclass=Singleton): + """ Control all createt AccesToken + + This Class create, delete, find and manage AccesToken. + + Attributes: + tokenList: List of currents AccessToken + lifetime: Variable for the Lifetime of one AccessToken in seconds. + """ + instance = None + tokenList = None + + def __init__(self, lifetime=1800): + """ Initialize AccessTokenController + + Initialize Thread and set tokenList empty. + """ + debug.info("init accesstoken controller") + self.lifetime = gc.accConfig + + def checkBar(self, user): + debug.info("check if user {{ {} }} is baruser".format(user)) + if (mainController.checkBarUser(user)): + if BAR not in user.group: + debug.debug("append bar to user {{ {} }}".format(user)) + user.group.append(BAR) + return True + else: + while BAR in user.group: + debug.debug("delete bar from user {{ {} }}".format(user)) + user.group.remove(BAR) + return False + debug.debug("user {{ {} }} groups are {{ {} }}".format(user, user.group)) + + def validateAccessToken(self, token, group): + """ Verify Accestoken + + Verify an Accestoken and Group so if the User has permission or not. + Retrieves the accestoken if valid else retrieves False + + Args: + token: Token to verify. + group: Group like 'moneymaster', 'gastro', 'user' or 'bar' + Returns: + An the AccesToken for this given Token or False. + """ + debug.info("check token {{ {} }} is valid") + for accToken in db.getAccessTokens(): + debug.debug("accesstoken is {}".format(accToken)) + endTime = accToken.timestamp + timedelta(seconds=accToken.lifetime) + now = datetime.now() + debug.debug("now is {{ {} }}, endtime is {{ {} }}".format(now, endTime)) + if now <= endTime: + debug.debug("check if token {{ {} }} is same as {{ {} }}".format(token, accToken)) + if accToken == token: + if not self.checkBar(accToken.user): + accToken.lock_bar = False + debug.debug("check if accestoken {{ {} }} has group {{ {} }}".format(accToken, group)) + if self.isSameGroup(accToken, group): + accToken.updateTimestamp() + db.updateAccessToken(accToken) + debug.debug("found accesstoken {{ {} }} with token: {{ {} }} and group: {{ {} }}".format(accToken, token, group)) + return accToken + else: + debug.debug("accesstoken is {{ {} }} out of date".format(accToken)) + db.deleteAccessToken(accToken) + debug.debug("no valid accesstoken with token: {{ {} }} and group: {{ {} }}".format(token, group)) + return False + + def createAccesToken(self, user, user_agent=None): + """ Create an AccessToken + + Create an AccessToken for an User and add it to the tokenList. + + Args: + user: For wich User is to create an AccessToken + + Returns: + A created Token for User + """ + debug.info("creat accesstoken") + now = datetime.ctime(datetime.now()) + token = hashlib.md5((now + user.dn).encode('utf-8')).hexdigest() + self.checkBar(user) + accToken = db.createAccessToken(user, token, self.lifetime, datetime.now(), lock_bar=False, user_agent=user_agent) + debug.debug("accesstoken is {{ {} }}".format(accToken)) + return token + + def isSameGroup(self, accToken, groups): + """ Verify group in AccessToken + + Verify if the User in the AccesToken has the right group. + + Args: + accToken: AccessToken to verify. + groups: Group to verify. + + Returns: + A Bool. If the same then True else False + """ + debug.info("check accesstoken {{ {} }} has group {{ {} }}".format(accToken, groups)) + for group in groups: + if group in accToken.user.group: return True + return False + + def getAccessTokensFromUser(self, user): + return db.getAccessTokensFromUser(user) + + def deleteAccessToken(self, accToken): + db.deleteAccessToken(accToken) + + def updateAccessToken(self, accToken): + accToken.updateTimestamp() + return db.updateAccessToken(accToken) diff --git a/geruecht/controller/databaseController/__init__.py b/geruecht/controller/databaseController/__init__.py new file mode 100644 index 0000000..8f783fd --- /dev/null +++ b/geruecht/controller/databaseController/__init__.py @@ -0,0 +1,71 @@ +from ..mainController import Singleton +from geruecht import db +from ..databaseController import dbUserController, dbCreditListController, dbJobKindController, dbPricelistController, dbWorkerController, dbWorkgroupController, dbJobInviteController, dbJobRequesController, dbAccessTokenController, dbRegistrationController +from geruecht.exceptions import DatabaseExecption +import traceback +from MySQLdb._exceptions import IntegrityError + +class DatabaseController(dbUserController.Base, + dbCreditListController.Base, + dbWorkerController.Base, + dbWorkgroupController.Base, + dbPricelistController.Base, + dbJobKindController.Base, + dbJobInviteController.Base, + dbJobRequesController.Base, + dbAccessTokenController.Base, + dbRegistrationController.Base, + metaclass=Singleton): + ''' + DatabaesController + + Connect to the Database and execute sql-executions + ''' + + def __init__(self): + self.db = db + + def getLockedDay(self, date): + try: + cursor = self.db.connection.cursor() + cursor.execute("select * from locked_days where daydate='{}'".format(date)) + data = cursor.fetchone() + return data + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def setLockedDay(self, date, locked, hard=False): + try: + cursor = self.db.connection.cursor() + sql = "insert into locked_days (daydate, locked) VALUES ('{}', {})".format(date, locked) + cursor.execute(sql) + self.db.connection.commit() + return self.getLockedDay(date) + except IntegrityError as err: + self.db.connection.rollback() + try: + exists = self.getLockedDay(date) + if hard: + sql = "update locked_days set locked={} where id={}".format(locked, exists['id']) + else: + sql = False + if sql: + cursor.execute(sql) + self.db.connection.commit() + return self.getLockedDay(date) + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went wrong with Database: {}".format(err)) + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + +if __name__ == '__main__': + db = DatabaseController() + user = db.getUser('jhille') + db.getCreditListFromUser(user, year=2018) diff --git a/geruecht/controller/databaseController/dbAccessTokenController.py b/geruecht/controller/databaseController/dbAccessTokenController.py new file mode 100644 index 0000000..13ae442 --- /dev/null +++ b/geruecht/controller/databaseController/dbAccessTokenController.py @@ -0,0 +1,82 @@ +import traceback +from geruecht.exceptions import DatabaseExecption +from geruecht.model.accessToken import AccessToken + + +class Base: + + def getAccessToken(self, item): + try: + cursor = self.db.connection.cursor() + if type(item) == str: + sql = "select * from session where token='{}'".format(item) + elif type(item) == int: + sql = 'select * from session where id={}'.format(item) + else: + raise DatabaseExecption("item as no type int or str. name={}, type={}".format(item, type(item))) + cursor.execute(sql) + session = cursor.fetchone() + retVal = AccessToken(session['id'], self.getUserById(session['user']), session['token'], session['lifetime'], lock_bar=bool(session['lock_bar']),timestamp=session['timestamp'], browser=session['browser'], platform=session['platform']) if session != None else None + return retVal + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) + + def getAccessTokensFromUser(self, user): + try: + cursor = self.db.connection.cursor() + cursor.execute("select * from session where user={}".format(user.id)) + sessions = cursor.fetchall() + retVal = [ + AccessToken(session['id'], self.getUserById(session['user']), session['token'], session['lifetime'], + lock_bar=bool(session['lock_bar']), timestamp=session['timestamp'], browser=session['browser'], platform=session['platform']) for session in sessions] + return retVal + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def getAccessTokens(self): + try: + cursor = self.db.connection.cursor() + cursor.execute("select * from session") + sessions = cursor.fetchall() + retVal = [AccessToken(session['id'], self.getUserById(session['user']), session['token'], session['lifetime'], lock_bar=bool(session['lock_bar']),timestamp=session['timestamp'], browser=session['browser'], platform=session['platform']) for session in sessions] + return retVal + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def createAccessToken(self, user, token, lifetime, timestamp, lock_bar, user_agent=None): + try: + cursor = self.db.connection.cursor() + cursor.execute("insert into session (user, timestamp, lock_bar, token, lifetime, browser, platform) VALUES ({}, '{}', {}, '{}', {}, '{}', '{}')".format(user.id, timestamp, lock_bar, token, lifetime, user_agent.browser if user_agent else 'NULL', user_agent.platform if user_agent else 'NULL')) + self.db.connection.commit() + return self.getAccessToken(token) + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def updateAccessToken(self, accToken): + try: + cursor = self.db.connection.cursor() + cursor.execute("update session set timestamp='{}', lock_bar={}, lifetime={} where id={}".format(accToken.timestamp, accToken.lock_bar, accToken.lifetime, accToken.id)) + self.db.connection.commit() + return self.getAccessToken(accToken.id) + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def deleteAccessToken(self, accToken): + try: + cursor = self.db.connection.cursor() + cursor.execute("delete from session where id={}".format(accToken.id)) + self.db.connection.commit() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) \ No newline at end of file diff --git a/geruecht/controller/databaseController/dbCreditListController.py b/geruecht/controller/databaseController/dbCreditListController.py new file mode 100644 index 0000000..62a3528 --- /dev/null +++ b/geruecht/controller/databaseController/dbCreditListController.py @@ -0,0 +1,73 @@ +import traceback +from datetime import datetime + +from geruecht.exceptions import DatabaseExecption +from geruecht.model.creditList import CreditList +from geruecht.model.user import User + + +class Base: + def getCreditListFromUser(self, user, **kwargs): + try: + if type(user) is User: + if user.uid == 'extern': + return [] + cursor = self.db.connection.cursor() + if 'year' in kwargs: + sql = "select * from creditList where user_id={} and year_date={}".format(user.id if type(user) is User else user, kwargs['year']) + else: + sql = "select * from creditList where user_id={}".format(user.id if type(user) is User else user) + cursor.execute(sql) + data = cursor.fetchall() + if len(data) == 0: + return self.createCreditList(user_id=user.id, year=datetime.now().year) + elif len(data) == 1: + return [CreditList(data[0])] + else: + return [CreditList(value) for value in data] + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + + def createCreditList(self, user_id, year=datetime.now().year): + try: + cursor = self.db.connection.cursor() + cursor.execute("insert into creditList (year_date, user_id) values ({},{})".format(year, user_id)) + self.db.connection.commit() + return self.getCreditListFromUser(user_id) + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + + def updateCreditList(self, creditlist): + try: + cursor = self.db.connection.cursor() + cursor.execute("select * from creditList where user_id={} and year_date={}".format(creditlist.user_id, creditlist.year)) + data = cursor.fetchall() + if len(data) == 0: + self.createCreditList(creditlist.user_id, creditlist.year) + sql = "update creditList set jan_guthaben={}, jan_schulden={},feb_guthaben={}, feb_schulden={}, maer_guthaben={}, maer_schulden={}, apr_guthaben={}, apr_schulden={}, mai_guthaben={}, mai_schulden={}, jun_guthaben={}, jun_schulden={}, jul_guthaben={}, jul_schulden={}, aug_guthaben={}, aug_schulden={},sep_guthaben={}, sep_schulden={},okt_guthaben={}, okt_schulden={}, nov_guthaben={}, nov_schulden={}, dez_guthaben={}, dez_schulden={}, last_schulden={} where year_date={} and user_id={}".format(creditlist.jan_guthaben, creditlist.jan_schulden, + creditlist.feb_guthaben, creditlist.feb_schulden, + creditlist.maer_guthaben, creditlist.maer_schulden, + creditlist.apr_guthaben, creditlist.apr_schulden, + creditlist.mai_guthaben, creditlist.mai_schulden, + creditlist.jun_guthaben, creditlist.jun_schulden, + creditlist.jul_guthaben, creditlist.jul_schulden, + creditlist.aug_guthaben, creditlist.aug_schulden, + creditlist.sep_guthaben, creditlist.sep_schulden, + creditlist.okt_guthaben, creditlist.okt_schulden, + creditlist.nov_guthaben, creditlist.nov_schulden, + creditlist.dez_guthaben, creditlist.dez_schulden, + creditlist.last_schulden, creditlist.year, creditlist.user_id) + print(sql) + cursor = self.db.connection.cursor() + cursor.execute(sql) + self.db.connection.commit() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) \ No newline at end of file diff --git a/geruecht/controller/databaseController/dbJobInviteController.py b/geruecht/controller/databaseController/dbJobInviteController.py new file mode 100644 index 0000000..91d54ad --- /dev/null +++ b/geruecht/controller/databaseController/dbJobInviteController.py @@ -0,0 +1,84 @@ +import traceback + +from geruecht.exceptions import DatabaseExecption + + +class Base: + def getJobInvite(self, from_user, to_user, date, id=None): + try: + cursor = self.db.connection.cursor() + if id: + cursor.execute("select * from job_invites where id={}".format(id)) + else: + cursor.execute("select * from job_invites where from_user={} and to_user={} and on_date='{}'".format(from_user['id'], to_user['id'], date)) + retVal = cursor.fetchone() + retVal['to_user'] = self.getUserById(retVal['to_user']).toJSON() + retVal['from_user'] = self.getUserById(retVal['from_user']).toJSON() + retVal['on_date'] = {'year': retVal['on_date'].year, 'month': retVal['on_date'].month, 'day': retVal['on_date'].day} + return retVal + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def getJobInvitesFromUser(self, from_user, date): + try: + cursor = self.db.connection.cursor() + cursor.execute("select * from job_invites where from_user={} and on_date>='{}'".format(from_user['id'], date)) + retVal = cursor.fetchall() + for item in retVal: + item['from_user'] = from_user + item['to_user'] = self.getUserById(item['to_user']).toJSON() + item['on_date'] = {'year': item['on_date'].year, 'month': item['on_date'].month, 'day': item['on_date'].day} + return retVal + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def getJobInvitesToUser(self, to_user, date): + try: + cursor = self.db.connection.cursor() + cursor.execute("select * from job_invites where to_user={} and on_date>='{}'".format(to_user['id'], date)) + retVal = cursor.fetchall() + for item in retVal: + item['from_user'] = self.getUserById(item['from_user']).toJSON() + item['to_user'] = to_user + item['on_date'] = {'year': item['on_date'].year, 'month': item['on_date'].month, 'day': item['on_date'].day} + return retVal + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def setJobInvite(self, from_user, to_user, date): + try: + cursor = self.db.connection.cursor() + cursor.execute("insert into job_invites (from_user, to_user, on_date) values ({}, {}, '{}')".format(from_user['id'], to_user['id'], date)) + self.db.connection.commit() + return self.getJobInvite(from_user, to_user, date) + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def updateJobInvite(self, jobinvite): + try: + cursor = self.db.connection.cursor() + cursor.execute("update job_invites set watched={} where id={}".format(jobinvite['watched'], jobinvite['id'])) + self.db.connection.commit() + return self.getJobInvite(None, None, None, jobinvite['id']) + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def deleteJobInvite(self, jobinvite): + try: + cursor = self.db.connection.cursor() + cursor.execute("delete from job_invites where id={}".format(jobinvite['id'])) + self.db.connection.commit() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) \ No newline at end of file diff --git a/geruecht/controller/databaseController/dbJobKindController.py b/geruecht/controller/databaseController/dbJobKindController.py new file mode 100644 index 0000000..d131eb3 --- /dev/null +++ b/geruecht/controller/databaseController/dbJobKindController.py @@ -0,0 +1,132 @@ +import traceback + +from geruecht.exceptions import DatabaseExecption + + +class Base: + def getAllJobKinds(self): + try: + cursor = self.db.connection.cursor() + cursor.execute('select * from job_kind') + list = cursor.fetchall() + for item in list: + item['workgroup'] = self.getWorkgroup(item['workgroup']) if item['workgroup'] != None else None + return list + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) + + def getJobKind(self, name): + try: + cursor = self.db.connection.cursor() + if type(name) == str: + sql = "select * from job_kind where name='{}'".format(name) + elif type(name) == int: + sql = 'select * from job_kind where id={}'.format(name) + else: + raise DatabaseExecption("name as no type int or str. name={}, type={}".format(name, type(name))) + cursor.execute(sql) + retVal = cursor.fetchone() + retVal['workgroup'] = self.getWorkgroup(retVal['workgroup']) if retVal['workgroup'] != None else None + return retVal + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) + + def setJobKind(self, name, workgroup_id): + try: + cursor = self.db.connection.cursor() + cursor.execute("insert into job_kind (name, workgroup) values ('{}', {})".format(name, workgroup_id if workgroup_id != None else 'NULL')) + self.db.connection.commit() + return self.getJobKind(name) + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) + + def updateJobKind(self, jobkind): + try: + cursor = self.db.connection.cursor() + cursor.execute("update job_kind set name='{}', workgroup={} where id={}".format(jobkind['name'], jobkind['workgroup']['id'] if jobkind['workgroup'] != None else 'NULL', jobkind['id'])) + self.db.connection.commit() + return self.getJobKind(jobkind['id']) + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) + + def deleteJobKind(self, jobkind): + try: + cursor = self.db.connection.cursor() + cursor.execute("delete from job_kind where id={}".format(jobkind['id'])) + self.db.connection.commit() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) + + def setJobKindDates(self, date, jobkind, maxpersons): + try: + cursor = self.db.connection.cursor() + cursor.execute("insert into job_kind_dates (daydate, job_kind, maxpersons) values ('{}', {}, {})".format(date, jobkind['id'] if jobkind != None else 'NULL', maxpersons)) + self.db.connection.commit() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) + + def updateJobKindDates(self, jobkindDate): + try: + cursor = self.db.connection.cursor() + cursor.execute("update job_kind_dates set job_kind={}, maxpersons='{}' where id={}".format(jobkindDate['job_kind']['id'] if jobkindDate['job_kind'] != None else 'NULL', jobkindDate['maxpersons'], jobkindDate['id'])) + self.db.connection.commit() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went wrong with Database: {}".format(err)) + + def getJobKindDates(self, date): + try: + cursor = self.db.connection.cursor() + cursor.execute("select * from job_kind_dates where daydate='{}'".format(date)) + list = cursor.fetchall() + for item in list: + item['job_kind'] = self.getJobKind(item['job_kind']) if item['job_kind'] != None else None + item['daydate'] = {'year': item['daydate'].year, 'month': item['daydate'].month, 'day': item['daydate'].day} + return list + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) + + def getJobKindDate(self, date, job_kind): + try: + cursor = self.db.connection.cursor() + cursor.execute("select * from job_kind_dates where daydate='{}' and job_kind={}".format(date, job_kind['id'])) + item = cursor.fetchone() + if item: + item['job_kind'] = self.getJobKind(item['job_kind']) if item['job_kind'] != None else None + item['daydate'] = {'year': item['daydate'].year, 'month': item['daydate'].month, 'day': item['daydate'].day} + else: + item = { + 'job_kind': self.getJobKind(1), + 'daydate': {'year': date.year, 'month': date.month, 'day': date.day}, + 'maxpersons': 2 + } + return item + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) + + def deleteJobKindDates(self, jobkinddates): + try: + cursor = self.db.connection.cursor() + cursor.execute("delete from job_kind_dates where id={}".format(jobkinddates['id'])) + self.db.connection.commit() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) \ No newline at end of file diff --git a/geruecht/controller/databaseController/dbJobRequesController.py b/geruecht/controller/databaseController/dbJobRequesController.py new file mode 100644 index 0000000..8f77752 --- /dev/null +++ b/geruecht/controller/databaseController/dbJobRequesController.py @@ -0,0 +1,97 @@ +import traceback + +from geruecht.exceptions import DatabaseExecption + + +class Base: + def getJobRequest(self, from_user, to_user, date, id=None): + try: + cursor = self.db.connection.cursor() + if id: + cursor.execute("select * from job_request where id={}".format(id)) + else: + cursor.execute("select * from job_request where from_user={} and to_user={} and on_date='{}'".format(from_user['id'], to_user['id'], date)) + retVal = cursor.fetchone() + retVal['to_user'] = self.getUserById(retVal['to_user']).toJSON() + retVal['from_user'] = self.getUserById(retVal['from_user']).toJSON() + retVal['on_date'] = {'year': retVal['on_date'].year, 'month': retVal['on_date'].month, 'day': retVal['on_date'].day} + retVal['job_kind'] = self.getJobKind(retVal['job_kind']) + return retVal + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def getJobRequestsFromUser(self, from_user, date): + try: + cursor = self.db.connection.cursor() + cursor.execute("select * from job_request where from_user={} and on_date>='{}'".format(from_user['id'], date)) + retVal = cursor.fetchall() + for item in retVal: + item['from_user'] = from_user + item['to_user'] = self.getUserById(item['to_user']).toJSON() + item['on_date'] = {'year': item['on_date'].year, 'month': item['on_date'].month, 'day': item['on_date'].day} + item['job_kind'] = self.getJobKind(item['job_kind']) + return retVal + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def getJobRequestsToUser(self, to_user, date): + try: + cursor = self.db.connection.cursor() + cursor.execute("select * from job_request where to_user={} and on_date>='{}'".format(to_user['id'], date)) + retVal = cursor.fetchall() + for item in retVal: + item['from_user'] = self.getUserById(item['from_user']).toJSON() + item['to_user'] = to_user + item['on_date'] = {'year': item['on_date'].year, 'month': item['on_date'].month, 'day': item['on_date'].day} + item['job_kind'] = self.getJobKind(item['job_kind']) + return retVal + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def setJobRequest(self, from_user, to_user, date, job_kind): + try: + cursor = self.db.connection.cursor() + cursor.execute("insert into job_request (from_user, to_user, on_date, job_kind) values ({}, {}, '{}', {})".format(from_user['id'], to_user['id'], date, job_kind['id'])) + self.db.connection.commit() + return self.getJobRequest(from_user, to_user, date) + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def updateJobRequest(self, jobrequest): + try: + cursor = self.db.connection.cursor() + cursor.execute("update job_request set watched={}, answered={}, accepted={} where id={}".format(jobrequest['watched'], jobrequest['answered'], jobrequest['accepted'], jobrequest['id'])) + self.db.connection.commit() + return self.getJobRequest(None, None, None, jobrequest['id']) + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def updateAllJobRequest(self, jobrequest): + try: + cursor = self.db.connection.cursor() + cursor.execute("update job_request set answered={} where from_user={} and on_date='{}'".format(jobrequest['answered'], jobrequest['from_user']['id'], jobrequest['on_date'])) + self.db.connection.commit() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def deleteJobRequest(self, jobrequest): + try: + cursor = self.db.connection.cursor() + cursor.execute("delete from job_request where id={}".format(jobrequest['id'])) + self.db.connection.commit() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) \ No newline at end of file diff --git a/geruecht/controller/databaseController/dbPricelistController.py b/geruecht/controller/databaseController/dbPricelistController.py new file mode 100644 index 0000000..2b0c749 --- /dev/null +++ b/geruecht/controller/databaseController/dbPricelistController.py @@ -0,0 +1,128 @@ +import traceback + +from geruecht.exceptions import DatabaseExecption + + +class Base: + def getPriceList(self): + try: + cursor = self.db.connection.cursor() + cursor.execute("select * from pricelist") + return cursor.fetchall() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went wrong with Database: {}".format(err)) + + def getDrinkPrice(self, name): + try: + cursor = self.db.connection.cursor() + if type(name) == str: + sql = "select * from pricelist where name='{}'".format(name) + elif type(name) == int: + sql = 'select * from pricelist where id={}'.format(name) + else: + raise DatabaseExecption("name as no type int or str. name={}, type={}".format(name, type(name))) + cursor.execute(sql) + return cursor.fetchone() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went wrong with Database: {}".format(err)) + + def setDrinkPrice(self, drink): + try: + cursor = self.db.connection.cursor() + cursor.execute( + "insert into pricelist (name, price, price_big, price_club, price_club_big, premium, premium_club, price_extern_club, type) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)", + ( + drink['name'], drink['price'], drink['price_big'], drink['price_club'], drink['price_club_big'], + drink['premium'], drink['premium_club'], drink['price_extern_club'], drink['type'])) + self.db.connection.commit() + return self.getDrinkPrice(str(drink['name'])) + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went wrong with Database: {}".format(err)) + + def updateDrinkPrice(self, drink): + try: + cursor = self.db.connection.cursor() + cursor.execute("update pricelist set name=%s, price=%s, price_big=%s, price_club=%s, price_club_big=%s, premium=%s, premium_club=%s, price_extern_club=%s, type=%s where id=%s", + ( + drink['name'], drink['price'], drink['price_big'], drink['price_club'], drink['price_club_big'], drink['premium'], drink['premium_club'], drink['price_extern_club'], drink['type'], drink['id'] + )) + self.db.connection.commit() + return self.getDrinkPrice(drink['id']) + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went wrong with Database: {}".format(err)) + + def deleteDrink(self, drink): + try: + cursor = self.db.connection.cursor() + cursor.execute("delete from pricelist where id={}".format(drink['id'])) + self.db.connection.commit() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Database: {}".format(err)) + + def getDrinkType(self, name): + try: + cursor = self.db.connection.cursor() + if type(name) == str: + sql = "select * from drink_type where name='{}'".format(name) + elif type(name) == int: + sql = 'select * from drink_type where id={}'.format(name) + else: + raise DatabaseExecption("name as no type int or str. name={}, type={}".format(name, type(name))) + cursor.execute(sql) + return cursor.fetchone() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went wrong with Database: {}".format(err)) + + def setDrinkType(self, name): + try: + cursor = self.db.connection.cursor() + cursor.execute("insert into drink_type (name) values ('{}')".format(name)) + self.db.connection.commit() + return self.getDrinkType(name) + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Database: {}".format(err)) + + def updateDrinkType(self, type): + try: + cursor = self.db.connection.cursor() + cursor.execute("update drink_type set name='{}' where id={}".format(type['name'], type['id'])) + self.db.connection.commit() + return self.getDrinkType(type['id']) + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Database: {}".format(err)) + + def deleteDrinkType(self, type): + try: + cursor = self.db.connection.cursor() + cursor.execute("delete from drink_type where id={}".format(type['id'])) + self.db.connection.commit() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went wrong with Database: {}".format(err)) + + def getAllDrinkTypes(self): + try: + cursor = self.db.connection.cursor() + cursor.execute('select * from drink_type') + return cursor.fetchall() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Database: {}".format(err)) \ No newline at end of file diff --git a/geruecht/controller/databaseController/dbRegistrationController.py b/geruecht/controller/databaseController/dbRegistrationController.py new file mode 100644 index 0000000..39aa2e1 --- /dev/null +++ b/geruecht/controller/databaseController/dbRegistrationController.py @@ -0,0 +1,32 @@ +import traceback +from geruecht.exceptions import DatabaseExecption + +class Base: + def setNewRegistration(self, data): + try: + cursor = self.db.connection.cursor() + if data['entryDate']: + sql = "insert into registration_list (firstname, lastname, clubname, email, keynumber, birthdate, entrydate) VALUES ('{}', '{}', '{}', '{}', {}, '{}', '{}')".format( + data['firstName'], + data['lastName'], + data['clubName'] if data['clubName'] else 'NULL', + data['mail'], + data['keynumber'] if data['keynumber'] else 'NULL', + data['birthDate'], + data['entryDate'] + ) + else: + sql = "insert into registration_list (firstname, lastname, clubname, email, keynumber, birthdate) VALUES ('{}', '{}', '{}', '{}', {}, '{}')".format( + data['firstName'], + data['lastName'], + data['clubName'] if data['clubName'] else 'NULL', + data['mail'], + data['keynumber'] if data['keynumber'] else 'NULL', + data['birthDate'] + ) + cursor.execute(sql) + self.db.connection.commit() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) \ No newline at end of file diff --git a/geruecht/controller/databaseController/dbUserController.py b/geruecht/controller/databaseController/dbUserController.py new file mode 100644 index 0000000..3e419d4 --- /dev/null +++ b/geruecht/controller/databaseController/dbUserController.py @@ -0,0 +1,214 @@ +from geruecht.exceptions import DatabaseExecption, UsernameExistDB +from geruecht.model.user import User +import traceback + +class Base: + def getAllUser(self, extern=False, workgroups=True): + try: + cursor = self.db.connection.cursor() + cursor.execute("select * from user") + data = cursor.fetchall() + + if data: + retVal = [] + for value in data: + if extern and value['uid'] == 'extern': + continue + user = User(value) + creditLists = self.getCreditListFromUser(user) + user.initGeruechte(creditLists) + if workgroups: + user.workgroups = self.getWorkgroupsOfUser(user.id) + retVal.append(user) + return retVal + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def getUser(self, username, workgroups=True): + try: + retVal = None + cursor = self.db.connection.cursor() + cursor.execute("select * from user where uid='{}'".format(username)) + data = cursor.fetchone() + if data: + retVal = User(data) + creditLists = self.getCreditListFromUser(retVal) + retVal.initGeruechte(creditLists) + if workgroups: + retVal.workgroups = self.getWorkgroupsOfUser(retVal.id) + if retVal: + if retVal.uid == username: + return retVal + else: + return None + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def getUserById(self, id, workgroups=True): + try: + retVal = None + cursor = self.db.connection.cursor() + cursor.execute("select * from user where id={}".format(id)) + data = cursor.fetchone() + if data: + retVal = User(data) + creditLists = self.getCreditListFromUser(retVal) + retVal.initGeruechte(creditLists) + if workgroups: + retVal.workgroups = self.getWorkgroupsOfUser(retVal.id) + return retVal + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def _convertGroupToString(self, groups): + retVal = '' + print('groups: {}'.format(groups)) + if groups: + for group in groups: + if len(retVal) != 0: + retVal += ',' + retVal += group + return retVal + + + def insertUser(self, user): + try: + cursor = self.db.connection.cursor() + groups = self._convertGroupToString(user.group) + cursor.execute("insert into user (uid, dn, firstname, lastname, gruppe, lockLimit, locked, autoLock, mail) VALUES ('{}','{}','{}','{}','{}',{},{},{},'{}')".format( + user.uid, user.dn, user.firstname, user.lastname, groups, user.limit, user.locked, user.autoLock, user.mail)) + self.db.connection.commit() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + + def updateUser(self, user): + try: + cursor = self.db.connection.cursor() + groups = self._convertGroupToString(user.group) + sql = "update user set dn='{}', firstname='{}', lastname='{}', gruppe='{}', lockLimit={}, locked={}, autoLock={}, mail='{}' where uid='{}'".format( + user.dn, user.firstname, user.lastname, groups, user.limit, user.locked, user.autoLock, user.mail, user.uid) + print(sql) + cursor.execute(sql) + self.db.connection.commit() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def updateLastSeen(self, user, time): + try: + cursor = self.db.connection.cursor() + sql = "update user set last_seen='{}' where uid='{}'".format( + time, user.uid) + print(sql) + cursor.execute(sql) + self.db.connection.commit() + + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def changeUsername(self, user, newUsername): + try: + cursor= self.db.connection.cursor() + cursor.execute("select * from user where uid='{}'".format(newUsername)) + data = cursor.fetchall() + if data: + raise UsernameExistDB("Username already exists") + else: + cursor.execute("update user set uid='{}' where id={}".format(newUsername, user.id)) + self.db.connection.commit() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def getAllStatus(self): + try: + cursor = self.db.connection.cursor() + cursor.execute('select * from statusgroup') + return cursor.fetchall() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) + + def getStatus(self, name): + try: + cursor = self.db.connection.cursor() + if type(name) == str: + sql = "select * from statusgroup where name='{}'".format(name) + elif type(name) == int: + sql = 'select * from statusgroup where id={}'.format(name) + else: + raise DatabaseExecption("name as no type int or str. name={}, type={}".format(name, type(name))) + cursor.execute(sql) + return cursor.fetchone() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) + + def setStatus(self, name): + try: + cursor = self.db.connection.cursor() + cursor.execute("insert into statusgroup (name) values ('{}')".format(name)) + self.db.connection.commit() + return self.getStatus(name) + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) + + def updateStatus(self, status): + try: + cursor = self.db.connection.cursor() + cursor.execute("update statusgroup set name='{}' where id={}".format(status['name'], status['id'])) + self.db.connection.commit() + return self.getStatus(status['id']) + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) + + def deleteStatus(self, status): + try: + cursor = self.db.connection.cursor() + cursor.execute("delete from statusgroup where id={}".format(status['id'])) + self.db.connection.commit() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) + + def updateStatusOfUser(self, username, status): + try: + cursor = self.db.connection.cursor() + cursor.execute("update user set statusgroup={} where uid='{}'".format(status['id'], username)) + self.db.connection.commit() + return self.getUser(username) + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) + + def updateVotingOfUser(self, username, voting): + try: + cursor = self.db.connection.cursor() + cursor.execute("update user set voting={} where uid='{}'".format(voting, username)) + self.db.connection.commit() + return self.getUser(username) + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) \ No newline at end of file diff --git a/geruecht/controller/databaseController/dbWorkerController.py b/geruecht/controller/databaseController/dbWorkerController.py new file mode 100644 index 0000000..3d7652d --- /dev/null +++ b/geruecht/controller/databaseController/dbWorkerController.py @@ -0,0 +1,81 @@ +import traceback +from datetime import timedelta + +from geruecht.exceptions import DatabaseExecption + + +class Base: + def getWorker(self, user, date): + try: + cursor = self.db.connection.cursor() + cursor.execute("select * from bardienste where user_id={} and startdatetime='{}'".format(user.id, date)) + data = cursor.fetchone() + return {"user": user.toJSON(), "startdatetime": data['startdatetime'], "enddatetime": data['enddatetime'], "start": { "year": data['startdatetime'].year, "month": data['startdatetime'].month, "day": data['startdatetime'].day}, "job_kind": self.getJobKind(data['job_kind']) if data['job_kind'] != None else None} if data else None + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def getWorkers(self, date): + try: + cursor = self.db.connection.cursor() + cursor.execute("select * from bardienste where startdatetime='{}'".format(date)) + data = cursor.fetchall() + retVal = [] + return [{"user": self.getUserById(work['user_id']).toJSON(), "startdatetime": work['startdatetime'], "enddatetime": work['enddatetime'], "start": { "year": work['startdatetime'].year, "month": work['startdatetime'].month, "day": work['startdatetime'].day}, "job_kind": self.getJobKind(work['job_kind']) if work['job_kind'] != None else None} for work in data] + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def getWorkersWithJobKind(self, date, job_kind): + try: + cursor = self.db.connection.cursor() + cursor.execute("select * from bardienste where startdatetime='{}' and job_kind={} {}".format(date, job_kind['id'], "or job_kind='null'" if job_kind['id'] is 1 else '')) + data = cursor.fetchall() + retVal = [] + return [{"user": self.getUserById(work['user_id']).toJSON(), "startdatetime": work['startdatetime'], "enddatetime": work['enddatetime'], "start": { "year": work['startdatetime'].year, "month": work['startdatetime'].month, "day": work['startdatetime'].day}, "job_kind": self.getJobKind(work['job_kind']) if work['job_kind'] != None else None} for work in data] + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def setWorker(self, user, date, job_kind=None): + try: + cursor = self.db.connection.cursor() + cursor.execute("insert into bardienste (user_id, startdatetime, enddatetime, job_kind) values ({},'{}','{}', {})".format(user.id, date, date + timedelta(days=1), job_kind['id'] if job_kind != None else 'NULL')) + self.db.connection.commit() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def changeWorker(self, from_user, to_user, date): + try: + cursor = self.db.connection.cursor() + cursor.execute("update bardienste set user_id={} where user_id={} and startdatetime='{}'".format(to_user['id'], from_user['id'], date)) + self.db.connection.commit() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) + + def deleteAllWorkerWithJobKind(self, date, job_kind): + try: + cursor = self.db.connection.cursor() + cursor.execute("delete from bardienste where startdatetime='{}' and job_kind={}".format(date, job_kind['id'])) + self.db.connection.commit() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went wrong with Database: {}".format(err)) + + def deleteWorker(self, user, date): + try: + cursor = self.db.connection.cursor() + cursor.execute("delete from bardienste where user_id={} and startdatetime='{}'".format(user.id, date)) + self.db.connection.commit() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Datatabase: {}".format(err)) \ No newline at end of file diff --git a/geruecht/controller/databaseController/dbWorkgroupController.py b/geruecht/controller/databaseController/dbWorkgroupController.py new file mode 100644 index 0000000..c67f5d2 --- /dev/null +++ b/geruecht/controller/databaseController/dbWorkgroupController.py @@ -0,0 +1,126 @@ +import traceback + +from geruecht.exceptions import DatabaseExecption + + +class Base: + def getAllWorkgroups(self): + try: + cursor = self.db.connection.cursor() + cursor.execute('select * from workgroup') + list = cursor.fetchall() + for item in list: + if item['boss'] != None: + item['boss']=self.getUserById(item['boss'], workgroups=False).toJSON() + return list + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) + + def getWorkgroup(self, name): + try: + cursor = self.db.connection.cursor() + if type(name) == str: + sql = "select * from workgroup where name='{}'".format(name) + elif type(name) == int: + sql = 'select * from workgroup where id={}'.format(name) + else: + raise DatabaseExecption("name as no type int or str. name={}, type={}".format(name, type(name))) + cursor.execute(sql) + retVal = cursor.fetchone() + retVal['boss'] = self.getUserById(retVal['boss'], workgroups=False).toJSON() if retVal['boss'] != None else None + return retVal + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) + + def setWorkgroup(self, name, boss): + try: + cursor = self.db.connection.cursor() + cursor.execute("insert into workgroup (name, boss) values ('{}', {})".format(name, boss['id'])) + self.db.connection.commit() + return self.getWorkgroup(name) + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) + + def updateWorkgroup(self, workgroup): + try: + cursor = self.db.connection.cursor() + cursor.execute("update workgroup set name='{}', boss={} where id={}".format(workgroup['name'], workgroup['boss']['id'], workgroup['id'])) + self.db.connection.commit() + return self.getWorkgroup(workgroup['id']) + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) + + def deleteWorkgroup(self, workgroup): + try: + cursor = self.db.connection.cursor() + cursor.execute("delete from workgroup where id={}".format(workgroup['id'])) + self.db.connection.commit() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went worng with Databes: {}".format(err)) + + def getWorkgroupsOfUser(self, userid): + try: + cursor = self.db.connection.cursor() + cursor.execute("select * from user_workgroup where user_id={} ".format(userid)) + knots = cursor.fetchall() + retVal = [self.getWorkgroup(knot['workgroup_id']) for knot in knots] + return retVal + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went wrong with Database: {}".format(err)) + + def getUsersOfWorkgroups(self, workgroupid): + try: + cursor = self.db.connection.cursor() + cursor.execute("select * from user_workgroup where workgroup_id={}".format(workgroupid)) + knots = cursor.fetchall() + retVal = [self.getUserById(knot['user_id'], workgroups=False).toJSON() for knot in knots] + return retVal + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went wrong with Database: {}".format(err)) + + def getUserWorkgroup(self, user, workgroup): + try: + cursor = self.db.connection.cursor() + cursor.execute("select * from user_workgroup where workgroup_id={} and user_id={}".format(workgroup['id'], user['id'])) + knot = cursor.fetchone() + retVal = {"workgroup": self.getWorkgroup(workgroup['id']), "user": self.getUserById(user['id'], workgroups=False).toJSON()} + return retVal + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went wrong with Database: {}".format(err)) + + def setUserWorkgroup(self, user, workgroup): + try: + cursor = self.db.connection.cursor() + cursor.execute("insert into user_workgroup (user_id, workgroup_id) VALUES ({}, {})".format(user['id'], workgroup['id'])) + self.db.connection.commit() + return self.getUserWorkgroup(user, workgroup) + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went wrong with Database: {}".format(err)) + + def deleteWorkgroupsOfUser(self, user): + try: + cursor = self.db.connection.cursor() + cursor.execute("delete from user_workgroup where user_id={}".format(user['id'])) + self.db.connection.commit() + except Exception as err: + traceback.print_exc() + self.db.connection.rollback() + raise DatabaseExecption("Something went wrong with Database: {}".format(err)) \ No newline at end of file diff --git a/geruecht/controller/emailController.py b/geruecht/controller/emailController.py new file mode 100644 index 0000000..067a34d --- /dev/null +++ b/geruecht/controller/emailController.py @@ -0,0 +1,119 @@ +import smtplib +from datetime import datetime +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText +from email.header import Header +from geruecht.logger import getDebugLogger +from . import mailConfig + +debug = getDebugLogger() + +class EmailController(): + + def __init__(self): + debug.info("init email controller") + self.smtpServer = mailConfig['URL'] + self.port = mailConfig['port'] + self.user = mailConfig['user'] + self.passwd = mailConfig['passwd'] + self.crypt = mailConfig['crypt'] + self.email = mailConfig['email'] + + debug.debug("smtpServer is {{ {} }}, port is {{ {} }}, user is {{ {} }}, crypt is {{ {} }}, email is {{ {} }}".format(self.smtpServer, self.port, self.user, self.crypt, self.email)) + + def __connect__(self): + debug.info('connect to email server') + if self.crypt == 'SSL': + self.smtp = smtplib.SMTP_SSL(self.smtpServer, self.port) + log = self.smtp.ehlo() + debug.debug("ehlo is {{ {} }}".format(log)) + if self.crypt == 'STARTTLS': + self.smtp = smtplib.SMTP(self.smtpServer, self.port) + log = self.smtp.ehlo() + debug.debug("ehlo is {{ {} }}".format(log)) + log = self.smtp.starttls() + debug.debug("starttles is {{ {} }}".format(log)) + log = self.smtp.login(self.user, self.passwd) + debug.debug("login is {{ {} }}".format(log)) + + def jobTransact(self, user, jobtransact): + debug.info("create email jobtransact {{ {} }}for user {{ {} }}".format(jobtransact, user)) + date = '{}.{}.{}'.format(jobtransact['on_date']['day'], jobtransact['on_date']['month'], jobtransact['on_date']['year']) + from_user = '{} {}'.format(jobtransact['from_user']['firstname'], jobtransact['from_user']['lastname']) + job_kind = jobtransact['job_kind'] + subject = 'Dienstanfrage am {}'.format(date) + text = MIMEText( + "Hallo {} {},\n" + "{} fragt, ob du am {} den Dienst {} übernehmen willst.\nBeantworte die Anfrage im Userportal von Flaschengeist.".format(user.firstname, user.lastname, from_user, date, job_kind['name']), 'plain') + debug.debug("subject is {{ {} }}, text is {{ {} }}".format(subject, text.as_string())) + return (subject, text) + + def jobInvite(self, user, jobtransact): + debug.info("create email jobtransact {{ {} }}for user {{ {} }}".format(jobtransact, user)) + date = '{}.{}.{}'.format(jobtransact['on_date']['day'], jobtransact['on_date']['month'], jobtransact['on_date']['year']) + from_user = '{} {}'.format(jobtransact['from_user']['firstname'], jobtransact['from_user']['lastname']) + subject = 'Diensteinladung am {}'.format(date) + text = MIMEText( + "Hallo {} {},\n" + "{} fragt, ob du am {} mit Dienst haben willst.\nBeantworte die Anfrage im Userportal von Flaschengeist.".format(user.firstname, user.lastname, from_user, date), 'plain') + debug.debug("subject is {{ {} }}, text is {{ {} }}".format(subject, text.as_string())) + return (subject, text) + + def credit(self, user): + debug.info("create email credit for user {{ {} }}".format(user)) + subject = Header('Gerücht, bezahle deine Schulden!', 'utf-8') + sum = user.getGeruecht(datetime.now().year).getSchulden() + if sum < 0: + type = 'Schulden' + add = 'Bezahle diese umgehend an den Finanzer.' + else: + type = 'Guthaben' + add = '' + text = MIMEText( + "Hallo {} {},\nDu hast {} im Wert von {:.2f} €. {}\n\nDiese Nachricht wurde automatisch erstellt.".format( + user.firstname, user.lastname, type, abs(sum) / 100, add), 'plain') + debug.debug("subject is {{ {} }}, text is {{ {} }}".format(subject, text.as_string())) + return (subject, text) + + def passwordReset(self, user, data): + debug.info("create email passwort reset for user {{ {} }}".format(user)) + subject = Header("Password vergessen") + text = MIMEText( + "Hallo {} {},\nDu hast dein Password vergessen!\nDies wurde nun mit Flaschengeist zurückgesetzt.\nDein neues Passwort lautet:\n{}\n\nBitte ändere es sofort in deinem Flaschengeistprolif in https://flaschengeist.wu5.de.".format( + user.firstname, user.lastname, data['password'] + ), 'plain' + ) + debug.debug("subject is {{ {} }}, text is {{ {} }}".format(subject, text.as_string())) + return (subject, text) + + def sendMail(self, user, type='credit', jobtransact=None, **kwargs): + debug.info("send email to user {{ {} }}".format(user)) + try: + if user.mail == 'None' or not user.mail: + debug.warning("user {{ {} }} has no email-address".format(user)) + raise Exception("no valid Email") + msg = MIMEMultipart() + msg['From'] = self.email + msg['To'] = user.mail + + if type == 'credit': + subject, text = self.credit(user) + elif type == 'jobtransact': + subject, text = self.jobTransact(user, jobtransact) + elif type == 'jobinvite': + subject, text = self.jobInvite(user, jobtransact) + elif type == 'passwordReset': + subject, text = self.passwordReset(user, kwargs) + else: + raise Exception("Fail to send Email. No type is set. user={}, type={} , jobtransact={}".format(user, type, jobtransact)) + + msg['Subject'] = subject + msg.attach(text) + + debug.debug("send email {{ {} }} to user {{ {} }}".format(msg.as_string(), user)) + self.__connect__() + self.smtp.sendmail(self.email, user.mail, msg.as_string()) + return {'error': False, 'user': {'userId': user.uid, 'firstname': user.firstname, 'lastname': user.lastname}} + except Exception: + debug.warning("exception in send email", exc_info=True) + return {'error': True, 'user': {'userId': user.uid, 'firstname': user.firstname, 'lastname': user.lastname}} diff --git a/geruecht/controller/ldapController.py b/geruecht/controller/ldapController.py new file mode 100644 index 0000000..da3044e --- /dev/null +++ b/geruecht/controller/ldapController.py @@ -0,0 +1,204 @@ +from geruecht import ldap +from ldap3 import SUBTREE, MODIFY_REPLACE, HASHED_SALTED_MD5 +from ldap3.utils.hashed import hashed +from geruecht.model import MONEY, USER, GASTRO, BAR, VORSTAND, EXTERN +from geruecht.exceptions import PermissionDenied +from . import Singleton +from geruecht.exceptions import UsernameExistLDAP, LDAPExcetpion +from geruecht import ldapConfig +from geruecht.logger import getDebugLogger + +debug = getDebugLogger() + +class LDAPController(metaclass=Singleton): + ''' + Authentification over LDAP. Create Account on-the-fly + ''' + + def __init__(self): + debug.info("init ldap controller") + self.dn = ldapConfig['DN'] + self.ldap = ldap + debug.debug("base dn is {{ {} }}".format(self.dn)) + debug.debug("ldap is {{ {} }}".format(self.ldap)) + + + def login(self, username, password): + debug.info("login user {{ {} }} in ldap") + try: + retVal = self.ldap.authenticate(username, password, 'uid', self.dn) + debug.debug("authentification to ldap is {{ {} }}".format(retVal)) + if not retVal: + debug.debug("authenification is incorrect") + raise PermissionDenied("Invalid Password or Username") + except Exception as err: + debug.warning("exception while login into ldap", exc_info=True) + raise PermissionDenied("Invalid Password or Username. {}".format(err)) + + def bind(self, user, password): + debug.info("bind user {{ {} }} to ldap") + ldap_conn = self.ldap.connect(user.dn, password) + debug.debug("ldap_conn is {{ {} }}".format(ldap_conn)) + return ldap_conn + + def getUserData(self, username): + debug.info("get user data from ldap of user {{ {} }}".format(username)) + try: + debug.debug("search user in ldap") + self.ldap.connection.search('ou=user,{}'.format(self.dn), '(uid={})'.format(username), SUBTREE, attributes=['uid', 'givenName', 'sn', 'mail']) + user = self.ldap.connection.response[0]['attributes'] + debug.debug("user is {{ {} }}".format(user)) + retVal = { + 'dn': self.ldap.connection.response[0]['dn'], + 'firstname': user['givenName'][0], + 'lastname': user['sn'][0], + 'uid': user['uid'][0], + } + if user['mail']: + retVal['mail'] = user['mail'][0] + debug.debug("user is {{ {} }}".format(retVal)) + if retVal['uid'] == username: + return retVal + else: + raise Exception() + except: + debug.warning("exception in get user data from ldap", exc_info=True) + raise PermissionDenied("No User exists with this uid.") + + + def getGroup(self, username): + debug.info("get group from user {{ {} }}".format(username)) + try: + retVal = [] + self.ldap.connection.search('ou=user,{}'.format(self.dn), '(uid={})'.format(username), SUBTREE, attributes=['gidNumber']) + main_group_number = self.ldap.connection.response[0]['attributes']['gidNumber'] + debug.debug("main group number is {{ {} }}".format(main_group_number)) + if main_group_number: + if type(main_group_number) is list: + main_group_number = main_group_number[0] + self.ldap.connection.search('ou=group,{}'.format(self.dn), '(gidNumber={})'.format(main_group_number), attributes=['cn']) + group_name = self.ldap.connection.response[0]['attributes']['cn'][0] + debug.debug("group name is {{ {} }}".format(group_name)) + if group_name == 'ldap-user': + retVal.append(USER) + if group_name == 'extern': + retVal.append(EXTERN) + + self.ldap.connection.search('ou=group,{}'.format(self.dn), '(memberUID={})'.format(username), SUBTREE, attributes=['cn']) + groups_data = self.ldap.connection.response + debug.debug("groups number is {{ {} }}".format(groups_data)) + for data in groups_data: + group_name = data['attributes']['cn'][0] + debug.debug("group name is {{ {} }}".format(group_name)) + if group_name == 'finanzer': + retVal.append(MONEY) + elif group_name == 'gastro': + retVal.append(GASTRO) + elif group_name == 'bar': + retVal.append(BAR) + elif group_name == 'vorstand': + retVal.append(VORSTAND) + elif group_name == 'ldap-user': + retVal.append(USER) + debug.debug("groups are {{ {} }}".format(retVal)) + return retVal + except Exception as err: + debug.warning("exception in get groups from ldap", exc_info=True) + raise LDAPExcetpion(str(err)) + + def __isUserInList(self, list, username): + help_list = [] + for user in list: + help_list.append(user['username']) + if username in help_list: + return True + return False + + def getAllUser(self): + debug.info("get all users from ldap") + retVal = [] + self.ldap.connection.search('ou=user,{}'.format(self.dn), '(uid=*)', SUBTREE, attributes=['uid', 'givenName', 'sn', 'mail']) + data = self.ldap.connection.response + debug.debug("data is {{ {} }}".format(data)) + for user in data: + if 'uid' in user['attributes']: + username = user['attributes']['uid'][0] + firstname = user['attributes']['givenName'][0] + lastname = user['attributes']['sn'][0] + retVal.append({'username': username, 'firstname': firstname, 'lastname': lastname}) + debug.debug("users are {{ {} }}".format(retVal)) + return retVal + + def searchUser(self, searchString): + + name = searchString.split(" ") + + for i in range(len(name)): + name[i] = "*"+name[i]+"*" + + + print(name) + + name_result = [] + + if len(name) == 1: + if name[0] == "**": + self.ldap.connection.search('ou=user,{}'.format(self.dn), '(uid=*)', SUBTREE, + attributes=['uid', 'givenName', 'sn']) + name_result.append(self.ldap.connection.response) + else: + self.ldap.connection.search('ou=user,{}'.format(self.dn), '(givenName={})'.format(name[0]), SUBTREE, attributes=['uid', 'givenName', 'sn', 'mail']) + name_result.append(self.ldap.connection.response) + self.ldap.connection.search('ou=user,{}'.format(self.dn), '(sn={})'.format(name[0]), SUBTREE, attributes=['uid', 'givenName', 'sn', 'mail']) + name_result.append(self.ldap.connection.response) + else: + self.ldap.connection.search('ou=user,{}'.format(self.dn), '(givenName={})'.format(name[1]), SUBTREE, attributes=['uid', 'givenName', 'sn']) + name_result.append(self.ldap.connection.response) + self.ldap.connection.search('ou=user,{}'.format(self.dn), '(sn={})'.format(name[1]), SUBTREE, attributes=['uid', 'givenName', 'sn', 'mail']) + name_result.append(self.ldap.connection.response) + retVal = [] + + for names in name_result: + for user in names: + if 'uid' in user['attributes']: + username = user['attributes']['uid'][0] + if not self.__isUserInList(retVal, username): + firstname = user['attributes']['givenName'][0] + lastname = user['attributes']['sn'][0] + retVal.append({'username': username, 'firstname': firstname, 'lastname': lastname}) + + return retVal + + def modifyUser(self, user, conn, attributes): + debug.info("modify ldap data from user {{ {} }} with attributes (can't show because here can be a password)".format(user)) + try: + if 'username' in attributes: + debug.debug("change username") + conn.search('ou=user,{}'.format(self.dn), '(uid={})'.format(attributes['username'])) + if conn.entries: + debug.warning("username already exists", exc_info=True) + raise UsernameExistLDAP("Username already exists in LDAP") + #create modifyer + mody = {} + if 'username' in attributes: + mody['uid'] = [(MODIFY_REPLACE, [attributes['username']])] + if 'firstname' in attributes: + mody['givenName'] = [(MODIFY_REPLACE, [attributes['firstname']])] + if 'lastname' in attributes: + mody['sn'] = [(MODIFY_REPLACE, [attributes['lastname']])] + if 'mail' in attributes: + mody['mail'] = [(MODIFY_REPLACE, [attributes['mail']])] + if 'password' in attributes: + salted_password = hashed(HASHED_SALTED_MD5, attributes['password']) + mody['userPassword'] = [(MODIFY_REPLACE, [salted_password])] + debug.debug("modyfier are (can't show because here can be a password)") + conn.modify(user.dn, mody) + except Exception as err: + debug.warning("exception in modify user data from ldap", exc_info=True) + raise LDAPExcetpion("Something went wrong in LDAP: {}".format(err)) + + + +if __name__ == '__main__': + a = LDAPController() + a.getUserData('jhille') diff --git a/geruecht/controller/mainController/__init__.py b/geruecht/controller/mainController/__init__.py new file mode 100644 index 0000000..ae3f73a --- /dev/null +++ b/geruecht/controller/mainController/__init__.py @@ -0,0 +1,152 @@ +from .. import Singleton, mailConfig +import geruecht.controller.databaseController as dc +import geruecht.controller.ldapController as lc +import geruecht.controller.emailController as ec +from geruecht.model.user import User +from datetime import datetime, timedelta +from geruecht.logger import getDebugLogger +from ..mainController import mainJobKindController, mainCreditListController, mainPricelistController, mainUserController, mainWorkerController, mainWorkgroupController, mainJobInviteController, mainJobRequestController, mainRegistrationController, mainPasswordReset + +db = dc.DatabaseController() +ldap = lc.LDAPController() +emailController = ec.EmailController() + +debug = getDebugLogger() + + +class MainController(mainJobKindController.Base, + mainCreditListController.Base, + mainPricelistController.Base, + mainUserController.Base, + mainWorkerController.Base, + mainWorkgroupController.Base, + mainJobInviteController.Base, + mainJobRequestController.Base, + mainRegistrationController.Base, + mainPasswordReset.Base, + metaclass=Singleton): + + def __init__(self): + debug.debug("init UserController") + pass + + def setLockedDay(self, date, locked, hard=False): + debug.info( + "set day locked on {{ {} }} with state {{ {} }}".format(date, locked)) + retVal = db.setLockedDay(date.date(), locked, hard) + debug.debug("seted day locked is {{ {} }}".format(retVal)) + return retVal + + def getLockedDays(self, from_date, to_date): + debug.info("get locked days from {{ {} }} to {{ {} }}".format( + from_date.date(), to_date.date())) + oneDay = timedelta(1) + delta = to_date.date() - from_date.date() + retVal = [] + startdate = from_date - oneDay + for _ in range(delta.days + 1): + startdate += oneDay + lockday = self.getLockedDay(startdate) + retVal.append(lockday) + debug.debug("lock days are {{ {} }}".format(retVal)) + return retVal + + def getLockedDaysFromList(self, date_list): + debug.info("get locked days from list {{ {} }}".format(date_list)) + retVal = [] + for on_date in date_list: + day = datetime(on_date['on_date']['year'], on_date['on_date']['month'], on_date['on_date']['day'], 12) + retVal.append(self.getLockedDay(day)) + return retVal + + def getLockedDay(self, date): + debug.info("get locked day on {{ {} }}".format(date)) + now = datetime.now() + debug.debug("now is {{ {} }}".format(now)) + oldMonth = False + debug.debug("check if date old month or current month") + for i in range(1, 8): + if datetime(now.year, now.month, i).weekday() == 2: + if now.day < i: + oldMonth = True + break + debug.debug("oldMonth is {{ {} }}".format(oldMonth)) + lockedYear = now.year + lockedMonth = now.month if now.month < now.month else now.month - \ + 1 if oldMonth else now.month + endDay = 1 + debug.debug("calculate end day of month") + lockedYear = lockedYear if lockedMonth != 12 else (lockedYear + 1) + lockedMonth = (lockedMonth + 1) if lockedMonth != 12 else 1 + for i in range(1, 8): + nextMonth = datetime(lockedYear, lockedMonth, i) + if nextMonth.weekday() == 2: + endDay = i + break + + monthLockedEndDate = datetime( + lockedYear, lockedMonth, endDay) - timedelta(1) + debug.debug("get lock day from database") + retVal = db.getLockedDay(date.date()) + if not retVal: + debug.debug( + "lock day not exists, retVal is {{ {} }}".format(retVal)) + if date.date() <= monthLockedEndDate.date(): + debug.debug("lock day {{ {} }}".format(date.date())) + self.setLockedDay(date, True) + retVal = db.getLockedDay(date.date()) + else: + retVal = {"daydate": date.date(), "locked": False} + debug.debug("locked day is {{ {} }}".format(retVal)) + return retVal + + def __updateDataFromLDAP(self, user): + debug.info("update data from ldap for user {{ {} }}".format(user)) + groups = ldap.getGroup(user.uid) + debug.debug("ldap gorups are {{ {} }}".format(groups)) + user_data = ldap.getUserData(user.uid) + debug.debug("ldap data is {{ {} }}".format(user_data)) + user_data['gruppe'] = groups + user_data['group'] = groups + user.updateData(user_data) + db.updateUser(user) + + def checkBarUser(self, user): + debug.info("check if user {{ {} }} is baruser") + date = datetime.now() + zero = date.replace(hour=0, minute=0, second=0, microsecond=0) + end = zero + timedelta(hours=12) + startdatetime = date.replace( + hour=12, minute=0, second=0, microsecond=0) + if date > zero and end > date: + startdatetime = startdatetime - timedelta(days=1) + enddatetime = startdatetime + timedelta(days=1) + debug.debug("startdatetime is {{ {} }} and enddatetime is {{ {} }}".format( + startdatetime, end)) + result = False + if date >= startdatetime and date < enddatetime: + result = db.getWorker(user, startdatetime) + debug.debug("worker is {{ {} }}".format(result)) + return True if result else False + + def sendMail(self, username): + debug.info("send mail to user {{ {} }}".format(username)) + if type(username) == User: + user = username + if type(username) == str: + user = db.getUser(username) + retVal = emailController.sendMail(user) + debug.debug("send mail is {{ {} }}".format(retVal)) + return retVal + + def sendAllMail(self): + debug.info("send mail to all user") + retVal = [] + users = db.getAllUser() + debug.debug("users are {{ {} }}".format(users)) + for user in users: + retVal.append(self.sendMail(user)) + debug.debug("send mails are {{ {} }}".format(retVal)) + return retVal + + diff --git a/geruecht/controller/mainController/mainCreditListController.py b/geruecht/controller/mainController/mainCreditListController.py new file mode 100644 index 0000000..7e6f19f --- /dev/null +++ b/geruecht/controller/mainController/mainCreditListController.py @@ -0,0 +1,86 @@ +from datetime import datetime + +import geruecht.controller.databaseController as dc +import geruecht.controller.emailController as ec +from geruecht.logger import getDebugLogger + +db = dc.DatabaseController() +emailController = ec.EmailController() +debug = getDebugLogger() + +class Base: + def autoLock(self, user): + debug.info("start autolock of user {{ {} }}".format(user)) + if user.autoLock: + debug.debug("autolock is active") + credit = user.getGeruecht(year=datetime.now().year).getSchulden() + limit = -1*user.limit + if credit <= limit: + debug.debug( + "credit {{ {} }} is more than user limit {{ {} }}".format(credit, limit)) + debug.debug("lock user") + user.updateData({'locked': True}) + debug.debug("send mail to user") + emailController.sendMail(user) + else: + debug.debug( + "cretid {{ {} }} is less than user limit {{ {} }}".format(credit, limit)) + debug.debug("unlock user") + user.updateData({'locked': False}) + db.updateUser(user) + + def addAmount(self, username, amount, year, month, finanzer=False, bar=False): + debug.info("add amount {{ {} }} to user {{ {} }} no month {{ {} }}, year {{ {} }}".format( + amount, username, month, year)) + user = self.getUser(username) + debug.debug("user is {{ {} }}".format(user)) + if user.uid == 'extern': + debug.debug("user is extern user, so exit add amount") + return + if not user.locked or finanzer: + debug.debug("user is not locked {{ {} }} or is finanzer execution {{ {} }}".format( + user.locked, finanzer)) + user.addAmount(amount, year=year, month=month) + if bar: + user.last_seen = datetime.now() + db.updateLastSeen(user, user.last_seen) + creditLists = user.updateGeruecht() + debug.debug("creditList is {{ {} }}".format(creditLists)) + for creditList in creditLists: + debug.debug("update creditlist {{ {} }}".format(creditList)) + db.updateCreditList(creditList) + debug.debug("do autolock") + self.autoLock(user) + retVal = user.getGeruecht(year) + debug.debug("updated creditlists is {{ {} }}".format(retVal)) + return retVal + + def addCredit(self, username, credit, year, month): + debug.info("add credit {{ {} }} to user {{ {} }} on month {{ {} }}, year {{ {} }}".format( + credit, username, month, year)) + user = self.getUser(username) + debug.debug("user is {{ {} }}".format(user)) + if user.uid == 'extern': + debug.debug("user is extern user, so exit add credit") + return + user.addCredit(credit, year=year, month=month) + creditLists = user.updateGeruecht() + debug.debug("creditlists are {{ {} }}".format(creditLists)) + for creditList in creditLists: + debug.debug("update creditlist {{ {} }}".format(creditList)) + db.updateCreditList(creditList) + debug.debug("do autolock") + self.autoLock(user) + retVal = user.getGeruecht(year) + debug.debug("updated creditlists are {{ {} }}".format(retVal)) + return retVal + + def __updateGeruechte(self, user): + debug.debug("update creditlists") + user.getGeruecht(datetime.now().year) + creditLists = user.updateGeruecht() + debug.debug("creditlists are {{ {} }}".format(creditLists)) + if user.getGeruecht(datetime.now().year).getSchulden() != 0: + for creditList in creditLists: + debug.debug("update creditlist {{ {} }}".format(creditList)) + db.updateCreditList(creditList) \ No newline at end of file diff --git a/geruecht/controller/mainController/mainJobInviteController.py b/geruecht/controller/mainController/mainJobInviteController.py new file mode 100644 index 0000000..ed8e50c --- /dev/null +++ b/geruecht/controller/mainController/mainJobInviteController.py @@ -0,0 +1,42 @@ +from datetime import date + +import geruecht.controller.databaseController as dc +import geruecht.controller.emailController as ec +from geruecht import getDebugLogger + +db = dc.DatabaseController() +debug = getDebugLogger() +emailController = ec.EmailController() + +class Base: + def getJobInvites(self, from_user, to_user, date): + debug.info("get JobInvites from_user {{ {} }} to_user {{ {} }} on date {{ {} }}".format(from_user, to_user, date)) + if from_user is None: + retVal = db.getJobInvitesToUser(to_user, date) + elif to_user is None: + retVal = db.getJobInvitesFromUser(from_user, date) + else: + raise Exception("from_user {{ {} }} and to_user {{ {} }} are None".format(from_user, to_user)) + return retVal + + def setJobInvites(self, data): + debug.info("set new JobInvites data {{ {} }}".format(data)) + retVal = [] + for jobInvite in data: + from_user = jobInvite['from_user'] + to_user = jobInvite['to_user'] + on_date = date(jobInvite['date']['year'], jobInvite['date']['month'], jobInvite['date']['day']) + debug.info("set new JobInvite from_user {{ {} }}, to_user {{ {} }}, on_date {{ {} }}") + setJobInvite = db.setJobInvite(from_user, to_user, on_date) + retVal.append(setJobInvite) + emailController.sendMail(db.getUserById(to_user['id'], False), type='jobinvite', jobtransact=setJobInvite) + debug.debug("seted JobInvites are {{ {} }}".format(retVal)) + return retVal + + def updateJobInvites(self, data): + debug.info("update JobInvites data {{ {} }}".format(data)) + return db.updateJobInvite(data) + + def deleteJobInvite(self, jobInvite): + debug.info("delete JobInvite {{ {} }}".format(jobInvite)) + db.deleteJobInvite(jobInvite) \ No newline at end of file diff --git a/geruecht/controller/mainController/mainJobKindController.py b/geruecht/controller/mainController/mainJobKindController.py new file mode 100644 index 0000000..3eb67f0 --- /dev/null +++ b/geruecht/controller/mainController/mainJobKindController.py @@ -0,0 +1,90 @@ +from datetime import date, timedelta, datetime, time +import geruecht.controller.databaseController as dc +from geruecht.logger import getDebugLogger + +db = dc.DatabaseController() +debug = getDebugLogger() + +class Base: + def getAllJobKinds(self): + debug.info("get all jobkinds") + retVal = db.getAllJobKinds() + debug.debug("jobkinds are {{ {} }}".format(retVal)) + return retVal + + def getJobKind(self, name): + debug.info("get jobkinds {{ {} }}".format(name)) + retVal = db.getJobKind(name) + debug.debug("jobkind is {{ {} }} is {{ {} }}".format(name, retVal)) + return retVal + + def setJobKind(self, name, workgroup=None): + debug.info("set jobkind {{ {} }} ".format(name)) + retVal = db.setJobKind(name, workgroup) + debug.debug( + "seted jobkind {{ {} }} is {{ {} }}".format(name, retVal)) + return retVal + + def deleteJobKind(self, jobkind): + debug.info("delete jobkind {{ {} }}".format(jobkind)) + db.deleteJobKind(jobkind) + + def updateJobKind(self, jobkind): + debug.info("update workgroup {{ {} }}".format(jobkind)) + retVal = db.updateJobKind(jobkind) + debug.debug("updated jobkind is {{ {} }}".format(retVal)) + return retVal + + def getJobKindDates(self, date): + debug.info("get jobkinddates on {{ {} }}".format(date)) + retVal = db.getJobKindDates(date) + debug.debug("jobkinddates are {{ {} }}".format(retVal)) + return retVal + + def updateJobKindDates(self, jobkindDate): + debug.info("update jobkinddate {{ {} }}".format(jobkindDate)) + retVal = db.updateJobKindDates(jobkindDate) + debug.debug("updated jobkind is {{ {} }}".format(retVal)) + return retVal + + def deleteJobKindDates(self, jobkinddates): + debug.info("delete jobkinddates {{ {} }}".format(jobkinddates)) + db.deleteJobKindDates(jobkinddates) + + def setJobKindDates(self, datum, jobkind, maxpersons): + debug.info("set jobkinddates with {{ {}, {}, {}, }}".format(datum, jobkind, maxpersons)) + retVal = db.setJobKindDates(datum, jobkind, maxpersons) + debug.debug("seted jobkinddates is {{ {} }}".format(retVal)) + return retVal + + def controllJobKindDates(self, jobkinddates): + debug.info("controll jobkinddates {{ {} }}".format(jobkinddates)) + datum = None + for jobkinddate in jobkinddates: + datum = date(jobkinddate['daydate']['year'], jobkinddate['daydate']['month'], jobkinddate['daydate']['day']) + if jobkinddate['id'] == -1: + if jobkinddate['job_kind']: + self.setJobKindDates(datum, jobkinddate['job_kind'], jobkinddate['maxpersons']) + if jobkinddate['id'] == 0: + jobkinddate['id'] = jobkinddate['backupid'] + db.deleteAllWorkerWithJobKind(datetime.combine(datum, time(12)), jobkinddate['job_kind']) + self.deleteJobKindDates(jobkinddate) + if jobkinddate['id'] >= 1: + self.updateJobKindDates(jobkinddate) + retVal = self.getJobKindDates(datum) if datum != None else [] + debug.debug("controlled jobkinddates {{ {} }}".format(retVal)) + return retVal + + def getJobKindDatesFromTo(self, from_date, to_date): + debug.info("get locked days from {{ {} }} to {{ {} }}".format( + from_date.date(), to_date.date())) + oneDay = timedelta(1) + delta = to_date.date() - from_date.date() + retVal = [] + startdate = from_date - oneDay + for _ in range(delta.days + 1): + startdate += oneDay + jobkinddate = self.getJobKindDates(startdate) + retVal.append(jobkinddate) + debug.debug("lock days are {{ {} }}".format(retVal)) + return retVal \ No newline at end of file diff --git a/geruecht/controller/mainController/mainJobRequestController.py b/geruecht/controller/mainController/mainJobRequestController.py new file mode 100644 index 0000000..e31845e --- /dev/null +++ b/geruecht/controller/mainController/mainJobRequestController.py @@ -0,0 +1,46 @@ +from datetime import date, time, datetime +import geruecht.controller.emailController as ec +import geruecht.controller.databaseController as dc +from geruecht import getDebugLogger + +db = dc.DatabaseController() +debug = getDebugLogger() +emailController = ec.EmailController() + +class Base: + def getJobRequests(self, from_user, to_user, date): + debug.info("get JobRequests from_user {{ {} }} to_user {{ {} }} on date {{ {} }}".format(from_user, to_user, date)) + if from_user is None: + retVal = db.getJobRequestsToUser(to_user, date) + elif to_user is None: + retVal = db.getJobRequestsFromUser(from_user, date) + else: + raise Exception("from_user {{ {} }} and to_user {{ {} }} are None".format(from_user, to_user)) + return retVal + + def setJobRequests(self, data): + debug.info("set new JobRequests data {{ {} }}".format(data)) + retVal = [] + for jobRequest in data: + from_user = jobRequest['from_user'] + to_user = jobRequest['to_user'] + on_date = date(jobRequest['date']['year'], jobRequest['date']['month'], jobRequest['date']['day']) + job_kind = jobRequest['job_kind'] + debug.info("set new JobRequest from_user {{ {} }}, to_user {{ {} }}, on_date {{ {} }}") + setJobRequest = db.setJobRequest(from_user, to_user, on_date, job_kind) + retVal.append(setJobRequest) + emailController.sendMail(db.getUserById(to_user['id']), type='jobtransact', jobtransact=setJobRequest) + + debug.debug("seted JobRequests are {{ {} }}".format(retVal)) + return retVal + + def updateJobRequests(self, data): + debug.info("update JobRequest data {{ {} }}".format(data)) + if data['accepted']: + self.changeWorker(data['from_user'], data['to_user'], datetime.combine(data['on_date'], time(12))) + db.updateAllJobRequest(data) + return db.updateJobRequest(data) + + def deleteJobRequest(self, jobRequest): + debug.info("delete JobRequest {{ {} }}".format(jobRequest)) + db.deleteJobRequest(jobRequest) \ No newline at end of file diff --git a/geruecht/controller/mainController/mainPasswordReset.py b/geruecht/controller/mainController/mainPasswordReset.py new file mode 100644 index 0000000..8cc031d --- /dev/null +++ b/geruecht/controller/mainController/mainPasswordReset.py @@ -0,0 +1,39 @@ +from geruecht import ldap, ldapConfig, getDebugLogger +import geruecht.controller.emailController as ec +from ldap3.utils.hashed import hashed +from ldap3 import HASHED_SALTED_MD5, MODIFY_REPLACE +import string +import random + +emailController = ec.EmailController() +debug = getDebugLogger() + +def randomString(stringLength=8): + letters = string.ascii_letters + string.digits + return ''.join(random.choice(letters) for i in range(stringLength)) + +class Base: + def resetPassword(self, data): + debug.info("forgot password {{ {} }}".format(data)) + adminConn = ldap.connect(ldapConfig['ADMIN_DN'], ldapConfig['ADMIN_SECRET']) + if 'username' in data: + search = 'uid={}'.format(data['username'].lower()) + elif 'mail' in data: + search = 'mail={}'.format(data['mail'].lower()) + else: + debug.error("username or mail not set") + raise Exception('username or mail not set') + adminConn.search(ldapConfig['DN'], '(&(objectClass=person)({}))'.format(search), + attributes=['cn', 'sn', 'givenName', 'uid', 'mail']) + for user in adminConn.response: + user_dn = user['dn'] + uid = user['attributes']['uid'][0] + mail = user['attributes']['mail'][0] + mody = {} + password = randomString() + salted_password = hashed(HASHED_SALTED_MD5, password) + mody['userPassword'] = [(MODIFY_REPLACE, [salted_password])] + debug.info("reset password for {{ {} }}".format(user_dn)) + adminConn.modify(user_dn, mody) + emailController.sendMail(self.getUser(uid), type='passwordReset', password=password) + return mail \ No newline at end of file diff --git a/geruecht/controller/mainController/mainPricelistController.py b/geruecht/controller/mainController/mainPricelistController.py new file mode 100644 index 0000000..06cec00 --- /dev/null +++ b/geruecht/controller/mainController/mainPricelistController.py @@ -0,0 +1,50 @@ +import geruecht.controller.databaseController as dc +from geruecht.logger import getDebugLogger + +db = dc.DatabaseController() +debug = getDebugLogger() + +class Base: + def deleteDrinkType(self, type): + debug.info("delete drink type {{ {} }}".format(type)) + db.deleteDrinkType(type) + + def updateDrinkType(self, type): + debug.info("update drink type {{ {} }}".format(type)) + retVal = db.updateDrinkType(type) + debug.debug("updated drink type is {{ {} }}".format(retVal)) + return retVal + + def setDrinkType(self, type): + debug.info("set drink type {{ {} }}".format(type)) + retVal = db.setDrinkType(type) + debug.debug("seted drink type is {{ {} }}".format(retVal)) + return retVal + + def deletDrinkPrice(self, drink): + debug.info("delete drink {{ {} }}".format(drink)) + db.deleteDrink(drink) + + def setDrinkPrice(self, drink): + debug.info("set drink {{ {} }}".format(drink)) + retVal = db.setDrinkPrice(drink) + debug.debug("seted drink is {{ {} }}".format(retVal)) + return retVal + + def updateDrinkPrice(self, drink): + debug.info("update drink {{ {} }}".format(drink)) + retVal = db.updateDrinkPrice(drink) + debug.debug("updated drink is {{ {} }}".format(retVal)) + return retVal + + def getAllDrinkTypes(self): + debug.info("get all drink types") + retVal = db.getAllDrinkTypes() + debug.debug("all drink types are {{ {} }}".format(retVal)) + return retVal + + def getPricelist(self): + debug.info("get all drinks") + list = db.getPriceList() + debug.debug("all drinks are {{ {} }}".format(list)) + return list \ No newline at end of file diff --git a/geruecht/controller/mainController/mainRegistrationController.py b/geruecht/controller/mainController/mainRegistrationController.py new file mode 100644 index 0000000..a32893f --- /dev/null +++ b/geruecht/controller/mainController/mainRegistrationController.py @@ -0,0 +1,14 @@ +from datetime import date + +import geruecht.controller.databaseController as dc +from geruecht.logger import getDebugLogger + +db = dc.DatabaseController() +debug = getDebugLogger() + +class Base: + def setNewRegistration(self, data): + debug.info("set new registration {{ {} }}".format(data)) + data['birthDate'] = date(int(data['birthDate']['year']), int(data['birthDate']['month']), int(data['birthDate']['day'])) + data['entryDate'] = date(int(data['entryDate']['year']), int(data['entryDate']['month']), int(data['entryDate']['day'])) if data['entryDate'] else None + db.setNewRegistration(data) \ No newline at end of file diff --git a/geruecht/controller/mainController/mainUserController.py b/geruecht/controller/mainController/mainUserController.py new file mode 100644 index 0000000..135663d --- /dev/null +++ b/geruecht/controller/mainController/mainUserController.py @@ -0,0 +1,179 @@ +from ldap3.core.exceptions import LDAPPasswordIsMandatoryError, LDAPBindError + +from geruecht.exceptions import UsernameExistLDAP, LDAPExcetpion, PermissionDenied +import geruecht.controller.databaseController as dc +import geruecht.controller.ldapController as lc +from geruecht.logger import getDebugLogger +from geruecht.model.user import User + +db = dc.DatabaseController() +ldap = lc.LDAPController() +debug = getDebugLogger() + +class Base: + def getAllStatus(self): + debug.info("get all status for user") + retVal = db.getAllStatus() + debug.debug("status are {{ {} }}".format(retVal)) + return retVal + + def getStatus(self, name): + debug.info("get status of user {{ {} }}".format(name)) + retVal = db.getStatus(name) + debug.debug("status of user {{ {} }} is {{ {} }}".format(name, retVal)) + return retVal + + def setStatus(self, name): + debug.info("set status of user {{ {} }}".format(name)) + retVal = db.setStatus(name) + debug.debug( + "settet status of user {{ {} }} is {{ {} }}".format(name, retVal)) + return retVal + + def deleteStatus(self, status): + debug.info("delete status {{ {} }}".format(status)) + db.deleteStatus(status) + + def updateStatus(self, status): + debug.info("update status {{ {} }}".format(status)) + retVal = db.updateStatus(status) + debug.debug("updated status is {{ {} }}".format(retVal)) + return retVal + + def updateStatusOfUser(self, username, status): + debug.info("update status {{ {} }} of user {{ {} }}".format( + status, username)) + retVal = db.updateStatusOfUser(username, status) + debug.debug( + "updatet status of user {{ {} }} is {{ {} }}".format(username, retVal)) + return retVal + + def updateVotingOfUser(self, username, voting): + debug.info("update voting {{ {} }} of user {{ {} }}".format( + voting, username)) + retVal = db.updateVotingOfUser(username, voting) + debug.debug( + "updatet voting of user {{ {} }} is {{ {} }}".format(username, retVal)) + return retVal + + def lockUser(self, username, locked): + debug.info("lock user {{ {} }} for credit with status {{ {} }}".format( + username, locked)) + user = self.getUser(username) + debug.debug("user is {{ {} }}".format(user)) + user.updateData({'locked': locked}) + db.updateUser(user) + retVal = self.getUser(username) + debug.debug("locked user is {{ {} }}".format(retVal)) + return retVal + + def updateConfig(self, username, data): + debug.info( + "update config of user {{ {} }} with config {{ {} }}".format(username, data)) + user = self.getUser(username) + debug.debug("user is {{ {} }}".format(user)) + user.updateData(data) + db.updateUser(user) + retVal = self.getUser(username) + debug.debug("updated config of user is {{ {} }}".format(retVal)) + return retVal + + def syncLdap(self): + debug.info('sync Users from Ldap') + ldap_users = ldap.getAllUser() + for user in ldap_users: + self.getUser(user['username']) + + def getAllUsersfromDB(self, extern=True): + debug.info("get all users from database") + if (len(ldap.getAllUser()) != len(db.getAllUser())): + self.syncLdap() + users = db.getAllUser() + debug.debug("users are {{ {} }}".format(users)) + for user in users: + try: + debug.debug("update data from ldap") + self.__updateDataFromLDAP(user) + except: + pass + debug.debug("update creditlists") + self.__updateGeruechte(user) + retVal = db.getAllUser(extern=extern) + debug.debug("all users are {{ {} }}".format(retVal)) + return retVal + + def getUser(self, username): + debug.info("get user {{ {} }}".format(username)) + user = db.getUser(username) + debug.debug("user is {{ {} }}".format(user)) + groups = ldap.getGroup(username) + debug.debug("groups are {{ {} }}".format(groups)) + user_data = ldap.getUserData(username) + debug.debug("user data from ldap is {{ {} }}".format(user_data)) + user_data['gruppe'] = groups + user_data['group'] = groups + if user is None: + debug.debug("user not exists in database -> insert into database") + user = User(user_data) + db.insertUser(user) + else: + debug.debug("update database with user") + user.updateData(user_data) + db.updateUser(user) + user = db.getUser(username) + self.__updateGeruechte(user) + debug.debug("user is {{ {} }}".format(user)) + return user + + def modifyUser(self, user, attributes, password): + debug.info("modify user {{ {} }} with attributes (can't show because here can be a password)".format( + user)) + + try: + ldap_conn = ldap.bind(user, password) + if attributes: + if 'username' in attributes: + debug.debug("change username, so change first in database") + db.changeUsername(user, attributes['username']) + ldap.modifyUser(user, ldap_conn, attributes) + if 'username' in attributes: + retVal = self.getUser(attributes['username']) + debug.debug("user is {{ {} }}".format(retVal)) + return retVal + else: + retVal = self.getUser(user.uid) + debug.debug("user is {{ {} }}".format(retVal)) + return retVal + return self.getUser(user.uid) + + except UsernameExistLDAP as err: + debug.debug( + "username exists on ldap, rechange username on database", exc_info=True) + db.changeUsername(user, user.uid) + raise Exception(err) + except LDAPExcetpion as err: + if 'username' in attributes: + db.changeUsername(user, user.uid) + raise Exception(err) + except LDAPPasswordIsMandatoryError as err: + raise Exception('Password wurde nicht gesetzt!!') + except LDAPBindError as err: + raise Exception('Password ist falsch') + except Exception as err: + raise Exception(err) + + def validateUser(self, username, password): + debug.info("validate user {{ {} }}".format(username)) + ldap.login(username, password) + + def loginUser(self, username, password): + debug.info("login user {{ {} }}".format(username)) + try: + user = self.getUser(username) + debug.debug("user is {{ {} }}".format(user)) + user.password = password + ldap.login(username, password) + return user + except PermissionDenied as err: + debug.debug("permission is denied", exc_info=True) + raise err \ No newline at end of file diff --git a/geruecht/controller/mainController/mainWorkerController.py b/geruecht/controller/mainController/mainWorkerController.py new file mode 100644 index 0000000..91a3068 --- /dev/null +++ b/geruecht/controller/mainController/mainWorkerController.py @@ -0,0 +1,58 @@ +from datetime import time, datetime + +import geruecht.controller.databaseController as dc +from geruecht.exceptions import DayLocked +from geruecht.logger import getDebugLogger + +db = dc.DatabaseController() +debug = getDebugLogger() + +class Base: + def getWorker(self, date, username=None): + debug.info("get worker {{ {} }} on {{ {} }}".format(username, date)) + if (username): + user = self.getUser(username) + debug.debug("user is {{ {} }}".format(user)) + retVal = [db.getWorker(user, date)] + debug.debug("worker is {{ {} }}".format(retVal)) + return retVal + retVal = db.getWorkers(date) + debug.debug("workers are {{ {} }}".format(retVal)) + return retVal + + def addWorker(self, username, date, job_kind=None, userExc=False): + debug.info("add job user {{ {} }} on {{ {} }} with job_kind {{ {} }}".format(username, date, job_kind)) + if (userExc): + debug.debug("this is a user execution, check if day is locked") + lockedDay = self.getLockedDay(date) + if lockedDay: + if lockedDay['locked']: + debug.debug("day is lockey. user cant get job") + raise DayLocked("Day is locked. You can't get the Job") + user = self.getUser(username) + debug.debug("user is {{ {} }}".format(user)) + debug.debug("check if user has job on date") + if (not db.getWorker(user, date) and len(db.getWorkersWithJobKind(date, job_kind)) < db.getJobKindDate(date.date(), job_kind)['maxpersons']): + debug.debug("set job to user") + db.setWorker(user, date, job_kind=job_kind) + retVal = self.getWorker(date, username=username) + debug.debug("worker on date is {{ {} }}".format(retVal)) + return retVal + + def changeWorker(self, from_user, to_user, date): + debug.info("change worker from {{ {} }} to {{ {} }} on {{ {} }}".format(from_user, to_user, date)) + db.changeWorker(from_user, to_user, date) + + def deleteWorker(self, username, date, userExc=False): + debug.info( + "delete worker {{ {} }} on date {{ {} }}".format(username, date)) + user = self.getUser(username) + debug.debug("user is {{ {} }}".format(user)) + if userExc: + debug.debug("is user execution, check if day locked") + lockedDay = self.getLockedDay(date) + if lockedDay: + if lockedDay['locked']: + raise DayLocked( + "Day is locked. You can't delete the Job") + db.deleteWorker(user, date) \ No newline at end of file diff --git a/geruecht/controller/mainController/mainWorkgroupController.py b/geruecht/controller/mainController/mainWorkgroupController.py new file mode 100644 index 0000000..c32132e --- /dev/null +++ b/geruecht/controller/mainController/mainWorkgroupController.py @@ -0,0 +1,42 @@ +import geruecht.controller.databaseController as dc +from geruecht.logger import getDebugLogger + +db = dc.DatabaseController() +debug = getDebugLogger() + +class Base: + def updateWorkgroupsOfUser(self, user, workgroups): + debug.info("update workgroups {{ {} }} of user {{ {} }}".format(workgroups, user)) + db.deleteWorkgroupsOfUser(user) + for workgroup in workgroups: + db.setUserWorkgroup(user, workgroup) + return db.getWorkgroupsOfUser(user['id']) + + def getAllWorkgroups(self): + debug.info("get all workgroups") + retVal = db.getAllWorkgroups() + debug.debug("workgroups are {{ {} }}".format(retVal)) + return retVal + + def getWorkgroups(self, name): + debug.info("get Workgroup {{ {} }}".format(name)) + retVal = db.getWorkgroup(name) + debug.debug("workgroup is {{ {} }} is {{ {} }}".format(name, retVal)) + return retVal + + def setWorkgroup(self, name, boss): + debug.info("set workgroup {{ {} }} with boss {{ {} }}".format(name, boss)) + retVal = db.setWorkgroup(name, boss) + debug.debug( + "seted workgroup {{ {} }} is {{ {} }}".format(name, retVal)) + return retVal + + def deleteWorkgroup(self, workgroup): + debug.info("delete workgroup {{ {} }}".format(workgroup)) + db.deleteWorkgroup(workgroup) + + def updateWorkgroup(self, workgroup): + debug.info("update workgroup {{ {} }}".format(workgroup)) + retVal = db.updateWorkgroup(workgroup) + debug.debug("updated workgroup is {{ {} }}".format(retVal)) + return retVal \ No newline at end of file diff --git a/geruecht/decorator.py b/geruecht/decorator.py new file mode 100644 index 0000000..fe9fb58 --- /dev/null +++ b/geruecht/decorator.py @@ -0,0 +1,38 @@ +from functools import wraps +from .logger import getDebugLogger +DEBUG = getDebugLogger() + + +def login_required(**kwargs): + import geruecht.controller.accesTokenController as ac + from geruecht.model import BAR, USER, MONEY, GASTRO, VORSTAND, EXTERN + from flask import request, jsonify + accessController = ac.AccesTokenController() + groups = [USER, BAR, GASTRO, MONEY, VORSTAND, EXTERN] + bar = False + if "groups" in kwargs: + groups = kwargs["groups"] + if "bar" in kwargs: + bar = kwargs["bar"] + DEBUG.debug("groups are {{ {} }}".format(groups)) + + def real_decorator(func): + @wraps(func) + def wrapper(*args, **kwargs): + token = request.headers.get('Token') + DEBUG.debug("token is {{ {} }}".format(token)) + accToken = accessController.validateAccessToken(token, groups) + DEBUG.debug("accToken is {{ {} }}".format(accToken)) + kwargs['accToken'] = accToken + if accToken: + DEBUG.debug("token {{ {} }} is valid".format(token)) + if accToken.lock_bar and not bar: + return jsonify({"error": "error", + "message": "permission forbidden"}), 403 + return func(*args, **kwargs) + else: + DEBUG.warning("token {{ {} }} is not valid".format(token)) + return jsonify({"error": "error", + "message": "permission denied"}), 401 + return wrapper + return real_decorator diff --git a/geruecht/exceptions/__init__.py b/geruecht/exceptions/__init__.py new file mode 100644 index 0000000..307c48e --- /dev/null +++ b/geruecht/exceptions/__init__.py @@ -0,0 +1,14 @@ +class PermissionDenied(Exception): + pass +class UsernameExistDB(Exception): + pass +class UsernameExistLDAP(Exception): + pass +class DatabaseExecption(Exception): + pass +class LDAPExcetpion(Exception): + pass +class DayLocked(Exception): + pass +class TansactJobIsAnswerdException(Exception): + pass \ No newline at end of file diff --git a/geruecht/finanzer/__init__.py b/geruecht/finanzer/__init__.py new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/geruecht/finanzer/__init__.py @@ -0,0 +1 @@ + diff --git a/geruecht/finanzer/routes.py b/geruecht/finanzer/routes.py new file mode 100644 index 0000000..8b2e2fa --- /dev/null +++ b/geruecht/finanzer/routes.py @@ -0,0 +1,206 @@ +from flask import Blueprint, request, jsonify +from datetime import datetime +import geruecht.controller.mainController as mc +from geruecht.model import MONEY +from geruecht.decorator import login_required +from geruecht.logger import getDebugLogger, getCreditLogger + +debug = getDebugLogger() +creditL = getCreditLogger() + +finanzer = Blueprint("finanzer", __name__) + +mainController = mc.MainController() + + +@finanzer.route("/getFinanzerMain") +@login_required(groups=[MONEY]) +def _getFinanzer(**kwargs): + """ Function for /getFinanzerMain + + Retrieves all User for the groupe 'moneymaster' + + Returns: + A JSON-File with Users + or ERROR 401 Permission Denied. + """ + debug.info("/getFinanzerMain") + try: + users = mainController.getAllUsersfromDB() + dic = {} + for user in users: + dic[user.uid] = user.toJSON() + dic[user.uid]['creditList'] = { + credit.year: credit.toJSON() for credit in user.geruechte} + debug.debug("return {{ {} }}".format(dic)) + return jsonify(dic) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@finanzer.route("/finanzerAddAmount", methods=['POST']) +@login_required(groups=[MONEY]) +def _addAmount(**kwargs): + """ Add Amount to User + + This Function add an amount to the user with posted userID. + If year is not posted the default is the actual Year. + If month is not posted the default is the actual Month. + + Returns: + JSON-File with geruecht of year + or ERROR 401 Permission Denied + """ + debug.info("/finanzerAddAmount") + try: + data = request.get_json() + userID = data['userId'] + amount = int(data['amount']) + try: + year = int(data['year']) + except KeyError: + year = datetime.now().year + try: + month = int(data['month']) + except KeyError: + month = datetime.now().month + mainController.addAmount( + userID, amount, year=year, month=month, finanzer=True) + user = mainController.getUser(userID) + retVal = {str(geruecht.year): geruecht.toJSON() + for geruecht in user.geruechte} + retVal['locked'] = user.locked + debug.debug("return {{ {} }}".format(retVal)) + creditL.info("{} Finanzer {} {} fügt {} {} {} € Schulden hinzu.".format(datetime(year, month, 1).date( + ), kwargs['accToken'].user.firstname, kwargs['accToken'].user.lastname, user.firstname, user.lastname, amount/100)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@finanzer.route("/finanzerAddCredit", methods=['POST']) +@login_required(groups=[MONEY]) +def _addCredit(**kwargs): + """ Add Credit to User + + This Function add an credit to the user with posted userID. + If year is not posted the default is the actual Year. + If month is not posted the default is the actual Month. + + Returns: + JSON-File with geruecht of year + or ERROR 401 Permission Denied + """ + debug.info("/finanzerAddCredit") + try: + data = request.get_json() + userID = data['userId'] + credit = int(data['credit']) + + try: + year = int(data['year']) + except KeyError: + year = datetime.now().year + try: + month = int(data['month']) + except KeyError: + month = datetime.now().month + + mainController.addCredit( + userID, credit, year=year, month=month).toJSON() + user = mainController.getUser(userID) + retVal = {str(geruecht.year): geruecht.toJSON() + for geruecht in user.geruechte} + retVal['locked'] = user.locked + debug.debug("return {{ {} }}".format(retVal)) + creditL.info("{} Finanzer {} {} fügt {} {} {} € Guthaben hinzu.".format(datetime(year, month, 1).date( + ), kwargs['accToken'].user.firstname, kwargs['accToken'].user.lastname, user.firstname, user.lastname, credit / 100)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@finanzer.route("/finanzerLock", methods=['POST']) +@login_required(groups=[MONEY]) +def _finanzerLock(**kwargs): + debug.info("/finanzerLock") + try: + data = request.get_json() + username = data['userId'] + locked = bool(data['locked']) + retVal = mainController.lockUser(username, locked).toJSON() + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@finanzer.route("/finanzerSetConfig", methods=['POST']) +@login_required(groups=[MONEY]) +def _finanzerSetConfig(**kwargs): + debug.info("/finanzerSetConfig") + try: + data = request.get_json() + username = data['userId'] + autoLock = bool(data['autoLock']) + limit = int(data['limit']) + retVal = mainController.updateConfig( + username, {'lockLimit': limit, 'autoLock': autoLock}).toJSON() + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@finanzer.route("/finanzerAddUser", methods=['POST']) +@login_required(groups=[MONEY]) +def _finanzerAddUser(**kwargs): + debug.info("/finanzerAddUser") + try: + data = request.get_json() + username = data['userId'] + mainController.getUser(username) + users = mainController.getAllUsersfromDB() + dic = {} + for user in users: + dic[user.uid] = user.toJSON() + dic[user.uid]['creditList'] = { + credit.year: credit.toJSON() for credit in user.geruechte} + debug.debug("return {{ {} }}".format(dic)) + return jsonify(dic), 200 + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@finanzer.route("/finanzerSendOneMail", methods=['POST']) +@login_required(groups=[MONEY]) +def _finanzerSendOneMail(**kwargs): + debug.info("/finanzerSendOneMail") + try: + data = request.get_json() + username = data['userId'] + retVal = mainController.sendMail(username) + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@finanzer.route("/finanzerSendAllMail", methods=['GET']) +@login_required(groups=[MONEY]) +def _finanzerSendAllMail(**kwargs): + debug.info("/finanzerSendAllMail") + try: + retVal = mainController.sendAllMail() + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 diff --git a/geruecht/forms.py b/geruecht/forms.py deleted file mode 100644 index c13803b..0000000 --- a/geruecht/forms.py +++ /dev/null @@ -1,23 +0,0 @@ -from flask_wtf import FlaskForm -from wtforms import StringField, SubmitField, PasswordField; -from wtforms.validators import DataRequired, Length, ValidationError -from geruecht.model import User - - -class RegistrationForm(FlaskForm): - username = StringField('Name', validators=[DataRequired(), Length(min=2, max=20)]) - submit = SubmitField('Create') - - def validate_username(self, username): - - user = User.query.filter_by(username=username.data).first() - - if user: - raise ValidationError('Bist du behindert!? Der Name ist vergeben!!') - - -class FinanzerLogin(FlaskForm): - username = StringField('Name', validators=[DataRequired(), Length(min=2, max=20)]) - password = PasswordField('Password', validators=[DataRequired()]) - submit = SubmitField('Login') - diff --git a/geruecht/gastro/__init__.py b/geruecht/gastro/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/geruecht/gastro/routes.py b/geruecht/gastro/routes.py new file mode 100644 index 0000000..baca57a --- /dev/null +++ b/geruecht/gastro/routes.py @@ -0,0 +1,97 @@ +from flask import request, jsonify, Blueprint +from geruecht.decorator import login_required +import geruecht.controller.mainController as mc +from geruecht.model import GASTRO +from geruecht.logger import getCreditLogger, getDebugLogger + +debug = getDebugLogger() + +gastrouser = Blueprint('gastrouser', __name__) + +mainController = mc.MainController() + + +@gastrouser.route('/gastro/setDrink', methods=['POST']) +@login_required(groups=[GASTRO]) +def setDrink(**kwargs): + debug.info("/gastro/setDrink") + try: + data = request.get_json() + retVal = mainController.setDrinkPrice(data) + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@gastrouser.route('/gastro/updateDrink', methods=['POST']) +@login_required(groups=[GASTRO]) +def updateDrink(**kwargs): + debug.info("/gastro/updateDrink") + try: + data = request.get_json() + retVal = mainController.updateDrinkPrice(data) + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@gastrouser.route('/gastro/deleteDrink', methods=['POST']) +@login_required(groups=[GASTRO]) +def deleteDrink(**kwargs): + debug.info("/gastro/dleteDrink") + try: + data = request.get_json() + id = data['id'] + mainController.deletDrinkPrice({"id": id}) + debug.debug("return ok") + return jsonify({"ok": "ok"}) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@gastrouser.route('/gastro/setDrinkType', methods=['POST']) +@login_required(groups=[GASTRO]) +def setType(**kwark): + debug.info("/gastro/setDrinkType") + try: + data = request.get_json() + name = data['name'] + retVal = mainController.setDrinkType(name) + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@gastrouser.route('/gastro/updateDrinkType', methods=['POST']) +@login_required(groups=[GASTRO]) +def updateType(**kwargs): + debug.info("/gastro/updateDrinkType") + try: + data = request.get_json() + retVal = mainController.updateDrinkType(data) + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@gastrouser.route('/gastro/deleteDrinkType', methods=['POST']) +@login_required(groups=[GASTRO]) +def deleteType(**kwargs): + debug.info("/gastro/deleteDrinkType") + try: + data = request.get_json() + mainController.deleteDrinkType(data) + debug.debug("return ok") + return jsonify({"ok": "ok"}) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 diff --git a/geruecht/logger.py b/geruecht/logger.py new file mode 100644 index 0000000..0348262 --- /dev/null +++ b/geruecht/logger.py @@ -0,0 +1,29 @@ +import logging +import logging.config +import yaml +from os import path, makedirs, getcwd + +if not path.exists("geruecht/log/debug"): + a = path.join(path.curdir, "geruecht", "log", "debug") + makedirs(a) + +if not path.exists("geruecht/log/info"): + b = path.join(path.curdir, "geruecht", "log", "info") + makedirs(b) + + +with open("geruecht/logging.yml", 'rb') as file: + config = yaml.safe_load(file.read()) +logging.config.dictConfig(config) + + +def getDebugLogger(): + return logging.getLogger("debug_logger") + + +def getCreditLogger(): + return logging.getLogger("credit_logger") + + +def getJobsLogger(): + return logging.getLogger("jobs_logger") diff --git a/geruecht/logging.yml b/geruecht/logging.yml new file mode 100644 index 0000000..6ca9241 --- /dev/null +++ b/geruecht/logging.yml @@ -0,0 +1,57 @@ +version: 1 +disable_existing_loggers: True + +formatters: + debug: + format: "%(asctime)s — %(filename)s - %(funcName)s - %(lineno)d - %(threadName)s - %(name)s — %(levelname)s — %(message)s" + + simple: + format: "%(asctime)s - %(name)s - %(message)s" + +handlers: + console: + class: logging.StreamHandler + level: DEBUG + formatter: debug + stream: ext://sys.stdout + + debug: + class: logging.handlers.WatchedFileHandler + level: DEBUG + formatter: debug + filename: geruecht/log/debug/debug.log + encoding: utf8 + + credit: + class: logging.handlers.WatchedFileHandler + level: INFO + formatter: simple + filename: geruecht/log/info/geruecht.log + encoding: utf8 + + jobs: + class: logging.handlers.WatchedFileHandler + level: INFO + formatter: simple + filename: geruecht/log/info/jobs.log + encoding: utf8 + +loggers: + debug_logger: + level: DEBUG + handlers: [console, debug] + propagate: no + + credit_logger: + level: INFO + handlers: [credit] + propagate: no + + jobs_logger: + level: INFO + handlers: [jobs] + propagate: no + +root: + level: INFO + handlers: [console, debug] \ No newline at end of file diff --git a/geruecht/model.py b/geruecht/model.py deleted file mode 100644 index 9e73343..0000000 --- a/geruecht/model.py +++ /dev/null @@ -1,341 +0,0 @@ -from geruecht import db, login_manager -from threading import Timer -from flask_login import UserMixin -from datetime import date - - -@login_manager.user_loader -def load_finanzer(finanzer_id): - return Finanzer.query.get(int(finanzer_id)) - - -class User(db.Model): - id = db.Column(db.Integer, primary_key=True) - username = db.Column(db.String(20), unique=True, nullable=False) - sum = db.Column(db.Float, nullable=False, default=0.0) - - jan = db.Column(db.Float, nullable=False, default=0) - jan_sub = db.Column(db.Float, nullable=False, default=0) - jan_year = db.Column(db.Integer, nullable=False, default=date.today().year) - - feb = db.Column(db.Float, nullable=False, default=0) - feb_sub = db.Column(db.Float, nullable=False, default=0) - feb_year = db.Column(db.Integer, nullable=False, default=date.today().year) - - maer = db.Column(db.Float, nullable=False, default=0) - maer_sub = db.Column(db.Float, nullable=False, default=0) - maer_year = db.Column(db.Integer, nullable=False, default=date.today().year) - - apr = db.Column(db.Float, nullable=False, default=0) - apr_sub = db.Column(db.Float, nullable=False, default=0) - apr_year = db.Column(db.Integer, nullable=False, default=date.today().year) - - mai = db.Column(db.Float, nullable=False, default=0) - mai_sub = db.Column(db.Float, nullable=False, default=0) - mai_year = db.Column(db.Integer, nullable=False, default=date.today().year) - - jun = db.Column(db.Float, nullable=False, default=0) - jun_sub = db.Column(db.Float, nullable=False, default=0) - jun_year = db.Column(db.Integer, nullable=False, default=date.today().year) - - jul = db.Column(db.Float, nullable=False, default=0) - jul_sub = db.Column(db.Float, nullable=False, default=0) - jul_year = db.Column(db.Integer, nullable=False, default=date.today().year) - - aug = db.Column(db.Float, nullable=False, default=0) - aug_sub = db.Column(db.Float, nullable=False, default=0) - aug_year = db.Column(db.Integer, nullable=False, default=date.today().year) - - sep = db.Column(db.Float, nullable=False, default=0) - sep_sub = db.Column(db.Float, nullable=False, default=0) - sep_year = db.Column(db.Integer, nullable=False, default=date.today().year) - - okt = db.Column(db.Float, nullable=False, default=0) - okt_sub = db.Column(db.Float, nullable=False, default=0) - okt_year = db.Column(db.Integer, nullable=False, default=date.today().year) - - nov = db.Column(db.Float, nullable=False, default=0) - nov_sub = db.Column(db.Float, nullable=False, default=0) - nov_year = db.Column(db.Integer, nullable=False, default=date.today().year) - - dez = db.Column(db.Float, nullable=False, default=0) - dez_sub = db.Column(db.Float, nullable=False, default=0) - dez_year = db.Column(db.Integer, nullable=False, default=date.today().year) - - - - def getsum(self): - jan = self.jan - self.jan_sub - feb = self.feb - self.feb_sub - maer = self.maer - self.maer_sub - apr = self.apr - self.apr_sub - mai = self.mai - self.mai_sub - jun = self.jun - self.jun_sub - jul = self.jul - self.jul_sub - aug = self.aug - self.aug_sub - sep = self.sep - self.sep_sub - okt = self.okt - self.okt_sub - nov = self.nov - self.nov_sub - dez = self.dez - self.dez_sub - - result = jan + feb + maer + apr + mai + jun + jul + aug + sep + okt + nov + dez - return result - - def add_sub(self, value): - year = date.today().year - month = date.today().month - - if month == 1: - if year == self.jan_year: - self.jan_sub += value - else: - self.jan = 0 - self.jan_sub = value - self.jan_year = year; - elif month == 2: - if year == self.feb_year: - self.feb_sub += value - else: - self.feb = 0 - self.feb_sub = value - self.feb_year = year - elif month == 3: - if year == self.maer_year: - self.maer_sub += value - else: - self.maer = 0 - self.maer_sub = value - self.maer_year = year - elif month == 4: - if year == self.apr_year: - self.apr_sub += value - else: - self.apr = 0 - self.apr_sub = value - self.apr_year = year - elif month == 5: - if year == self.mai_year: - self.mai_sub += value - else: - self.mai = 0 - self.mai_sub = value - self.mai_year = year - elif month == 6: - if year == self.jun_year: - self.jun_sub += value - else: - self.jun = 0 - self.jun_sub = value - self.jun_year = year - elif month == 7: - if year == self.jul_year: - self.jul_sub += value - else: - self.jul = 0 - self.jul_sub = value - self.jul_year = year - elif month == 8: - if year == self.aug_year: - self.aug_sub += value - else: - self.aug = 0 - self.aug_sub = value - self.aug_year = year - elif month == 9: - if year == self.sep_year: - self.sep_sub += value - else: - self.sep = 0 - self.sep_sub = value - self.sep_year = year - elif month == 10: - if year == self.okt_year: - self.okt_sub += value - else: - self.okt = 0 - self.okt_sub = value - self.okt_year = year - elif month == 11: - if year == self.nov_year: - self.nov_sub += value - else: - self.nov = 0 - self.nov_sub = value - self.nov_year = year - elif month == 12: - if year == self.dez_year: - self.dez_sub += value - else: - self.dez = 0 - self.dez_sub = value - self.dez_year = year - else: - raise IndexError('Mehr monate gibt es nicht') - - - def add(self, value): - - year = date.today().year - month = date.today().month - - if month == 1 : - if year == self.jan_year: - self.jan += value - else: - self.jan = value - self.jan_sub = 0 - self.jan_year = year - elif month == 2: - if year == self.feb_year: - self.feb += value - else: - self.feb = value - self.feb_sub = 0 - self.feb_year = year - elif month == 3: - if year == self.maer_year: - self.maer += value - else: - self.maer = value - self.mear_sub = 0 - self.mear_year = year - elif month == 4: - if year == self.apr_year: - self.apr += value - else: - self.apr = value - self.apr_sub = 0 - self.apr_year = year - elif month == 5: - if year == self.mai_year: - self.mai += value - else: - self.mai = value - self.mai_sub = 0 - self.mai_year = year - elif month == 6: - if year == self.jun_year: - self.jun += value - else: - self.jun = value - self.jun_sub = 0 - self.jun_year = year - elif month == 7: - if year == self.jul_year: - self.jul += value - else: - self.jul = value - self.jul_sub = 0 - self.jul_year = year - elif month == 8: - if year == self.aug_year: - self.aug += value - else: - self.aug = value - self.aug_sub = 0 - self.aug_year = year - elif month == 9: - if year == self.sep_year: - self.sep += value - else: - self.sep = value - self.sep_sub = 0 - self.sep_year = year - elif month == 10: - if year == self.okt_year: - self.okt += value - else: - self.okt = value - self.okt_sub = 0 - self.okt_year = year - elif month == 11: - if year == self.nov_year: - self.nov += value - else: - self.nov = value - self.nov_sub = 0 - self.nov_year = year - elif month == 12: - if year == self.dez_year: - self.dez += value - else: - self.dez = value - self.dez_sub = 0 - self.dez_year = year - else: - raise IndexError('Mehr monate gibt es nicht') - - - def storner(self, value, month): - - if month == 1: - self.jan = self.jan - value - elif month == 2: - self.feb = self.feb - value - elif month == 3: - self.maer = self.maer - value - elif month == 4: - self.apr = self.apr - value - elif month == 5: - self.mai = self.mai - value - elif month == 6: - self.jun = self.jun - value - elif month == 7: - self.jul = self.jul - value - elif month == 8: - self.aug = self.aug - value - elif month == 9: - self.sep = self.sep - value - elif month == 10: - self.okt = self.okt - value - elif month == 11: - self.nov = self.nov - value - elif month == 12: - self.dez = self.dez - value - else: - raise IndexError('Mehr monate gibt es nicht') - - def __repr__(self): - return f"User('{self.username}', '{self.sum}')" - - -class Finanzer(db.Model, UserMixin): - id = db.Column(db.Integer, primary_key=True) - username = db.Column(db.String(20), unique=True, nullable=False) - password = db.Column(db.String(60), nullable=False) - - def __repr__(self): - return f"Finanzer('{self.username}')" - - -class History: - history = [] - user = None - - def __init__(self, history, user, value): - self.history = history - self.history.append(self) - self.user = user - self.month = date.today().month - self.value = value - self.timer = Timer(60, self.kill) - self.timer.start() - - def exec(self): - self.timer.cancel() - User.query.filter_by(username=self.user.username).first().storner(self.value, self.month) - self.kill() - - def kill(self): - print("{} deledet from history".format(self.user)) - self.history.remove(self) - print(self.history) - - -''' - def __repr__(self): - print(f'self:{self}, history:{self.history}, user:{self.user}, value:{self.value}') - - def __str__(self): - print(f'self:{self}, history:{self.history}, user:{self.user}, value:{self.value}') -''' diff --git a/geruecht/model/__init__.py b/geruecht/model/__init__.py new file mode 100644 index 0000000..065f441 --- /dev/null +++ b/geruecht/model/__init__.py @@ -0,0 +1,6 @@ +MONEY = "moneymaster" +VORSTAND = "vorstand" +EXTERN = "extern" +GASTRO = "gastro" +USER = "user" +BAR = "bar" \ No newline at end of file diff --git a/geruecht/model/accessToken.py b/geruecht/model/accessToken.py new file mode 100644 index 0000000..6e777f7 --- /dev/null +++ b/geruecht/model/accessToken.py @@ -0,0 +1,79 @@ +from datetime import datetime +from geruecht.logger import getDebugLogger + +debug = getDebugLogger() + +class AccessToken(): + """ Model for an AccessToken + + Attributes: + timestamp: Is a Datetime from current Time. + user: Is an User. + token: String to verify access later. + """ + + timestamp = None + user = None + token = None + + def __init__(self, id, user, token, lifetime, lock_bar=False, timestamp=datetime.now(), browser=None, platform=None): + """ Initialize Class AccessToken + + No more to say. + + Args: + User: Is an User to set. + token: Is a String to verify later + timestamp: Default current time, but can set to an other datetime-Object. + """ + debug.debug("init accesstoken") + self.id = id + self.user = user + self.timestamp = timestamp + self.lifetime = lifetime + self.token = token + self.lock_bar = lock_bar + self.browser = browser + self.platform = platform + debug.debug("accesstoken is {{ {} }}".format(self)) + + def updateTimestamp(self): + """ Update the Timestamp + + Update the Timestamp to the current Time. + """ + debug.debug("update timestamp from accesstoken {{ {} }}".format(self)) + self.timestamp = datetime.now() + + def toJSON(self): + """ Create Dic to dump in JSON + + Returns: + A Dic with static Attributes. + """ + dic = { + "id": self.id, + "timestamp": {'year': self.timestamp.year, + 'month': self.timestamp.month, + 'day': self.timestamp.day, + 'hour': self.timestamp.hour, + 'minute': self.timestamp.minute, + 'second': self.timestamp.second + }, + "lifetime": self.lifetime, + "browser": self.browser, + "platform": self.platform + } + return dic + + def __eq__(self, token): + return True if self.token == token else False + + def __sub__(self, other): + return other - self.timestamp + + def __str__(self): + return "AccessToken(user={}, token={}, timestamp={}, lifetime={}".format(self.user, self.token, self.timestamp, self.lifetime) + + def __repr__(self): + return "AccessToken(user={}, token={}, timestamp={}, lifetime={}".format(self.user, self.token, self.timestamp, self.lifetime) diff --git a/geruecht/model/creditList.py b/geruecht/model/creditList.py new file mode 100644 index 0000000..9c909f8 --- /dev/null +++ b/geruecht/model/creditList.py @@ -0,0 +1,324 @@ +from datetime import datetime +from geruecht.logger import getDebugLogger + +debug = getDebugLogger() + +def create_empty_data(): + empty_data = {'id': 0, + 'jan_guthaben': 0, + 'jan_schulden': 0, + 'feb_guthaben': 0, + 'feb_schulden': 0, + 'maer_guthaben': 0, + 'maer_schulden': 0, + 'apr_guthaben': 0, + 'apr_schulden': 0, + 'mai_guthaben': 0, + 'mai_schulden': 0, + 'jun_guthaben': 0, + 'jun_schulden': 0, + 'jul_guthaben': 0, + 'jul_schulden': 0, + 'aug_guthaben': 0, + 'aug_schulden': 0, + 'sep_guthaben': 0, + 'sep_schulden': 0, + 'okt_guthaben': 0, + 'okt_schulden': 0, + 'nov_guthaben': 0, + 'nov_schulden': 0, + 'dez_guthaben': 0, + 'dez_schulden': 0, + 'last_schulden': 0, + 'year_date': datetime.now().year, + 'user_id': 0} + return empty_data + +class CreditList(): + """ DataBase Object Credit List: + + Attributes: + id: id in Database. Is the Primary Key + _guthaben: Credit of the Month. + _schulden: Debt of the Month. + + last_schulden: Debt or Credit of last Year. + year: Year of all Credits and Debts. + user_id: id from the User. + """ + def __init__(self, data): + debug.debug("init creditlist") + self.id = int(data['id']) + + self.jan_guthaben = int(data['jan_guthaben']) + self.jan_schulden = int(data['jan_schulden']) + + self.feb_guthaben = int(data['feb_guthaben']) + self.feb_schulden = int(data['feb_schulden']) + + self.maer_guthaben = int(data['maer_guthaben']) + self.maer_schulden = int(data['maer_schulden']) + + self.apr_guthaben = int(data['apr_guthaben']) + self.apr_schulden = int(data['apr_schulden']) + + self.mai_guthaben = int(data['mai_guthaben']) + self.mai_schulden = int(data['mai_schulden']) + + self.jun_guthaben = int(data['jun_guthaben']) + self.jun_schulden = int(data['jun_schulden']) + + self.jul_guthaben = int(data['jul_guthaben']) + self.jul_schulden = int(data['jul_schulden']) + + self.aug_guthaben = int(data['aug_guthaben']) + self.aug_schulden = int(data['aug_schulden']) + + self.sep_guthaben = int(data['sep_guthaben']) + self.sep_schulden = int(data['sep_schulden']) + + self.okt_guthaben = int(data['okt_guthaben']) + self.okt_schulden = int(data['okt_schulden']) + + self.nov_guthaben = int(data['nov_guthaben']) + self.nov_schulden = int(data['nov_schulden']) + + self.dez_guthaben = int(data['dez_guthaben']) + self.dez_schulden = int(data['dez_schulden']) + + self.last_schulden = int(data['last_schulden']) + + self.year = int(data['year_date']) + + self.user_id = int(data['user_id']) + + debug.debug("credit list is {{ {} }}".format(self)) + + def getSchulden(self): + """ Get Schulden + + This function calculate the total amount of them self. + From the Credit of the Month will the Amount of the Month subtract. + Finaly all Month will added together. + At Last the amount from last year will be subtract. + + If the Return Value is negativ, the User has an Credit, else the User has an amount. + + Returns: + double of the calculated amount + """ + debug.info("calculate amount") + jan = self.jan_guthaben - self.jan_schulden + feb = self.feb_guthaben - self.feb_schulden + maer = self.maer_guthaben - self.maer_schulden + apr = self.apr_guthaben - self.apr_schulden + mai = self.mai_guthaben - self.mai_schulden + jun = self.jun_guthaben - self.jun_schulden + jul = self.jul_guthaben - self.jul_schulden + aug = self.aug_guthaben - self.aug_schulden + sep = self.sep_guthaben - self.sep_schulden + okt = self.okt_guthaben - self.okt_schulden + nov = self.nov_guthaben - self.nov_schulden + dez = self.dez_guthaben - self.dez_schulden + + sum = jan + feb + maer + apr + mai + jun + jul + aug + sep + okt + nov + dez - self.last_schulden + debug.debug("amount is {{ {} }}".format(sum)) + return sum + + def getMonth(self, month=datetime.now().month): + """ Get Amount from month + + This function returns the amount and credit of the month. + By default is month the actual month + + Args: + month: which month you want to get the amount(1-12) + + Returns: + double (credit, amount) + """ + debug.info("get credit and amount from month {{ {} }}".format(month)) + retValue = None + + if month == 1: + retValue = (self.jan_guthaben, self.jan_schulden) + elif month == 2: + retValue = (self.feb_guthaben, self.feb_schulden) + elif month == 3: + retValue = (self.maer_guthaben, self.maer_schulden) + elif month == 4: + retValue = (self.apr_guthaben, self.apr_schulden) + elif month == 5: + retValue = (self.mai_guthaben, self.mai_schulden) + elif month == 6: + retValue = (self.jun_guthaben, self.jun_schulden) + elif month == 7: + retValue = (self.jul_guthaben, self.jul_schulden) + elif month == 8: + retValue = (self.aug_guthaben, self.aug_schulden) + elif month == 9: + retValue = (self.sep_guthaben, self.sep_schulden) + elif month == 10: + retValue = (self.okt_guthaben, self.okt_schulden) + elif month == 11: + retValue = (self.nov_guthaben, self.nov_schulden) + elif month == 12: + retValue = (self.dez_guthaben, self.dez_schulden) + debug.debug("credit and amount is {{ {} }}".format(retValue)) + return retValue + + def addAmount(self, amount, month=datetime.now().month): + """ Add Amount + + This function add an amount to a month and returns the credit and amount of the month. + By default is month the actual month. + + Args: + amount: the amount which is to add + month: in which month to add the amount (1-12) + + Returns: + double (credit, amount) + """ + debug.info("add amount in month {{ {} }}".format(month)) + if month == 1: + self.jan_schulden += amount + retValue = (self.jan_guthaben, self.jan_schulden) + elif month == 2: + self.feb_schulden += amount + retValue = (self.feb_guthaben, self.feb_schulden) + elif month == 3: + self.maer_schulden += amount + retValue = (self.maer_guthaben, self.maer_schulden) + elif month == 4: + self.apr_schulden += amount + retValue = (self.apr_guthaben, self.apr_schulden) + elif month == 5: + self.mai_schulden += amount + retValue = (self.mai_guthaben, self.mai_schulden) + elif month == 6: + self.jun_schulden += amount + retValue = (self.jun_guthaben, self.jun_schulden) + elif month == 7: + self.jul_schulden += amount + retValue = (self.jul_guthaben, self.jul_schulden) + elif month == 8: + self.aug_schulden += amount + retValue = (self.aug_guthaben, self.aug_schulden) + elif month == 9: + self.sep_schulden += amount + retValue = (self.sep_guthaben, self.sep_schulden) + elif month == 10: + self.okt_schulden += amount + retValue = (self.okt_guthaben, self.okt_schulden) + elif month == 11: + self.nov_schulden += amount + retValue = (self.nov_guthaben, self.nov_schulden) + elif month == 12: + self.dez_schulden += amount + retValue = (self.dez_guthaben, self.dez_schulden) + debug.debug("credit and amount is {{ {} }}".format(retValue)) + return retValue + + def addCredit(self, credit, month=datetime.now().month): + """ Add Credit + + This function add an credit to a month and returns the credit and amount of the month. + By default is month the actual month. + + Args: + credit: the credit which is to add + month: in which month to add the credit (1-12) + + Returns: + double (credit, amount) + """ + debug.info("add credit in month {{ {} }}".format(month)) + if month == 1: + self.jan_guthaben += credit + retValue = (self.jan_guthaben, self.jan_schulden) + elif month == 2: + self.feb_guthaben += credit + retValue = (self.feb_guthaben, self.feb_schulden) + elif month == 3: + self.maer_guthaben += credit + retValue = (self.maer_guthaben, self.maer_schulden) + elif month == 4: + self.apr_guthaben += credit + retValue = (self.apr_guthaben, self.apr_schulden) + elif month == 5: + self.mai_guthaben += credit + retValue = (self.mai_guthaben, self.mai_schulden) + elif month == 6: + self.jun_guthaben += credit + retValue = (self.jun_guthaben, self.jun_schulden) + elif month == 7: + self.jul_guthaben += credit + retValue = (self.jul_guthaben, self.jul_schulden) + elif month == 8: + self.aug_guthaben += credit + retValue = (self.aug_guthaben, self.aug_schulden) + elif month == 9: + self.sep_guthaben += credit + retValue = (self.sep_guthaben, self.sep_schulden) + elif month == 10: + self.okt_guthaben += credit + retValue = (self.okt_guthaben, self.okt_schulden) + elif month == 11: + self.nov_guthaben += credit + retValue = (self.nov_guthaben, self.nov_schulden) + elif month == 12: + self.dez_guthaben += credit + retValue = (self.dez_guthaben, self.dez_schulden) + debug.debug("credit and amount is {{ {} }}".format(retValue)) + return retValue + + def toJSON(self): + """ Create Dic to dump in JSON + + Returns: + A Dic with static Attributes. + """ + dic = { + "jan": { + "credit": self.jan_guthaben, + "depts": self.jan_schulden}, + "feb": { + "credit": self.feb_guthaben, + "depts": self.feb_schulden}, + "maer": { + "credit": self.maer_guthaben, + "depts": self.maer_schulden}, + "apr": { + "credit": self.apr_guthaben, + "depts": self.apr_schulden}, + "mai": { + "credit": self.mai_guthaben, + "depts": self.mai_schulden}, + "jun": { + "credit": self.jun_guthaben, + "depts": self.jun_schulden}, + "jul": { + "credit": self.jul_guthaben, + "depts": self.jul_schulden}, + "aug": { + "credit": self.aug_guthaben, + "depts": self.aug_schulden}, + "sep": { + "credit": self.sep_guthaben, + "depts": self.sep_schulden}, + "okt": { + "credit": self.okt_guthaben, + "depts": self.okt_schulden}, + "nov": { + "credit": self.nov_guthaben, + "depts": self.nov_schulden}, + "dez": { + "credit": self.dez_guthaben, + "depts": self.dez_schulden}, + "last": self.last_schulden + } + return dic + + def __repr__(self): + return "CreditList(year: {}, userID: {}, amount: {})".format(self.year, self.user_id, self.toJSON()) diff --git a/geruecht/model/user.py b/geruecht/model/user.py new file mode 100644 index 0000000..543859c --- /dev/null +++ b/geruecht/model/user.py @@ -0,0 +1,244 @@ +from geruecht.logger import getDebugLogger +from geruecht.model.creditList import CreditList, create_empty_data +from datetime import datetime + +debug = getDebugLogger() + + +class User(): + """ Database Object for User + + Table for all safed User + + Attributes: + id: Id in Database as Primary Key. + userID: ID for the User maybe to Link? + username: Username of the User to Login + firstname: Firstname of the User + Lastname: Lastname of the User + group: Which group is the User? moneymaster, gastro, user or bar? + password: salted hashed password for the User. + """ + def __init__(self, data): + debug.info("init user") + if 'id' in data: + self.id = int(data['id']) + self.uid = data['uid'] + self.dn = data['dn'] + self.firstname = data['firstname'] + self.lastname = data['lastname'] + self.group = data['gruppe'] + self.last_seen = None + if 'last_seen' in data: + self.last_seen = data['last_seen'] + if 'statusgroup' in data: + self.statusgroup = data['statusgroup'] + else: + self.statusgroup = None + if 'voting' in data: + self.voting = data['voting'] + else: + self.voting = None + if 'mail' in data: + self.mail = data['mail'] + else: + self.mail = '' + if 'lockLimit' in data: + self.limit = int(data['lockLimit']) + else: + self.limit = 4200 + if 'locked' in data: + self.locked = bool(data['locked']) + else: + self.locked = False + if 'autoLock' in data: + self.autoLock = bool(data['autoLock']) + else: + self.autoLock = True + if type(data['gruppe']) == list: + self.group = data['gruppe'] + elif type(data['gruppe']) == str: + self.group = data['gruppe'].split(',') + if 'creditLists' in data: + self.geruechte = data['creditLists'] + if 'workgroups' in data: + self.workgroups = data['workgroups'] + else: + self.workgroups = None + self.password = '' + debug.debug("user is {{ {} }}".format(self)) + + def updateData(self, data): + debug.info("update data of user") + if 'dn' in data: + self.dn = data['dn'] + if 'firstname' in data: + self.firstname = data['firstname'] + if 'lastname' in data: + self.lastname = data['lastname'] + if 'gruppe' in data: + self.group = data['gruppe'] + if 'lockLimit' in data: + self.limit = int(data['lockLimit']) + if 'locked' in data: + self.locked = bool(data['locked']) + if 'autoLock' in data: + self.autoLock = bool(data['autoLock']) + if 'mail' in data: + self.mail = data['mail'] + if 'statusgorup' in data: + self.statusgroup = data['statusgroup'] + if 'voting' in data: + self.voting = data['voting'] + if 'workgroups' in data: + self.workgroups = data['workgroups'] + else: + self.workgroups = None + + def initGeruechte(self, creditLists): + if type(creditLists) == list: + self.geruechte = creditLists + + def createGeruecht(self, amount=0, year=datetime.now().year): + """ Create Geruecht + + This function create a geruecht for the user for an year. + By default is amount zero and year the actual year. + + Args: + amount: is the last_schulden of the geruecht + year: is the year of the geruecht + + Returns: + the created geruecht + """ + debug.info("create creditlist for user {{ {} }} in year {{ {} }}".format(self, year)) + data = create_empty_data() + data['user_id'] = self.id + data['last_schulden'] = amount + data['year_date'] = year + credit = CreditList(data) + self.geruechte.append(credit) + debug.debug("creditlist is {{ {} }}".format(credit)) + return credit + + def getGeruecht(self, year=datetime.now().year): + """ Get Geruecht + + This function returns the geruecht of an year. + By default is the year the actual year. + + Args: + year: the year of the geruecht + + Returns: + the geruecht of the year + """ + debug.info("get creditlist from user on year {{ {} }}".format(year)) + for geruecht in self.geruechte: + if geruecht.year == year: + debug.debug("creditlist is {{ {} }} for user {{ {} }}".format(geruecht, self)) + return geruecht + debug.debug("no creditlist found for user {{ {} }}".format(self)) + geruecht = self.createGeruecht(year=year) + + return self.getGeruecht(year=year) + + def addAmount(self, amount, year=datetime.now().year, month=datetime.now().month): + """ Add Amount + + This function add an amount to a geruecht with an spezified year and month to the user. + By default the year is the actual year. + By default the month is the actual month. + + Args: + year: year of the geruecht + month: month for the amount + + Returns: + double (credit, amount) + """ + debug.info("add amount to user {{ {} }} in year {{ {} }} and month {{ {} }}".format(self, year, month)) + geruecht = self.getGeruecht(year=year) + retVal = geruecht.addAmount(amount, month=month) + + return retVal + + def addCredit(self, credit, year=datetime.now().year, month=datetime.now().month): + """ Add Credit + + This function add an credit to a geruecht with an spezified year and month to the user. + By default the year is the actual year. + By default the month is the actual month. + + Args: + year: year of the geruecht + month: month for the amount + + Returns: + double (credit, amount) + """ + debug.info("add credit to user {{ {} }} in year {{ {} }} and month {{ {} }}".format(self, year, month)) + geruecht = self.getGeruecht(year=year) + retVal = geruecht.addCredit(credit, month=month) + + return retVal + + def updateGeruecht(self): + """ Update list of geruechte + + This function iterate through the geruechte, which sorted by year and update the last_schulden of the geruecht. + """ + debug.info("update all creditlists ") + self.geruechte.sort(key=self.sortYear) + + for index, geruecht in enumerate(self.geruechte): + if index == 0 or index == len(self.geruechte) - 1: + geruecht.last_schulden = 0 + if index != 0: + geruecht.last_schulden = (self.geruechte[index - 1].getSchulden() * -1) + + return self.geruechte + + def sortYear(self, geruecht): + """ Sort Year + + This function is only an helperfunction to sort the list of geruechte by years. + It only returns the year of the geruecht. + + Args: + geruecht: geruecht which year you want + + Returns: + int year of the geruecht + """ + return geruecht.year + + def toJSON(self): + """ Create Dic to dump in JSON + + Returns: + A Dic with static Attributes. + """ + dic = { + "id": self.id, + "userId": self.uid, + "uid": self.uid, + "dn": self.dn, + "firstname": self.firstname, + "lastname": self.lastname, + "group": self.group, + "username": self.uid, + "locked": self.locked, + "autoLock": self.autoLock, + "limit": self.limit, + "mail": self.mail, + "statusgroup": self.statusgroup, + "voting": self.voting, + "workgroups": self.workgroups + } + return dic + + def __repr__(self): + return "User({}, {}, {})".format(self.uid, self.dn, self.group) + diff --git a/geruecht/registration_route.py b/geruecht/registration_route.py new file mode 100644 index 0000000..8a4bed1 --- /dev/null +++ b/geruecht/registration_route.py @@ -0,0 +1,15 @@ +from flask import Blueprint, request, jsonify +import geruecht.controller.mainController as mc +from geruecht.logger import getDebugLogger + +registration = Blueprint("registration", __name__) + +mainController = mc.MainController() + +debug = getDebugLogger() + +@registration.route("/registration", methods=['PUT']) +def __registration(): + data = request.get_json() + mainController.setNewRegistration(data) + return jsonify({"ok":"ok"}) \ No newline at end of file diff --git a/geruecht/routes.py b/geruecht/routes.py index f828660..07b78ce 100644 --- a/geruecht/routes.py +++ b/geruecht/routes.py @@ -1,156 +1,216 @@ -from flask import render_template, url_for, redirect, flash, jsonify, g, request -from flask_login import login_user, current_user, logout_user, login_required -from geruecht import app, db, bcrypt -from geruecht.forms import RegistrationForm, FinanzerLogin -from geruecht.model import User, History, Finanzer -import flask_sijax -import os, sys +from geruecht import app +from geruecht.logger import getDebugLogger +from geruecht.decorator import login_required +from geruecht.exceptions import PermissionDenied +import geruecht.controller.accesTokenController as ac +import geruecht.controller.mainController as mc +from geruecht.model import MONEY, BAR, USER, GASTRO, VORSTAND, EXTERN +from flask import request, jsonify -path = os.path.join('.', os.path.dirname(__file__), '../') -sys.path.append(path) +accesTokenController = ac.AccesTokenController() +mainController = mc.MainController() -# The path where you want the extension to create the needed javascript files -# DON'T put any of your files in this directory, because they'll be deleted! -app.config["SIJAX_STATIC_PATH"] = os.path.join('.', os.path.dirname(__file__), 'static/js/sijax/') +debug = getDebugLogger() -# You need to point Sijax to the json2.js library if you want to support -# browsers that don't support JSON natively (like IE <= 7) -app.config["SIJAX_JSON_URI"] = '/static/js/sijax/json2.js' +@app.route("/valid", methods=['POST']) +@login_required(bar=True) +def _valid(**kwargs): + debug.info('/valid') + try: + accToken = kwargs['accToken'] + data = request.get_json() + mainController.validateUser(accToken.user.uid, data['password']) + debug.debug('return {{ "ok": "ok" }}') + return jsonify({"ok": "ok"}) + except Exception as err: + debug.warning("exception in valide.", exc_info=True) + return jsonify({"error": str(err)}), 500 -flask_sijax.Sijax(app) - -history = [] +@app.route("/pricelist", methods=['GET']) +def _getPricelist(): + try: + debug.info("get pricelist") + retVal = mainController.getPricelist() + debug.info("return pricelist {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.warning("exception in get pricelist.", exc_info=True) + return jsonify({"error": str(err)}), 500 -@flask_sijax.route(app, "/", methods=['GET', 'POST']) -@flask_sijax.route(app, "/home", methods=['GET', 'POST']) -def home(): - def add(obj_response, username, value): - user_2 = User.query.filter_by(username=username).first() - print(user_2) - print(user_2.id) - user_2.add(value) - print(user_2) - db.session.commit() - print(obj_response, username, value) - History(history=history, user=user_2, value=value) - print(history) - obj_response.html('div#flash', f'{user_2.username} wurde {"%.2f"%value} € hinzugefügt') - obj_response.attr('div#flash', "class", "alert alert-success") - obj_response.html(f'#{user_2.id}-sum', str("%.2f" % user_2.getsum() + " €")) - - def storner(obj_response): - try: - obj = history[len(history)-1] - user_2 = User.query.filter_by(username=obj.user.username).first() - print("{} {}".format(obj.user, obj.value)) - obj.exec() - print(history) - print(user_2) - db.session.commit() - obj_response.html('div#flash', f'{"%.2f"%obj.value} wurden von {user_2.username} storniert') - obj_response.attr('div#flash', "class", "alert alert-success") - obj_response.html(f'#{user_2.id}-sum', str("%.2f" % user_2.getsum() + " €")) - - except IndexError: - print("history: {} is empty".format(history)) - obj_response.html('div#flash', "Der Timer ist abgelaufen!! Die Stornierliste ist leer!! Falls es was wichtiges ist, melde dich beim Finanzer oder Administrator!!") - obj_response.attr('div#flash', "class", "alert alert-error") - - if g.sijax.is_sijax_request: - g.sijax.register_callback('add', add) - g.sijax.register_callback('storner', storner) - return g.sijax.process_request() - - form = RegistrationForm() - if form.validate_on_submit(): - user = User(username=form.username.data) - db.session.add(user) - db.session.commit() - flash(f'Person wurde angelegt: {form.username.data}', 'success') - return redirect(url_for('home')) - return render_template('home.html', users=User.query.all(), form=form) +@app.route('/drinkTypes', methods=['GET']) +def getTypes(): + try: + debug.info("get drinktypes") + retVal = mainController.getAllDrinkTypes() + debug.info("return drinktypes {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.warning("exception in get drinktypes.", exc_info=True) + return jsonify({"error": str(err)}), 500 -@flask_sijax.route(app, "/return") -def to_home(): - return home() +@app.route('/getAllStatus', methods=['GET']) +@login_required(groups=[USER, MONEY, GASTRO, BAR, VORSTAND], bar=True) +def _getAllStatus(**kwargs): + try: + debug.info("get all status for users") + retVal = mainController.getAllStatus() + debug.info("return all status for users {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.warning("exception in get all status for users.", exc_info=True) + return jsonify({"error": str(err)}), 500 -@app.route("/login", methods=['GET', 'POST']) -def login(): - if current_user.is_authenticated: - return redirect(url_for('home')) - login_form = FinanzerLogin() - if login_form.validate_on_submit(): - user = Finanzer.query.filter_by(username=login_form.username.data).first() - if user: - if user and bcrypt.check_password_hash(user.password, login_form.password.data): - login_user(user) - next_page = request.args.get('next') - return redirect(next_page) if next_page else redirect(url_for('home')) - else: - flash('Passwort ist falsch', 'error') - else: - flash('nur der finanzer kann sich einloggen !!', 'error') - return render_template('login.html', title='Login', form=login_form) +@app.route('/getStatus', methods=['POST']) +@login_required(groups=[USER, MONEY, GASTRO, BAR, VORSTAND], bar=True) +def _getStatus(**kwargs): + try: + debug.info("get status from user") + data = request.get_json() + name = data['name'] + debug.info("get status from user {{ {} }}".format(name)) + retVal = mainController.getStatus(name) + debug.info( + "return status from user {{ {} }} : {{ {} }}".format(name, retVal)) + return jsonify(retVal) + except Exception as err: + debug.warning("exception in get status from user.", exc_info=True) + return jsonify({"error": str(err)}), 500 -@app.route("/logout") -def logout(): - logout_user() - return redirect(url_for('home')) +@app.route('/getUsers', methods=['GET']) +@login_required(groups=[USER], bar=True) +def _getUsers(**kwargs): + try: + extern = True + if 'extern' in request.args: + extern = not bool(int(request.args['extern'])) + debug.info("get all users from database") + users = mainController.getAllUsersfromDB(extern=extern) + debug.debug("users are {{ {} }}".format(users)) + retVal = [user.toJSON() for user in users] + debug.info("return all users from database {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.warning( + "exception in get all users from database.", exc_info=True) + return jsonify({"error": str(err)}), 500 -@flask_sijax.route(app, "/uebersicht") -@login_required -def finanzen(): - - def supply(obj_response, arg1, arg2): - - list = zip(arg1, arg2) - try: - for value in arg2: - if value: - float(value) - - for user_id, value in list: - if user_id and value: - user_ = User.query.get(user_id) - user_.add_sub(float(value)) - db.session.commit() - obj_response.attr(f'#{user_id}-input', 'value', '') - - obj_response.html('div#flash', "Alle Werte wurden übernommen") - obj_response.attr('div#flash', 'class', "alert alert-success") - - for user_ in User.query.all(): - obj_response.html(f'p#{user_.id}-jan-sub', "%.2f"%user_.jan_sub + " €") - obj_response.html(f'p#{user_.id}-feb-sub', "%.2f"%user_.feb_sub + " €") - obj_response.html(f'p#{user_.id}-maer-sub', "%.2f"%user_.maer_sub + " €") - obj_response.html(f'p#{user_.id}-apr-sub', "%.2f"%user_.apr_sub + " €") - obj_response.html(f'p#{user_.id}-mai-sub', "%.2f"%user_.mai_sub + " €") - obj_response.html(f'p#{user_.id}-jun-sub', "%.2f"%user_.jun_sub + " €") - obj_response.html(f'p#{user_.id}-jul-sub', "%.2f"%user_.jul_sub + " €") - obj_response.html(f'p#{user_.id}-aug-sub', "%.2f"%user_.aug_sub + " €") - obj_response.html(f'p#{user_.id}-sep-sub', "%.2f"%user_.sep_sub + " €") - obj_response.html(f'p#{user_.id}-okt-sub', "%.2f"%user_.okt_sub + " €") - obj_response.html(f'p#{user_.id}-nov-sub', "%.2f"%user_.nov_sub + " €") - obj_response.html(f'p#{user_.id}-dez-sub', "%.2f"%user_.dez_sub + " €") - obj_response.html(f'p#{user_.id}-sum', "%.2f"%user_.getsum() + " €") - - except ValueError: - obj_response.html('div#flash', - "Du hast irgendwo keine Zahl eingegeb!!") - obj_response.attr('div#flash', "class", "alert alert-error") - - if g.sijax.is_sijax_request: - g.sijax.register_callback('supply', supply) - return g.sijax.process_request() - - return render_template('finanzer.html', users=User.query.all()) +@app.route("/getLifeTime", methods=['GET']) +@login_required(groups=[MONEY, GASTRO, VORSTAND, EXTERN, USER], bar=True) +def _getLifeTime(**kwargs): + try: + debug.info("get lifetime of accesstoken") + if 'accToken' in kwargs: + accToken = kwargs['accToken'] + debug.debug("accessToken is {{ {} }}".format(accToken)) + retVal = {"value": accToken.lifetime, + "group": accToken.user.toJSON()['group'], + "lock_bar": accToken.lock_bar} + debug.info( + "return get lifetime from accesstoken {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.info("exception in get lifetime of accesstoken.", exc_info=True) + return jsonify({"error": str(err)}), 500 -@flask_sijax.route(app, "/about") -def about(): - return render_template('about.html', title='about') +@app.route("/saveLifeTime", methods=['POST']) +@login_required(groups=[MONEY, GASTRO, VORSTAND, EXTERN, USER], bar=True) +def _saveLifeTime(**kwargs): + try: + debug.info("save lifetime for accessToken") + if 'accToken' in kwargs: + accToken = kwargs['accToken'] + debug.debug("accessToken is {{ {} }}".format(accToken)) + data = request.get_json() + lifetime = data['value'] + debug.debug("lifetime is {{ {} }}".format(lifetime)) + debug.info("set lifetime {{ {} }} to accesstoken {{ {} }}".format( + lifetime, accToken)) + accToken.lifetime = lifetime + debug.info("update accesstoken timestamp") + accToken = accesTokenController.updateAccessToken(accToken) + accToken = accesTokenController.validateAccessToken(accToken.token, [USER, EXTERN]) + retVal = {"value": accToken.lifetime, + "group": accToken.user.toJSON()['group']} + debug.info( + "return save lifetime for accessToken {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.warning( + "exception in save lifetime for accesstoken.", exc_info=True) + return jsonify({"error": str(err)}), 500 + +@app.route("/passwordReset", methods=['POST']) +def _passwordReset(): + try: + debug.info('password reset') + data = request.get_json() + mail = mainController.resetPassword(data) + index = mail.find('@') + for i in range(index): + if i == 0: + continue + mail = mail.replace(mail[i], "*", 1) + return jsonify({"ok": "ok", "mail": mail}) + except Exception as err: + debug.warning("excetpion in password reset", exc_info=True) + return jsonify({"error": str(err)}), 409 + +@app.route("/logout", methods=['GET']) +@login_required(groups=[MONEY, GASTRO, VORSTAND, EXTERN, USER], bar=True) +def _logout(**kwargs): + try: + debug.info("logout user") + if 'accToken' in kwargs: + accToken = kwargs['accToken'] + debug.debug("accesstoken is {{ {} }}".format(accToken)) + debug.info("delete accesstoken") + accesTokenController.deleteAccessToken(accToken) + debug.info("return ok logout user") + return jsonify({"ok": "ok"}) + except Exception as err: + debug.warning("exception in logout user.", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@app.route("/login", methods=['POST']) +def _login(): + """ Login User + + Nothing to say. + Login in User and create an AccessToken for the User. + + Returns: + A JSON-File with createt Token or Errors + """ + debug.info("Start log in.") + data = request.get_json() + username = data['username'] + password = data['password'] + debug.debug("username is {{ {} }}".format(username)) + try: + user_agent = request.user_agent + debug.info("search {{ {} }} in database".format(username)) + user = mainController.loginUser(username, password) + debug.debug("user is {{ {} }}".format(user)) + token = accesTokenController.createAccesToken(user, user_agent=user_agent) + debug.debug("accesstoken is {{ {} }}".format(token)) + debug.info("validate accesstoken") + dic = accesTokenController.validateAccessToken( + token, [USER, EXTERN]).user.toJSON() + dic["token"] = token + dic["accessToken"] = token + debug.info("User {{ {} }} success login.".format(username)) + debug.info("return login {{ {} }}".format(dic)) + return jsonify(dic) + except PermissionDenied as err: + debug.warning("permission denied exception in logout", exc_info=True) + return jsonify({"error": str(err)}), 401 + except Exception as err: + debug.warning("exception in logout.", exc_info=True) + return jsonify({"error": "permission denied"}), 401 diff --git a/geruecht/static/img/logo.png b/geruecht/static/img/logo.png deleted file mode 100644 index abd2e09..0000000 Binary files a/geruecht/static/img/logo.png and /dev/null differ diff --git a/geruecht/static/img/logo_selected.png b/geruecht/static/img/logo_selected.png deleted file mode 100644 index f27650d..0000000 Binary files a/geruecht/static/img/logo_selected.png and /dev/null differ diff --git a/geruecht/static/master.css b/geruecht/static/master.css deleted file mode 100644 index 3c3c336..0000000 --- a/geruecht/static/master.css +++ /dev/null @@ -1,194 +0,0 @@ -body { - margin: 0 auto; -} - -.topnav { - background-color: #077BCB; - height: 61; - overflow: hidden; -} - -.blue-button { - color: white; - background-color: #055288; - text-align: center; - padding: 5px 5px; - margin: 7px 17px; - text-decoration: none; - font-size: 17px; - border: 5px solid #055288; - border-style: solid; - border-radius: 10px; - transition-duration: 0.4s; -/*box-shadow: 0 8px 16px 0 rgba(0, 0, 0, 2), 0 6px 20px 0 rgba(0, 0, 0, 0.19);*/ -} - -.no-mg { - margin: 0; -} - -.no-pd { - padding: 0; -} - -.blue-button:hover { - background: white; - border: 5px solid #055288; - color: black; -} - -.blue-button:active { - transform: translateY(4px); -} - -.first { - float: left;; - margin-left: 10%; -} - -.last { - float: right; -} - -.logo-nav { - height: 61px; - width: auto; - transition-duration: 0.4s; -} -.logo-nav:active { - transform: translateY(4px) -} - -.logo-nav img { - position: absolute; - transition-duration: 0.4s; -} - -.logo-nav img.main-logo:hover { - opacity: 0; -} - - - -.geruecht { - margin: 5px auto; - display: table; - border: 0px; - border-top: 1px gray; - border-bottom: 1px gray; - border-radius: 15px; - border-style: solid; - width: 100%; - border-spacing: 5px; - height: 30px; -} - -.g-item { - display: table-cell; - text-align: center; - vertical-align: middle; - width: 20%; -} - -.auto-width { - width:6.66%; -} - -.width-auto { - width:80%; -} - -.g-item p { - font-size: 15px; -} - -.button { - width: 70px; - heigt: 30px; - border-radius: 10px; - border: 5px solid green; - background: green; - color: white; - transition-duration: 0.4s; -} - -.button:hover { - color: green; - background: white; -} - -.button:active { - transform: translateY(4px); -} - -.bottombar { - background-color: #077BCB; - overflow: scroll; - position: fixed; - bottom: 0; - width: 100%; - height: 62px; - display: table; -} - -.bottombar-element { - float: left; - line-height: auto; - vertical-align: middle; -} - -.right { - float: right; -} - -.form-group { - float: left; - border: 0; - height: auto; - padding: 5px; - margin: auto; - float: left; - vertical-align: middle; -} - -.reg-label { - color: white; -} - -.m { - margin-top: 10px; -} - -.alert { - color: black; - font-size: 15px; - text-align: center; -} - -.alert-success { - background: lightgreen; - border: 1px solid darkgreen; - color: darkgreen; - border-radius: 5px; - padding: 6px; -} - -.alert-error { - background: darksalmon; - border: 1px solid darkred; - color: darkred; - border-radius: 5px; - padding: 6px; -} - -.container { - margin-bottom: 50%; -} - -.schulden { - color: red; -} - -.bezahlt { - color: green; -} diff --git a/geruecht/templates/about.html b/geruecht/templates/about.html deleted file mode 100644 index 941af53..0000000 --- a/geruecht/templates/about.html +++ /dev/null @@ -1,4 +0,0 @@ -{% extends "layout.html" %} -{% block content %} -

About Page

-{% endblock %} \ No newline at end of file diff --git a/geruecht/templates/finanzer.html b/geruecht/templates/finanzer.html deleted file mode 100644 index def5748..0000000 --- a/geruecht/templates/finanzer.html +++ /dev/null @@ -1,119 +0,0 @@ -{% extends 'layout.html' %} - -{% block content %} -
-
- Username -
-
- Januar -
-
- Februar -
-
- März -
-
- April -
-
- Mai -
-
- Juni -
-
- July -
-
- August -
-
- September -
-
- Oktober -
-
- November -
-
- Dezember -
-
- Schulden -
-
- Ausgleich -
-
- {% for user in users %} -
-
-

{{ user.username }}

-
-
-

{{ "%.2f"%user.jan }} €

-

{{ "%.2f"%user.jan_sub }} €

-
-
-

{{ "%.2f"%user.feb }} €

-

{{ "%.2f"%user.feb_sub }} €

-
-
-

{{ "%.2f"%user.maer }} €

-

{{ "%.2f"%user.maer_sub }} €

-
-
-

{{ "%.2f"%user.apr }} €

-

{{ "%.2f"%user.apr_sub }} €

-
-
-

{{ "%.2f"%user.mai }} €

-

{{ "%.2f"%user.mai_sub }} €

-
-
-

{{ "%.2f"%user.jun }} €

-

{{ "%.2f"%user.jun_sub }} €

-
-
-

{{ "%.2f"%user.jul }} €

-

{{ "%.2f"%user.jul_sub }} €

-
-
-

{{ "%.2f"%user.aug }} €

-

{{ "%.2f"%user.aug_sub }} €

-
-
-

{{ "%.2f"%user.sep }} €

-

{{ "%.2f"%user.sep_sub }} €

-
-
-

{{ "%.2f"%user.okt }} €

-

{{ "%.2f"%user.okt_sub }} €

-
-
-

{{ "%.2f"%user.nov }} €

-

{{ "%.2f"%user.nov_sub }} €

-
-
-

{{ "%.2f"%user.dez }} €

-

{{ "%.2f"%user.dez_sub }} €

-
-
-

{{ "%.2f"%user.getsum() }} €

-
-
- -
-
- {% endfor %} -{% endblock %} -{% block bottombar %} - - -
- Anwenden -
-{% endblock %} diff --git a/geruecht/templates/home.html b/geruecht/templates/home.html deleted file mode 100644 index 7045b52..0000000 --- a/geruecht/templates/home.html +++ /dev/null @@ -1,53 +0,0 @@ -{% extends "layout.html" %} -{% block content %} - {% for user in users %} -
-
-

{{ user.username }}

-
-
- +2 € -
-
- +1 € -
-
- +0,5 € -
-
- +0,4 € -
-
- +0,2 € -
-
- +0,1 € -
-
-

{{ "%.2f"%user.getsum() }} €

-
-
- {% endfor %} -{% endblock %} -{% block bottombar %} -
- {% if form %} -
- {{ form.hidden_tag() }} -
- -
- {{ form.username.label(class="reg-label") }} - {{ form.username() }} -
-
-
- {{ form.submit(class="blue-button no-mg") }} -
-
- {% endif %} -
-
- Stornieren -
-{% endblock %} diff --git a/geruecht/templates/layout.html b/geruecht/templates/layout.html deleted file mode 100644 index a115b51..0000000 --- a/geruecht/templates/layout.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - {% if title %} - {{ title }} - {% else %} - Gerüchteküche - {% endif %} - - - - - - - - - - - - - -
- - - - - {% if current_user.is_authenticated %} - Logout - Übersicht - {% else %} - Finanzer - {% endif %} -
-
- {% block content %} - - {% endblock %} - -
- - - -
- {% with messages = get_flashed_messages(with_categories=true) %} - {% if messages %} - {% for category, message in messages %} -
- {{ message }} -
- {% endfor %} - {% endif %} - {% if form %} - {% if form.username.errors %} - {% for error in form.username.errors %} -
- {{ error }} -
- {% endfor %} - {% endif %} - {% if form.password %} - {% if form.password.errors %} - {% for error in form.password.errors %} -
- {{ error }} -
- {% endfor %} - {% endif %} - {% endif %} - {% endif %} - {% endwith %} -
- {% block bottombar %} - - {% endblock %} -
- - - - - - - diff --git a/geruecht/templates/login.html b/geruecht/templates/login.html deleted file mode 100644 index ab7f0ec..0000000 --- a/geruecht/templates/login.html +++ /dev/null @@ -1,41 +0,0 @@ - -{% extends "layout.html" %} -{% block content %} - -{% endblock %} diff --git a/geruecht/templates/test.html b/geruecht/templates/test.html deleted file mode 100644 index 1d754ff..0000000 --- a/geruecht/templates/test.html +++ /dev/null @@ -1,346 +0,0 @@ - - - Home - - - -
- Finanzer -
- -
-
-

dummy 1

-
-
-

+2 €

-
-
-

+1 €

-
-
-

+0,5 €

-
-
-

+0,4 €

-
-
-

+0,2 €

-
-
-

+0,1 €

-
-
-

Gesamt

-
-
- -
-
-

dummy 1

-
-
-

+2 €

-
-
-

+1 €

-
-
-

+0,5 €

-
-
-

+0,4 €

-
-
-

+0,2 €

-
-
-

+0,1 €

-
-
-

Gesamt

-
-
- -
-
-

dummy 1

-
-
-

+2 €

-
-
-

+1 €

-
-
-

+0,5 €

-
-
-

+0,4 €

-
-
-

+0,2 €

-
-
-

+0,1 €

-
-
-

Gesamt

-
-
- -
-
-

dummy 1

-
-
-

+2 €

-
-
-

+1 €

-
-
-

+0,5 €

-
-
-

+0,4 €

-
-
-

+0,2 €

-
-
-

+0,1 €

-
-
-

Gesamt

-
-
- -
-
-

dummy 1

-
-
-

+2 €

-
-
-

+1 €

-
-
-

+0,5 €

-
-
-

+0,4 €

-
-
-

+0,2 €

-
-
-

+0,1 €

-
-
-

Gesamt

-
-
- -
-
-

dummy 1

-
-
-

+2 €

-
-
-

+1 €

-
-
-

+0,5 €

-
-
-

+0,4 €

-
-
-

+0,2 €

-
-
-

+0,1 €

-
-
-

Gesamt

-
-
- -
-
-

dummy 1

-
-
-

+2 €

-
-
-

+1 €

-
-
-

+0,5 €

-
-
-

+0,4 €

-
-
-

+0,2 €

-
-
-

+0,1 €

-
-
-

Gesamt

-
-
- -
-
-

dummy 1

-
-
-

+2 €

-
-
-

+1 €

-
-
-

+0,5 €

-
-
-

+0,4 €

-
-
-

+0,2 €

-
-
-

+0,1 €

-
-
-

Gesamt

-
-
- -
-
-

dummy 1

-
-
-

+2 €

-
-
-

+1 €

-
-
-

+0,5 €

-
-
-

+0,4 €

-
-
-

+0,2 €

-
-
-

+0,1 €

-
-
-

Gesamt

-
-
- -
-
-

dummy 1

-
-
-

+2 €

-
-
-

+1 €

-
-
-

+0,5 €

-
-
-

+0,4 €

-
-
-

+0,2 €

-
-
-

+0,1 €

-
-
-

Gesamt

-
-
- -
-
-

dummy 1

-
-
-

+2 €

-
-
-

+1 €

-
-
-

+0,5 €

-
-
-

+0,4 €

-
-
-

+0,2 €

-
-
-

+0,1 €

-
-
-

Gesamt

-
-
- -
-
-

dummy 1

-
-
-

+2 €

-
-
-

+1 €

-
-
-

+0,5 €

-
-
-

+0,4 €

-
-
-

+0,2 €

-
-
-

+0,1 €

-
-
-

Gesamt

-
-
- -
-
-
- Name: - -
-
-
-

Stornieren

-
-
- diff --git a/geruecht/user/__init__.py b/geruecht/user/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/geruecht/user/routes.py b/geruecht/user/routes.py new file mode 100644 index 0000000..6b5e3c2 --- /dev/null +++ b/geruecht/user/routes.py @@ -0,0 +1,413 @@ +from flask import Blueprint, request, jsonify +from geruecht.decorator import login_required +import geruecht.controller.mainController as mc +import geruecht.controller.accesTokenController as ac +from geruecht.model import USER +from datetime import datetime, time, date +from geruecht.exceptions import DayLocked +from geruecht.logger import getDebugLogger, getCreditLogger, getJobsLogger +from geruecht.model.accessToken import AccessToken + +user = Blueprint("user", __name__) + +mainController = mc.MainController() +accesTokenController = ac.AccesTokenController() + +debug = getDebugLogger() +creditL = getCreditLogger() +jobL = getJobsLogger() + + +@user.route("/user/main") +@login_required(groups=[USER]) +def _main(**kwargs): + debug.info("/user/main") + try: + if 'accToken' in kwargs: + accToken = kwargs['accToken'] + accToken.user = mainController.getUser(accToken.user.uid) + retVal = accToken.user.toJSON() + retVal['creditList'] = {credit.year: credit.toJSON() + for credit in accToken.user.geruechte} + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception: + debug.debug("exception", exc_info=True) + return jsonify("error", "something went wrong"), 500 + + +@user.route("/user/addAmount", methods=['POST']) +@login_required(groups=[USER]) +def _addAmount(**kwargs): + debug.info("/user/addAmount") + try: + if 'accToken' in kwargs: + accToken = kwargs['accToken'] + data = request.get_json() + amount = int(data['amount']) + date = datetime.now() + mainController.addAmount( + accToken.user.uid, amount, year=date.year, month=date.month) + accToken.user = mainController.getUser(accToken.user.uid) + retVal = accToken.user.toJSON() + retVal['creditList'] = {credit.year: credit.toJSON() + for credit in accToken.user.geruechte} + debug.debug("return {{ {} }}".format(retVal)) + creditL.info("{} {} {} fügt sich selbst {} € Schulden hinzu".format( + date, accToken.user.firstname, accToken.user.lastname, amount/100)) + return jsonify(retVal) + except Exception: + debug.debug("exception", exc_info=True) + return jsonify({"error": "something went wrong"}), 500 + + +@user.route("/user/saveConfig", methods=['POST']) +@login_required(groups=[USER]) +def _saveConfig(**kwargs): + debug.info("/user/saveConfig") + try: + if 'accToken' in kwargs: + accToken = kwargs['accToken'] + data = request.get_json() + password = data['acceptedPassword'] + data.pop('acceptedPassword') + accToken.user = mainController.modifyUser( + accToken.user, data, password) + retVal = accToken.user.toJSON() + retVal['creditList'] = {credit.year: credit.toJSON() + for credit in accToken.user.geruechte} + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 409 + + +@user.route("/user/jobs", methods=['POST']) +@login_required(groups=[USER]) +def _getUsers(**kwrags): + debug.info("/user/jobs") + try: + data = request.get_json() + from_date = data['from_date'] + to_date = data['to_date'] + from_date = datetime( + from_date['year'], from_date['month'], from_date['day']) + to_date = datetime(to_date['year'], to_date['month'], to_date['day']) + lockedDays = mainController.getLockedDays(from_date, to_date) + retVal = [] + for lockedDay in lockedDays: + day = datetime.combine(lockedDay['daydate'], time(12)) + retDay = { + "worker": mainController.getWorker(day), + "day": { + "date": { + "year": day.year, + "month": day.month, + "day": day.day + }, + "locked": lockedDay['locked'] + }, + "jobkinddate": mainController.getJobKindDates(day.date()) + } + retVal.append(retDay) + + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + +@user.route("/user/jobsOnDates", methods=['POST']) +@login_required(groups=[USER]) +def _getJobsOnDates(**kwargs): + debug.info("/user/jobsOnDates") + try: + data = request.get_json() + lockedDays = mainController.getLockedDaysFromList(data) + retVal = [] + for lockedDay in lockedDays: + day = datetime.combine(lockedDay['daydate'], time(12)) + retDay = { + "worker": mainController.getWorker(day), + "day": { + "date": { + "year": day.year, + "month": day.month, + "day": day.day + }, + "locked": lockedDay['locked'] + }, + "jobkinddate": mainController.getJobKindDates(day.date()) + } + retVal.append(retDay) + + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + +@user.route("/user/job", methods=['POST']) +@login_required(groups=[USER]) +def _getUser(**kwargs): + debug.info("/user/job") + try: + data = request.get_json() + day = data['day'] + month = data['month'] + year = data['year'] + date = datetime(year, month, day, 12) + lockedDay = mainController.getLockedDay(date) + if not lockedDay: + lockedDay = { + 'date': { + 'year': year, + 'month': month, + 'day': day + }, + 'locked': False + } + else: + lockedDay = { + 'date': { + 'year': year, + 'month': month, + 'day': day + }, + 'locked': lockedDay['locked'] + } + retVal = { + 'worker': mainController.getWorker(date), + 'day': lockedDay + } + debug.debug("retrun {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@user.route("/user/addJob", methods=['POST']) +@login_required(groups=[USER]) +def _addUser(**kwargs): + debug.info("/user/addJob") + try: + if 'accToken' in kwargs: + accToken = kwargs['accToken'] + user = accToken.user + data = request.get_json() + day = data['day'] + month = data['month'] + year = data['year'] + date = datetime(year, month, day, 12) + job_kind = None + if 'job_kind' in data: + job_kind = data['job_kind'] + mainController.addWorker(user.uid, date, job_kind=job_kind, userExc=True) + retVal = mainController.getWorker(date) + debug.debug("return {{ {} }}".format(retVal)) + jobL.info("Mitglied {} {} schreib sich am {} zum Dienst ein.".format( + user.firstname, user.lastname, date.date())) + return jsonify(retVal) + except DayLocked as err: + debug.debug("exception", exc_info=True) + return jsonify({'error': str(err)}), 403 + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({'error': str(err)}), 409 + + +@user.route("/user/deleteJob", methods=['POST']) +@login_required(groups=[USER]) +def _deletJob(**kwargs): + debug.info("/user/deleteJob") + try: + if 'accToken' in kwargs: + accToken = kwargs['accToken'] + user = accToken.user + data = request.get_json() + day = data['day'] + month = data['month'] + year = data['year'] + date = datetime(year, month, day, 12) + mainController.deleteWorker(user.uid, date, True) + retVal = mainController.getWorker(date) + debug.debug("return ok") + jobL.info("Mitglied {} {} entfernt sich am {} aus dem Dienst".format( + user.firstname, user.lastname, date.date())) + return jsonify(retVal) + except DayLocked as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 403 + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 409 + +@user.route("/user/storno", methods=['POST']) +@login_required(groups=[USER]) +def _storno(**kwargs): + """ Function for Baruser to storno amount + + This function added to the user with the posted userID the posted amount. + + Returns: + JSON-File with userID and the amount + or ERROR 401 Permission Denied + """ + + debug.info("/user/storno") + try: + if 'accToken' in kwargs: + accToken = kwargs['accToken'] + user = accToken.user + data = request.get_json() + amount = int(data['amount']) + + date = datetime.now() + mainController.addCredit( + user.uid, amount, year=date.year, month=date.month) + accToken.user = mainController.getUser(accToken.user.uid) + retVal = accToken.user.toJSON() + retVal['creditList'] = {credit.year: credit.toJSON() + for credit in accToken.user.geruechte} + debug.debug("return {{ {} }}".format(retVal)) + creditL.info("{} {} {} storniert {} €".format( + date, user.firstname, user.lastname, amount/100)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@user.route("/user/getJobInvites", methods=['POST']) +@login_required(groups=[USER]) +def _getJobInvites(**kwargs): + try: + debug.info("/user/getJobInvites") + from_user = None + to_user = None + on_date = None + + data = request.get_json() + + if 'from_user' in data: + from_user = data['from_user'] + if 'to_user' in data: + to_user = data['to_user'] + on_date = date(data['date']['year'], data['date']['month'], data['date']['day']) + retVal = mainController.getJobInvites(from_user, to_user, on_date) + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + +@user.route("/user/JobInvites", methods=['PUT', 'POST']) +@login_required(groups=[USER]) +def _JobInvites(**kwargs): + try: + debug.info("/user/JobInvites") + data = request.get_json() + if request.method == 'PUT': + mainController.setJobInvites(data) + retVal = mainController.getJobInvites(kwargs['accToken'].user.toJSON(), None, datetime.now().date()) + debug.debug("return {{ {} }}".format(retVal)) + if request.method == 'POST': + retVal = mainController.updateJobInvites(data) + + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + +@user.route("/user/deleteJobInvite", methods=['POST']) +@login_required(groups=[USER]) +def _deleteJobInvite(**kwargs): + try: + debug.info("/user/deleteJobInvite") + data = request.get_json() + mainController.deleteJobInvite(data) + retVal = mainController.getJobInvites(data['from_user'], None, datetime.now().date()) + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@user.route("/user/getJobRequests", methods=['POST']) +@login_required(groups=[USER]) +def _getJobRequests(**kwargs): + try: + debug.info("/user/getJobRequests") + from_user = None + to_user = None + on_date = None + + data = request.get_json() + + if 'from_user' in data: + from_user = data['from_user'] + if 'to_user' in data: + to_user = data['to_user'] + on_date = date(data['date']['year'], data['date']['month'], data['date']['day']) + retVal = mainController.getJobRequests(from_user, to_user, on_date) + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + +@user.route("/user/JobRequests", methods=['PUT', 'POST']) +@login_required(groups=[USER]) +def _JobRequests(**kwargs): + try: + debug.info("/user/JobRequests") + data = request.get_json() + if request.method == 'PUT': + mainController.setJobRequests(data) + retVal = mainController.getJobRequests(kwargs['accToken'].user.toJSON(), None, datetime.now().date()) + debug.debug("return {{ {} }}".format(retVal)) + if request.method == 'POST': + data['on_date'] = date(data['on_date']['year'], data['on_date']['month'], data['on_date']['day']) + retVal = mainController.updateJobRequests(data) + + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + +@user.route("/user/deleteJobRequest", methods=['POST']) +@login_required(groups=[USER]) +def _deleteJobRequest(**kwargs): + try: + debug.info("/user/deleteJobRequest") + data = request.get_json() + mainController.deleteJobRequest(data) + retVal = mainController.getJobRequests(data['from_user'], None, datetime.now().date()) + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@user.route("/user/getAccessTokens", methods=['GET', 'POST']) +@login_required(groups=[USER]) +def _getAccessTokens(**kwargs): + try: + debug.info("/user/getAccessTokens") + if request.method == 'POST': + data = request.get_json() + delAccToken = AccessToken(data['id'], kwargs['accToken'].user, None, None, None) + accesTokenController.deleteAccessToken(delAccToken) + tokens = accesTokenController.getAccessTokensFromUser(kwargs['accToken'].user) + retVal = [] + for token in tokens: + retVal.append(token.toJSON()) + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 diff --git a/geruecht/vorstand/__init__.py b/geruecht/vorstand/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/geruecht/vorstand/routes.py b/geruecht/vorstand/routes.py new file mode 100644 index 0000000..143a6c6 --- /dev/null +++ b/geruecht/vorstand/routes.py @@ -0,0 +1,380 @@ +from flask import Blueprint, request, jsonify +from datetime import datetime, time, date +import geruecht.controller.mainController as mc +import geruecht.controller.ldapController as lc +from geruecht.decorator import login_required +from geruecht.model import MONEY, GASTRO, VORSTAND +from geruecht.logger import getDebugLogger, getJobsLogger + +debug = getDebugLogger() +jobL = getJobsLogger() + +vorstand = Blueprint("vorstand", __name__) +mainController = mc.MainController() +ldap = lc.LDAPController() + + +@vorstand.route('/um/setStatus', methods=['POST']) +@login_required(groups=[MONEY, GASTRO, VORSTAND]) +def _setStatus(**kwargs): + debug.info("/um/setStatus") + try: + data = request.get_json() + name = data['name'] + retVal = mainController.setStatus(name) + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@vorstand.route('/um/updateStatus', methods=['POST']) +@login_required(groups=[MONEY, GASTRO, VORSTAND]) +def _updateStatus(**kwargs): + debug.info("/um/updateStatus") + try: + data = request.get_json() + retVal = mainController.updateStatus(data) + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@vorstand.route('/um/deleteStatus', methods=['POST']) +@login_required(groups=[MONEY, GASTRO, VORSTAND]) +def _deleteStatus(**kwargs): + debug.info("/um/deleteStatus") + try: + data = request.get_json() + mainController.deleteStatus(data) + debug.debug("return ok") + return jsonify({"ok": "ok"}) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 409 + + +@vorstand.route('/um/updateStatusUser', methods=['POST']) +@login_required(groups=[MONEY, GASTRO, VORSTAND]) +def _updateStatusUser(**kwargs): + debug.info("/um/updateStatusUser") + try: + data = request.get_json() + username = data['username'] + status = data['status'] + retVal = mainController.updateStatusOfUser(username, status).toJSON() + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@vorstand.route('/um/updateVoting', methods=['POST']) +@login_required(groups=[MONEY, GASTRO, VORSTAND]) +def _updateVoting(**kwargs): + debug.info("/um/updateVoting") + try: + data = request.get_json() + username = data['username'] + voting = data['voting'] + retVal = mainController.updateVotingOfUser(username, voting).toJSON() + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + +@vorstand.route('/um/updateWorkgroups', methods=['POST']) +@login_required(groups=[VORSTAND]) +def _updateWorkgroups(**kwargs): + debug.info("/um/updateWorkgroups") + try: + data = request.get_json() + retVal = mainController.updateWorkgroupsOfUser({"id": data['id']}, data['workgroups']) + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal), 200 + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + +@vorstand.route("/sm/addUser", methods=['POST', 'GET']) +@login_required(groups=[MONEY, GASTRO, VORSTAND]) +def _addUser(**kwargs): + debug.info("/sm/addUser") + try: + data = request.get_json() + user = data['user'] + day = data['day'] + month = data['month'] + year = data['year'] + date = datetime(year, month, day, 12) + job_kind = None + if 'job_kind' in data: + job_kind = data['job_kind'] + retVal = mainController.addWorker(user['username'], date, job_kind=job_kind) + debug.debug("retrun {{ {} }}".format(retVal)) + userl = mainController.getUser(user['username']) + jobL.info("Vorstand {} {} schreibt Mitglied {} {} am {} zum Dienst ein".format( + kwargs['accToken'].user.firstname, kwargs['accToken'].user.lastname, userl.firstname, userl.lastname, date.date())) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@vorstand.route("/sm/getUser", methods=['POST']) +@login_required(groups=[MONEY, GASTRO, VORSTAND]) +def _getUser(**kwargs): + debug.info("/sm/getUser") + try: + data = request.get_json() + day = data['day'] + month = data['month'] + year = data['year'] + date = datetime(year, month, day, 12) + lockedDay = mainController.getLockedDay(date) + lockedDay = { + 'date': { + 'year': year, + 'month': month, + 'day': day + }, + 'locked': lockedDay['locked'] + } + retVal = { + 'worker': mainController.getWorker(date), + 'day': lockedDay + } + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + + +@vorstand.route("/sm/deleteUser", methods=['POST']) +@login_required(groups=[MONEY, GASTRO, VORSTAND]) +def _deletUser(**kwargs): + debug.info("/sm/deletUser") + try: + data = request.get_json() + user = data['user'] + day = data['day'] + month = data['month'] + year = data['year'] + date = datetime(year, month, day, 12) + mainController.deleteWorker(user['username'], date) + debug.debug("return ok") + user = mainController.getUser(user['username']) + jobL.info("Vorstand {} {} entfernt Mitglied {} {} am {} vom Dienst".format( + kwargs['accToken'].user.firstname, kwargs['accToken'].user.lastname, user.firstname, user.lastname, date.date())) + return jsonify({"ok": "ok"}) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + +@vorstand.route("/wgm/getAllWorkgroups", methods=['GET']) +@login_required(bar=True) +def _getAllWorkgroups(**kwargs): + try: + debug.info("get all workgroups") + retVal = mainController.getAllWorkgroups() + debug.info("return all workgroups {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.warning("exception in get all workgroups.", exc_info=True) + return jsonify({"error": str(err)}), 500 + +@vorstand.route("/wgm/getWorkgroup", methods=['POST']) +@login_required(bar=True) +def _getWorkgroup(**kwargs): + try: + debug.info("get workgroup") + data = request.get_json() + name = data['name'] + debug.info("get workgroup {{ {} }}".format(name)) + retVal = mainController.getWorkgroups(name) + debug.info( + "return workgroup {{ {} }} : {{ {} }}".format(name, retVal)) + return jsonify(retVal) + except Exception as err: + debug.warning("exception in get workgroup.", exc_info=True) + return jsonify({"error": str(err)}), 500 + +@vorstand.route("/wgm/workgroup", methods=['POST', 'PUT', 'DELETE']) +@login_required(groups=[MONEY, GASTRO, VORSTAND]) +def _workgroup(**kwargs): + debug.info("/wgm/workgroup") + try: + data = request.get_json() + if request.method == 'PUT': + name = data['name'] + boss = None + if 'boss' in data: + boss = data['boss'] + retVal = mainController.setWorkgroup(name, boss) + debug.debug("return {{ {} }}".format(retVal)) + if request.method == 'POST': + retVal = mainController.updateWorkgroup(data) + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + +@vorstand.route("/wgm/deleteWorkgroup", methods=['POST']) +@login_required(groups=[VORSTAND]) +def _deleteWorkgroup(**kwargs): + try: + data = request.get_json() + debug.info("/wgm/deleteWorkgroup") + mainController.deleteWorkgroup(data) + retVal = {"ok": "ok"} + debug.debug("return ok") + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + +@vorstand.route("/sm/getAllJobKinds", methods=['GET']) +@login_required(bar=True) +def _getAllJobKinds(**kwargs): + try: + debug.info("get all jobkinds") + retVal = mainController.getAllJobKinds() + debug.info("return all jobkinds {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.warning("exception in get all workgroups.", exc_info=True) + return jsonify({"error": str(err)}), 500 + +@vorstand.route("/sm/getJobKind", methods=['POST']) +@login_required(bar=True) +def _getJobKinds(**kwargs): + try: + debug.info("get jobkind") + data = request.get_json() + name = data['name'] + debug.info("get jobkind {{ {} }}".format(name)) + retVal = mainController.getJobKind(name) + debug.info( + "return workgroup {{ {} }} : {{ {} }}".format(name, retVal)) + return jsonify(retVal) + except Exception as err: + debug.warning("exception in get workgroup.", exc_info=True) + return jsonify({"error": str(err)}), 500 + +@vorstand.route("/sm/JobKind", methods=['POST', 'PUT', 'DELETE']) +@login_required(groups=[MONEY, GASTRO, VORSTAND]) +def _JobKinds(**kwargs): + debug.info("/sm/JobKind") + try: + data = request.get_json() + if request.method == 'PUT': + name = data['name'] + workgroup = None + if 'workgroup' in data: + workgroup = data['workgroup'] + retVal = mainController.setJobKind(name, workgroup) + debug.debug("return {{ {} }}".format(retVal)) + if request.method == 'POST': + retVal = mainController.updateJobKind(data) + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + +@vorstand.route("/sm/deleteJobKind", methods=['POST']) +@login_required(groups=[VORSTAND]) +def _deleteJobKind(**kwargs): + try: + data = request.get_json() + debug.info("/sm/deleteJobKind") + mainController.deleteJobKind(data) + retVal = {"ok": "ok"} + debug.debug("return ok") + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + +@vorstand.route("/jk/getJobKindDates", methods=['POST']) +@login_required() +def _getJobKindDates(**kwargs): + try: + debug.info("/jk/getJobKindDates") + data = request.get_json() + datum = date(data['year'], data['month'], data['day']) + retVal = mainController.getJobKindDates(datum) + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + +@vorstand.route("/jk/JobKindDate", methods=['POST']) +@login_required(groups=[VORSTAND]) +def _jobKindDates(**kwargs): + try: + debug.info("/jk/JobKindDate") + data = request.get_json() + retVal = mainController.controllJobKindDates(data) + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 + +@vorstand.route("/sm/lockDay", methods=['POST']) +@login_required(groups=[MONEY, GASTRO, VORSTAND]) +def _lockDay(**kwargs): + debug.info("/sm/lockDay") + try: + data = request.get_json() + year = data['year'] + month = data['month'] + day = data['day'] + locked = data['locked'] + date = datetime(year, month, day, 12) + lockedDay = mainController.setLockedDay(date, locked, True) + if not lockedDay: + retVal = { + 'date': { + 'year': year, + 'month': month, + 'day': day + }, + 'locked': False + } + else: + retVal = { + 'date': { + 'year': year, + 'month': month, + 'day': day + }, + 'locked': lockedDay['locked'] + } + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({'error': err}), 409 + + +@vorstand.route("/sm/searchWithExtern", methods=['GET']) +@login_required(groups=[VORSTAND]) +def _search(**kwargs): + debug.info("/sm/searchWithExtern") + try: + retVal = ldap.getAllUser() + debug.debug("return {{ {} }}".format(retVal)) + return jsonify(retVal) + except Exception as err: + debug.debug("exception", exc_info=True) + return jsonify({"error": str(err)}), 500 diff --git a/packages.txt b/packages.txt new file mode 100644 index 0000000..c852dc5 --- /dev/null +++ b/packages.txt @@ -0,0 +1,20 @@ +bcrypt==3.1.6 +cffi==1.12.3 +Click==7.0 +entrypoints==0.3 +flake8==3.7.7 +Flask==1.0.2 +Flask-Bcrypt==0.7.1 +Flask-Cors==3.0.7 +Flask-SQLAlchemy==2.4.0 +itsdangerous==1.1.0 +Jinja2==2.10.1 +MarkupSafe==1.1.1 +mccabe==0.6.1 +pkg-resources==0.0.0 +pycodestyle==2.5.0 +pycparser==2.19 +pyflakes==2.1.1 +six==1.12.0 +SQLAlchemy==1.3.3 +Werkzeug==0.15.2 diff --git a/required.txt b/required.txt new file mode 100644 index 0000000..1a818f2 --- /dev/null +++ b/required.txt @@ -0,0 +1,14 @@ +click==7.1.2 +Flask==1.1.2 +Flask-Cors==3.0.8 +Flask-LDAPConn==0.10.1 +Flask-MySQLdb==0.2.0 +itsdangerous==1.1.0 +Jinja2==2.11.2 +ldap3==2.7 +MarkupSafe==1.1.1 +mysqlclient==1.4.6 +pyasn1==0.4.8 +PyYAML==5.3.1 +six==1.15.0 +Werkzeug==1.0.1 diff --git a/run.py b/run.py index 1d9622b..b6d40ab 100644 --- a/run.py +++ b/run.py @@ -1,9 +1,9 @@ from geruecht import app - - - - +""" Main + + Start the backend +""" if __name__ == '__main__': app.run(debug=True, host='0.0.0.0') diff --git a/server.crt b/server.crt new file mode 100644 index 0000000..e804409 --- /dev/null +++ b/server.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDazCCAlOgAwIBAgIJAJGH2ozWvd1RMA0GCSqGSIb3DQEBCwUAMFMxCzAJBgNV +BAYTAkRFMQ8wDQYDVQQIDAZTYXhvbnkxEDAOBgNVBAcMB0RyZXNkZW4xITAfBgNV +BAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDAeFw0yMDAxMTcwOTA0MDFaFw0z +MDAxMDQwOTA0MDFaMEQxCzAJBgNVBAYTAkRFMQ8wDQYDVQQIDAZTYXhvbnkxEDAO +BgNVBAcMB0RyZXNkZW4xEjAQBgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN +AQEBBQADggEPADCCAQoCggEBALlkr1UOQypLKicESRnse52d5mAX9MjZQpH0/Y5u +V5WxpPSasmOpt4MRj5MWTfTK2ukj/jLtPAMsggUh7wMXb1uytHj7T5mtiahXBM0H +1sUi2nScXR6doQZlmqKWDGrVS7WHULM01WhirsnxI8S8e6Evpk4F5/RafKA8FgYI +Ongg6S1B16+7T0e/FnILoMjKr1jpgzXnVkPFIneu/qVevSNco5/aw+bc6sjeS/ZA +65dXFGpDlw0lPRHLT5/CgNyMyiLYov7KwMycZw7uxa1ynO+73tqe5tvO/DiMpAPJ +EkrSz/StYBsGJxDhwq5RT31tHVtHhTf0rk1BmaoQJ0Aq7iECAwEAAaNRME8wHwYD +VR0jBBgwFoAUt8P5gBfN9hCUAiWhtPH5fTWnctAwCQYDVR0TBAIwADALBgNVHQ8E +BAMCBPAwFAYDVR0RBA0wC4IJbG9jYWxob3N0MA0GCSqGSIb3DQEBCwUAA4IBAQCD +fBByVq8AbV1DMrY+MElb/nZA5/cuGnUpBpjSlk5OnYHWtywuQk6veiiJ0S2fNfqf +RzwOFuZDHKmIcH0574VssLfUynMKP3w3xb2ZNic3AxAdhzZ6LXLx6+qF5tYcL7oC +UWmj5Mo9SkX5HZLEGamQlVyGOGKNatxep4liyoSeKXr0AOHYfB4AkDhVZn7yQc/v +But42fLBg4mE+rk4UBYOHA4XdoFwqgTCNZq2RxKzvG9LIcok6lOc6gDnfTsH8GqE +byGpfIIQAXF8aftCm4dGXxtzMh8C5d0t2Ell9g+Rr8i/enebT2nJ9B9ptldDjhcZ +7I0ywGsXwrh0EwFsX74/ +-----END CERTIFICATE----- diff --git a/server.key b/server.key new file mode 100644 index 0000000..153fd6b --- /dev/null +++ b/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQC5ZK9VDkMqSyon +BEkZ7HudneZgF/TI2UKR9P2ObleVsaT0mrJjqbeDEY+TFk30ytrpI/4y7TwDLIIF +Ie8DF29bsrR4+0+ZrYmoVwTNB9bFItp0nF0enaEGZZqilgxq1Uu1h1CzNNVoYq7J +8SPEvHuhL6ZOBef0WnygPBYGCDp4IOktQdevu09HvxZyC6DIyq9Y6YM151ZDxSJ3 +rv6lXr0jXKOf2sPm3OrI3kv2QOuXVxRqQ5cNJT0Ry0+fwoDcjMoi2KL+ysDMnGcO +7sWtcpzvu97anubbzvw4jKQDyRJK0s/0rWAbBicQ4cKuUU99bR1bR4U39K5NQZmq +ECdAKu4hAgMBAAECggEABoMQ3Y34sf2d52zxHGYAGZM4SlvND1kCS5otZdleXjW1 +M5pTdci6V3JAdswrxNNzSQkonqVSnFHt5zw/5v3lvXTTfgRl0WIVGcKkuobx9k65 +Gat8YdzrkQv0mI1otj/zvtaX8ROEA3yj4xgDR5/PP+QqlUcD1MNw6TfzFhcn5pxB +/RDPmvarMhzMdDW60Uub6Z7e/kVPuXWrW4bDyULd1d1NoSibnFZi+vGY0Lc1ctDW +2Vl7A8RFTcQi6Cjx/FwgPGJTBE4UMjIBO3wnoPQBMrsSxeGhcarerqIlEafgT4XN +p9BMtRyaXE7TTb1BXc35ZYNJLDLJKQxABhrEHtFreQKBgQDpiGwuKAFK8BLPlbAx +zkShhKd9fhlwm2bfRv3cojPQZsxn0BjefmtrISbKCD79Ivyn7TnOyYAoKAxdp2q9 +wtz94aAXV2lfhUw2lhcb/aw4sXuY/s1XnVyoglOO8pYRCUN0o80pKuWFsaDyy/uL +LhINff1oMNCa7vmMdu8Ccz0o/wKBgQDLOqdTQhSFs4f1yhlDDH3pqT6eKvtFNeRJ +usxYDnAyRXHRqwhQ86z1nBZIgwXqq7PfO9V5Y/l6/2HmmA2ufjS8aBTNpCUMuvJk +y98Z4hTjKRdnVlMUjHq9ahCixJVQ8pcCnWRFdeAwSKhHQiJEFLYeYOIrUeCIYJI4 +FiCshSPI3wKBgGU0ErWZ7p18FprRIs8itYlNhIwUxo+POPCPwloIDO5GblSa0Pwy +yvhdIIMzOaDXtahMXN3pYtmEKX+4msBrnvuC+K7E2cxkZtfNCWy+7RCQkaCG45QR +hOMdv3pWVIRDgHEevz0U8uySQs6VaYgySe6A5/1sEiriX1DpBcEJEbsfAoGAKUCb +rGvSbJ1XsM24OQL1IBQJsON6o77fuxOe3RT5M0sjYnL8OipsZmKrp0ZpUgxOc7ba +i0x+3LewMLWWuV/G5qOd7WwvVRkxkMJNZByfLskthf1g2d/2HjLEc7XBtW+4tYAr +VWoq+sIU3noPKJCnsxzpa++vyx8HLzlWoo5YCDMCgYBJvGH2zMgInlQNO/2XY5nl +E53EZMex+RDq8Wzr4tRM3IrCGc2t8WKEQ/9teKNH0tg9xib0vhqqmiGl1xNfqJVo +ePJyfgFabeUx9goG3mgTdV9woSRlBJso62dM0DAC/jsJoHnVzgokysR4/BfW9Da+ +AYTxRZSNbfmsTHawXqG8Fw== +-----END PRIVATE KEY-----