From d0a9345d68044ffb3c7ef9864d0f01d2f37f747c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20Gr=C3=B6ger?= Date: Sun, 5 Jan 2020 14:15:02 +0100 Subject: [PATCH] added EmailController with the emailController you can send automaticly emails, if a user is over the limit or if the finanzer send the emails the configparser is updated. So you have to set database and ldapconfig. if accestokenlifetime and mailconfig is not set, the parser set default values. --- geruecht/baruser/routes.py | 13 ++++- geruecht/config.yml | 4 +- geruecht/configparser.py | 66 +++++++++++++++++++++-- geruecht/controller/__init__.py | 3 ++ geruecht/controller/databaseController.py | 8 +-- geruecht/controller/emailController.py | 49 +++++++++++++++++ geruecht/controller/ldapController.py | 10 ++-- geruecht/controller/userController.py | 28 +++++++++- geruecht/finanzer/routes.py | 24 ++++++++- geruecht/model/user.py | 6 +++ 10 files changed, 193 insertions(+), 18 deletions(-) create mode 100644 geruecht/controller/emailController.py diff --git a/geruecht/baruser/routes.py b/geruecht/baruser/routes.py index 2ecfaff..f809622 100644 --- a/geruecht/baruser/routes.py +++ b/geruecht/baruser/routes.py @@ -30,7 +30,7 @@ def _bar(): month = geruecht.getMonth(datetime.now().month) amount = month[0] - month[1] all = geruecht.getSchulden() - if amount != 0: + if all != 0: if all >= 0: type = 'credit' else: @@ -106,7 +106,16 @@ def _getUser(): if accToken: data = request.get_json() username = data['userId'] - retVal = userController.getUser(username).toJSON() + user = userController.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 return jsonify(retVal) return jsonify("error", "permission denied"), 401 diff --git a/geruecht/config.yml b/geruecht/config.yml index 2b3e45b..3df779a 100644 --- a/geruecht/config.yml +++ b/geruecht/config.yml @@ -1,9 +1,9 @@ AccessTokenLifeTime: 1800 Database: - URL: 192.168.5.108 + URL: 192.168.5.128 user: wu5 passwd: E1n$tein database: geruecht LDAP: - URL: ldap://192.168.5.108 + URL: ldap://192.168.5.128 dn: dc=ldap,dc=example,dc=local \ No newline at end of file diff --git a/geruecht/configparser.py b/geruecht/configparser.py index ee945e0..247f23c 100644 --- a/geruecht/configparser.py +++ b/geruecht/configparser.py @@ -1,15 +1,68 @@ import yaml +import sys +from . import LOGGER + +default = { + 'AccessTokenLifeTime': 1800, + 'Mail': { + 'URL': '', + 'port': 0, + 'user': '', + 'passwd': '', + 'email': '' + } +} class ConifgParser(): def __init__(self, file='config.yml'): self.file = file with open(file, 'r') as f: - self.config = yaml.load(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"') - print(self.config) self.db = self.config['Database'] + LOGGER.debug("Set Databaseconfig: {}".format(self.db)) + + if 'LDAP' not in self.config: + self.__error__('Wrong Configuration for LDAP. You should configure ldapconfig with "URL" and "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 "dn"') self.ldap = self.config['LDAP'] - self.accessTokenLifeTime = self.config['AccessTokenLifeTime'] + LOGGER.info("Set LDAPconfig: {}".format(self.ldap)) + if 'AccessTokenLifeTime' in self.config: + self.accessTokenLifeTime = self.config['AccessTokenLifeTime'] + LOGGER.info("Set AccessTokenLifeTime: {}".format(self.accessTokenLifeTime)) + else: + self.accessTokenLifeTime = default['AccessTokenLifeTime'] + LOGGER.info("No Config for AccessTokenLifetime found. Set it to default: {}".format(self.accessTokenLifeTime)) + + if 'Mail' not in self.config: + self.config['Mail'] = default['Mail'] + LOGGER.info('No Conifg for Mail found. Set it to defaul: {}'.format(self.config['Mail'])) + if 'URL' not in self.config['Mail']: + self.config['Mail']['URL'] = default['Mail']['URL'] + LOGGER.info("No Config for URL in Mail found. Set it to default") + if 'port' not in self.config['Mail']: + self.config['Mail']['port'] = default['Mail']['port'] + LOGGER.info("No Config for port in Mail found. Set it to default") + else: + self.config['Mail']['port'] = int(self.config['Mail']['port']) + if 'user' not in self.config['Mail']: + self.config['Mail']['user'] = default['Mail']['user'] + LOGGER.info("No Config for user in Mail found. Set it to default") + if 'passwd' not in self.config['Mail']: + self.config['Mail']['passwd'] = default['Mail']['passwd'] + LOGGER.info("No Config for passwd in Mail found. Set it to default") + if 'email' not in self.config['Mail']: + self.config['Mail']['email'] = default['Mail']['email'] + LOGGER.info("No Config for email in Mail found. Set it to default") + self.mail = self.config['Mail'] + LOGGER.info('Set Mailconfig: {}'.format(self.mail)) + def getLDAP(self): return self.ldap @@ -20,5 +73,12 @@ class ConifgParser(): def getAccessToken(self): return self.accessTokenLifeTime + def getMail(self): + return self.mail + + def __error__(self, msg): + LOGGER.error(msg) + sys.exit(-1) + if __name__ == '__main__': ConifgParser() \ No newline at end of file diff --git a/geruecht/controller/__init__.py b/geruecht/controller/__init__.py index efcc892..ed03c81 100644 --- a/geruecht/controller/__init__.py +++ b/geruecht/controller/__init__.py @@ -32,9 +32,12 @@ from .accesTokenController import AccesTokenController dbConfig = config.getDatabase() ldapConfig = config.getLDAP() accConfig = config.getAccessToken() +mailConfig = config.getMail() db = DatabaseController(dbConfig['URL'], dbConfig['user'], dbConfig['passwd'], dbConfig['database']) ldapController = LDAPController(ldapConfig['URL'], ldapConfig['dn']) accesTokenController = AccesTokenController(accConfig) +from . emailController import EmailController +emailController = EmailController(mailConfig['URL'], mailConfig['user'], mailConfig['passwd'], mailConfig['port'], mailConfig['email']) from . userController import UserController userController = UserController() \ No newline at end of file diff --git a/geruecht/controller/databaseController.py b/geruecht/controller/databaseController.py index 9d7fb68..f58cd6c 100644 --- a/geruecht/controller/databaseController.py +++ b/geruecht/controller/databaseController.py @@ -74,8 +74,8 @@ class DatabaseController(metaclass=Singleton): cursor = self.db.cursor() groups = self._convertGroupToString(user.group) try: - cursor.execute("insert into user (uid, dn, firstname, lastname, gruppe, lockLimit, locked, autoLock) VALUES ('{}','{}','{}','{}','{}',{},{},{})".format( - user.uid, user.dn, user.firstname, user.lastname, groups, user.limit, user.locked, user.autoLock)) + 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.commit() except Exception as err: self.db.rollback() @@ -88,8 +88,8 @@ class DatabaseController(metaclass=Singleton): cursor = self.db.cursor() groups = self._convertGroupToString(user.group) try: - sql = "update user set dn='{}', firstname='{}', lastname='{}', gruppe='{}', lockLimit={}, locked={}, autoLock={} where uid='{}'".format( - user.dn, user.firstname, user.lastname, groups, user.limit, user.locked, user.autoLock, user.uid) + 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.commit() diff --git a/geruecht/controller/emailController.py b/geruecht/controller/emailController.py new file mode 100644 index 0000000..23882d8 --- /dev/null +++ b/geruecht/controller/emailController.py @@ -0,0 +1,49 @@ +import smtplib +from datetime import datetime +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText +from email.header import Header +from . import LOGGER + +class EmailController(): + + def __init__(self, smtpServer, user, passwd, port = 587, email = ""): + self.smtpServer = smtpServer + self.port = port + self.user = user + self.passwd = passwd + if email: + self.email = email + else: + self.email = user + + def __connect__(self): + self.smtp = smtplib.SMTP(self.smtpServer, self.port) + self.smtp.starttls() + self.smtp.login(self.user, self.passwd) + + def sendMail(self, user): + try: + if user.mail == 'None' or not user.mail: + LOGGER.debug("cant send email to {}. Has no email-address. {}".format(user.uid, {'error': True, 'user': {'userId': user.uid, 'firstname': user.firstname, 'lastname': user.lastname}})) + raise Exception("no valid Email") + msg = MIMEMultipart() + msg['From'] = self.email + msg['To'] = user.mail + msg['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', 'utf-8') + msg.attach(text) + LOGGER.debug("Send email to {}: '{}'".format(user.uid, msg.as_string())) + self.__connect__() + self.smtp.sendmail(self.email, user.mail, msg.as_string()) + LOGGER.debug("Sended email to {}. {}".format(user.uid, {'error': False, 'user': {'userId': user.uid, 'firstname': user.firstname, 'lastname': user.lastname}})) + return {'error': False, 'user': {'userId': user.uid, 'firstname': user.firstname, 'lastname': user.lastname}} + except Exception: + return {'error': True, 'user': {'userId': user.uid, 'firstname': user.firstname, 'lastname': user.lastname}} \ No newline at end of file diff --git a/geruecht/controller/ldapController.py b/geruecht/controller/ldapController.py index 67ba4c0..7002f44 100644 --- a/geruecht/controller/ldapController.py +++ b/geruecht/controller/ldapController.py @@ -32,7 +32,7 @@ class LDAPController(metaclass=Singleton): def getUserData(self, username): try: self.connect() - search_data = self.client.search_s('ou=user,{}'.format(self.dn), ldap.SCOPE_SUBTREE, 'uid={}'.format(username), ['uid', 'givenName', 'sn']) + search_data = self.client.search_s('ou=user,{}'.format(self.dn), ldap.SCOPE_SUBTREE, 'uid={}'.format(username), ['uid', 'givenName', 'sn', 'mail']) retVal = search_data[0][1] for k,v in retVal.items(): retVal[k] = v[0].decode('utf-8') @@ -79,7 +79,7 @@ class LDAPController(metaclass=Singleton): def getAllUser(self): self.connect() retVal = [] - data = self.client.search_s('ou=user,{}'.format(self.dn), ldap.SCOPE_SUBTREE, attrlist=['uid', 'givenName', 'sn']) + data = self.client.search_s('ou=user,{}'.format(self.dn), ldap.SCOPE_SUBTREE, attrlist=['uid', 'givenName', 'sn', 'mail']) for user in data: if 'uid' in user[1]: username = user[1]['uid'][0].decode('utf-8') @@ -106,13 +106,13 @@ class LDAPController(metaclass=Singleton): name_result.append(self.client.search_s('ou=user,{}'.format(self.dn), ldap.SCOPE_SUBTREE, attrlist=['uid', 'givenName', 'sn'])) else: - name_result.append(self.client.search_s('ou=user,{}'.format(self.dn), ldap.SCOPE_SUBTREE, 'givenName={}'.format(name[0]), ['uid', 'givenName', 'sn'])) - name_result.append(self.client.search_s('ou=user,{}'.format(self.dn), ldap.SCOPE_SUBTREE, 'sn={}'.format(name[0]),['uid', 'givenName', 'sn'])) + name_result.append(self.client.search_s('ou=user,{}'.format(self.dn), ldap.SCOPE_SUBTREE, 'givenName={}'.format(name[0]), ['uid', 'givenName', 'sn', 'mail'])) + name_result.append(self.client.search_s('ou=user,{}'.format(self.dn), ldap.SCOPE_SUBTREE, 'sn={}'.format(name[0]),['uid', 'givenName', 'sn'], 'mail')) else: name_result.append(self.client.search_s('ou=user,{}'.format(self.dn), ldap.SCOPE_SUBTREE, 'givenName={}'.format(name[1]), ['uid', 'givenName', 'sn'])) name_result.append(self.client.search_s('ou=user,{}'.format(self.dn), ldap.SCOPE_SUBTREE, 'sn={}'.format(name[1]), - ['uid', 'givenName', 'sn'])) + ['uid', 'givenName', 'sn', 'mail'])) retVal = [] for names in name_result: diff --git a/geruecht/controller/userController.py b/geruecht/controller/userController.py index fcf3d7e..f027816 100644 --- a/geruecht/controller/userController.py +++ b/geruecht/controller/userController.py @@ -1,4 +1,4 @@ -from . import LOGGER, Singleton, db, ldapController as ldap +from . import LOGGER, Singleton, db, ldapController as ldap, emailController from geruecht.model.user import User from geruecht.exceptions import PermissionDenied from datetime import datetime @@ -24,6 +24,7 @@ class UserController(metaclass=Singleton): if user.autoLock: if user.getGeruecht(year=datetime.now().year).getSchulden() <= (-1*user.limit): user.updateData({'locked': True}) + emailController.sendMail(user) else: user.updateData({'locked': False}) db.updateUser(user) @@ -48,6 +49,9 @@ class UserController(metaclass=Singleton): return user.getGeruecht(year) def getAllUsersfromDB(self): + users = db.getAllUser() + for user in users: + self.__updateGeruechte(user) return db.getAllUser() def getUser(self, username): @@ -63,8 +67,30 @@ class UserController(metaclass=Singleton): user.updateData(user_data) db.updateUser(user) user = db.getUser(username) + self.__updateGeruechte(user) return user + def __updateGeruechte(self, user): + user.getGeruecht(datetime.now().year) + creditLists = user.updateGeruecht() + if user.getGeruecht(datetime.now().year).getSchulden() != 0: + for creditList in creditLists: + db.updateCreditList(creditList) + + def sendMail(self, username): + if type(username) == User: + user = username + if type(username) == str: + user = db.getUser(username) + return emailController.sendMail(user) + + def sendAllMail(self): + retVal = [] + users = db.getAllUser() + for user in users: + retVal.append(self.sendMail(user)) + return retVal + def loginUser(self, username, password): try: user = self.getUser(username) diff --git a/geruecht/finanzer/routes.py b/geruecht/finanzer/routes.py index d72e2fc..4f1894d 100644 --- a/geruecht/finanzer/routes.py +++ b/geruecht/finanzer/routes.py @@ -170,4 +170,26 @@ def _finanzerAddUser(): dic[user.uid]['creditList'] = {credit.year: credit.toJSON() for credit in user.geruechte} LOGGER.debug("ReturnValue is {}".format(dic)) return jsonify(dic), 200 - return jsonify("error:" "permission denied"), 401 \ No newline at end of file + return jsonify({"error": "permission denied"}), 401 + +@finanzer.route("/finanzerSendOneMail", methods=['POST']) +def _finanzerSendOneMail(): + token = request.headers.get("Token") + accToken = accesTokenController.validateAccessToken(token, MONEY) + + if accToken: + data = request.get_json() + username = data['userId'] + retVal = userController.sendMail(username) + return jsonify(retVal) + return jsonify({"error:", "permission denied"}), 401 + +@finanzer.route("/finanzerSendAllMail", methods=['GET']) +def _finanzerSendAllMail(): + token = request.headers.get("Token") + accToken = accesTokenController.validateAccessToken(token, MONEY) + + if accToken: + retVal = userController.sendAllMail() + return jsonify(retVal) + return jsonify({"error": "permission denied"}), 401 \ No newline at end of file diff --git a/geruecht/model/user.py b/geruecht/model/user.py index 85c6b7a..925ca37 100644 --- a/geruecht/model/user.py +++ b/geruecht/model/user.py @@ -27,6 +27,10 @@ class User(): self.firstname = data['firstname'] self.lastname = data['lastname'] self.group = data['gruppe'] + if 'mail' in data: + self.mail = data['mail'] + else: + self.mail = '' if 'lockLimit' in data: self.limit = int(data['lockLimit']) else: @@ -61,6 +65,8 @@ class User(): self.locked = bool(data['locked']) if 'autoLock' in data: self.autoLock = bool(data['autoLock']) + if 'mail' in data: + self.mail = data['mail'] def initGeruechte(self, creditLists): if type(creditLists) == list: