import json import logging import pydapper import bcrypt from ..schemas import model from .. import local_db from BreCal.database.sql_queries import SQLQuery, create_sql_query_user_put def PutUser(schemaModel): """ :param schemaModel: The deserialized dict of the request """ # This updates an *existing* entry pooledConnection = None try: pooledConnection = local_db.getPoolConnection() commands = pydapper.using(pooledConnection) # test if object to update is found sentinel = object() # query = SQLQuery.get_user_by_id() # theuser = commands.query_single_or_default(query, sentinel, param={"id" : schemaModel["id"]}, model=model.User) theuser = commands.query_single_or_default("SELECT * FROM user where id = ?id?", sentinel, param={"id" : schemaModel["id"]}, model=model.User) if theuser is sentinel: # #TODO: result = {"message":"no such record"} -> json.dumps return json.dumps("no such record"), 404, {'Content-Type': 'application/json; charset=utf-8'} # see if we need to update public fields # #TODO_determine: this filter blocks Put-Requests, which update the 'notify_email', 'notify_whatsapp', 'notify_signal', 'notify_popup' fields # should this be refactored? # Also, what about the 'user_name'? # 'participant_id' would also not trigger an update in isolation if "first_name" in schemaModel or "last_name" in schemaModel or "user_phone" in schemaModel or "user_email" in schemaModel or "notify_email" in schemaModel or "notify_whatsapp" in schemaModel or "notify_signal" in schemaModel or "notify_popup" in schemaModel or "notify_on" in schemaModel: # query = SQLQuery.get_user_put(schemaModel) query = "UPDATE user SET " isNotFirst = False for key in schemaModel.keys(): if key == "id": continue if key == "old_password": continue if key == "new_password": continue if isNotFirst: query += ", " isNotFirst = True if key != "notify_on": query += key + " = ?" + key + "? " else: flag_value = model.list_to_bitflag(schemaModel["notify_on"]) query += "notify_event = " + str(flag_value) + " " query += "WHERE id = ?id?" affected_rows = commands.execute(query, param=schemaModel) # update password if available and old pw is (correctly!) given if "old_password" in schemaModel and schemaModel["old_password"] and "new_password" in schemaModel and schemaModel["new_password"]: if bcrypt.checkpw(schemaModel["old_password"].encode("utf-8"), bytes(theuser.password_hash, "utf-8")): # old pw matches password_hash = bcrypt.hashpw(schemaModel["new_password"].encode('utf-8'), bcrypt.gensalt( 12 )).decode('utf8') # query = SQLQuery.get_update_user_password() query = "UPDATE user SET password_hash = ?password_hash? WHERE id = ?id?" commands.execute(query, param={"password_hash" : password_hash, "id" : schemaModel["id"]}) else: result = {} result["error_field"] = "old password invalid" return json.dumps(result), 400, {'Content-Type': 'application/json; charset=utf-8'} return json.dumps({"id" : schemaModel["id"]}), 200 except Exception as ex: logging.error(ex) print(ex) result = {} result["error_field"] = "call failed" return json.dumps(result), 500, {'Content-Type': 'application/json; charset=utf-8'} finally: if pooledConnection is not None: pooledConnection.close()