passwordreset hinzugefügt und gitignore verbessert

This commit is contained in:
Tim Gröger 2020-06-28 12:31:58 +02:00
parent d474ef49e8
commit f87d7b9e5d
7 changed files with 109 additions and 5 deletions

1
.gitignore vendored
View File

@ -124,3 +124,4 @@ dmypy.json
# custom
test_pricelist/
test_project/
geruecht.config.yml

View File

@ -0,0 +1,19 @@
AccessTokenLifeTime: 1800
Database:
URL:
user:
passwd:
database:
LDAP:
URL:
dn:
USER_DN:
ADMIN_DN:
ADMIN_SECRET:
Mail:
URL:
port:
user:
passwd:
email:
crypt: SSL/STARTLS

View File

@ -42,6 +42,21 @@ class ConifgParser():
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
self.ldap = self.config['LDAP']
DEBUG.info("Set LDAPconfig: {}".format(self.ldap))
if 'AccessTokenLifeTime' in self.config:

View File

@ -44,7 +44,7 @@ class EmailController():
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']), 'utf-8')
"{} 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)
@ -55,7 +55,7 @@ class EmailController():
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), 'utf-8')
"{} 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)
@ -71,11 +71,22 @@ class EmailController():
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')
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 sendMail(self, user, type='credit', jobtransact=None):
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:
@ -91,6 +102,8 @@ class EmailController():
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))

View File

@ -5,7 +5,7 @@ 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
from ..mainController import mainJobKindController, mainCreditListController, mainPricelistController, mainUserController, mainWorkerController, mainWorkgroupController, mainJobInviteController, mainJobRequestController, mainRegistrationController, mainPasswordReset
db = dc.DatabaseController()
ldap = lc.LDAPController()
@ -23,6 +23,7 @@ class MainController(mainJobKindController.Base,
mainJobInviteController.Base,
mainJobRequestController.Base,
mainRegistrationController.Base,
mainPasswordReset.Base,
metaclass=Singleton):
def __init__(self):

View File

@ -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['USER_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

View File

@ -144,6 +144,22 @@ def _saveLifeTime(**kwargs):
"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):