Fixed Hooks, use own implementation. Fixed routes.

This commit is contained in:
Ferdinand Thiessen 2020-10-16 00:37:57 +02:00
parent 287cc91947
commit ec05cde746
10 changed files with 405 additions and 330 deletions

View File

@ -1,6 +1,6 @@
from pyhooks import precall_register from flaschengeist.system.hook import HookCall
send_message_hook = precall_register("send_message") send_message_hook = HookCall("send_message")
class Plugin: class Plugin:

View File

@ -11,7 +11,7 @@ from werkzeug.local import LocalProxy
from flaschengeist import logger from flaschengeist import logger
from flaschengeist.modules import Plugin from flaschengeist.modules import Plugin
from flaschengeist.system.decorator import login_required from flaschengeist.system.decorator import login_required
from flaschengeist.system.controller import accessTokenController, userController from flaschengeist.system.controller import accessTokenController, userController, messageController
access_controller = LocalProxy(lambda: accessTokenController.AccessTokenController()) access_controller = LocalProxy(lambda: accessTokenController.AccessTokenController())
auth_bp = Blueprint("auth", __name__) auth_bp = Blueprint("auth", __name__)
@ -21,89 +21,96 @@ class AuthRoutePlugin(Plugin):
def __init__(self, conf): def __init__(self, conf):
super().__init__(blueprint=auth_bp) super().__init__(blueprint=auth_bp)
################################################# #################################################
# Routes # # Routes #
# # # #
# /auth POST: login (new token) # # /auth POST: login (new token) #
# GET: get all tokens for user # # GET: get all tokens for user #
# /auth/<token> GET: get lifetime of token # # /auth/<token> GET: get lifetime of token #
# PUT: set new lifetime # # PUT: set new lifetime #
# DELETE: logout / delete token # # DELETE: logout / delete token #
################################################# #################################################
@auth_bp.route("/auth", methods=["POST"])
def _create_token():
"""Login User
Login in User and create an AccessToken for the User. @auth_bp.route("/auth", methods=["POST"])
Requires POST data {'userid': string, 'password': string} def _create_token():
Returns: """Login User
A JSON-File with user information and created token or errors
"""
logger.debug("Start log in.")
data = request.get_json()
try:
userid = data["userid"]
password = data["password"]
except KeyError:
raise BadRequest("Missing parameter(s)")
logger.debug("search user {{ {} }} in database".format(userid)) Login in User and create an AccessToken for the User.
user = userController.login_user(userid, password) Requires POST data {'userid': string, 'password': string}
if not user: Returns:
raise Unauthorized A JSON-File with user information and created token or errors
logger.debug("user is {{ {} }}".format(user)) """
token = access_controller.create(user, user_agent=request.user_agent) logger.debug("Start log in.")
logger.debug("access token is {{ {} }}".format(token)) data = request.get_json()
logger.info("User {{ {} }} success login.".format(userid)) try:
userid = data["userid"]
password = data["password"]
except KeyError:
raise BadRequest("Missing parameter(s)")
# Lets cleanup the DB logger.debug("search user {{ {} }} in database".format(userid))
access_controller.clear_expired() user = userController.login_user(userid, password)
return jsonify({"user": user, "token": token, "permissions": user.get_permissions()}) if not user:
raise Unauthorized
logger.debug("user is {{ {} }}".format(user))
token = access_controller.create(user, user_agent=request.user_agent)
logger.debug("access token is {{ {} }}".format(token))
logger.info("User {{ {} }} success login.".format(userid))
@auth_bp.route("/auth", methods=["GET"]) # Lets cleanup the DB
@login_required() access_controller.clear_expired()
def _get_tokens(access_token, **kwargs): return jsonify({"user": user, "token": token, "permissions": user.get_permissions()})
tokens = access_controller.get_users_tokens(access_token.user)
return jsonify(tokens)
@auth_bp.route("/auth/<token>", methods=["DELETE"])
@login_required() @auth_bp.route("/auth", methods=["GET"])
def _delete_token(token, access_token, **kwargs): @login_required()
logger.debug("Try to delete access token {{ {} }}".format(token)) def _get_tokens(access_token, **kwargs):
token = access_controller.get_token(token, access_token.user) tokens = access_controller.get_users_tokens(access_token.user)
if not token: a = messageController.Message(access_token.user, "Go", "Bar")
logger.debug("Token not found in database!") messageController.send_message(a)
# Return 403 error, so that users can not bruteforce tokens return jsonify(tokens)
# Valid tokens from other users and invalid tokens now are looking the same
raise Forbidden
access_controller.delete_token(token) @login_required()
access_controller.clear_expired() @auth_bp.route("/auth/<token>", methods=["DELETE"])
def _delete_token(token, access_token, **kwargs):
logger.debug("Try to delete access token {{ {} }}".format(token))
token = access_controller.get_token(token, access_token.user)
if not token:
logger.debug("Token not found in database!")
# Return 403 error, so that users can not bruteforce tokens
# Valid tokens from other users and invalid tokens now are looking the same
raise Forbidden
access_controller.delete_token(token)
access_controller.clear_expired()
return jsonify({"ok": "ok"})
@login_required()
@auth_bp.route("/auth/<token>", methods=["GET"])
def _get_token(token, access_token, **kwargs):
logger.debug("get token {{ {} }}".format(token))
token = access_controller.get_token(token, access_token.user)
if not token:
# Return 403 error, so that users can not bruteforce tokens
# Valid tokens from other users and invalid tokens now are looking the same
raise Forbidden
return jsonify(token)
@login_required()
@auth_bp.route("/auth/<token>", methods=["PUT"])
def _set_lifetime(token, access_token, **kwargs):
token = access_controller.get_token(token, access_token.user)
if not token:
# Return 403 error, so that users can not bruteforce tokens
# Valid tokens from other users and invalid tokens now are looking the same
raise Forbidden
try:
lifetime = request.get_json()["value"]
logger.debug("set lifetime {{ {} }} to access token {{ {} }}".format(lifetime, token))
access_controller.set_lifetime(token, lifetime)
return jsonify({"ok": "ok"}) return jsonify({"ok": "ok"})
except (KeyError, TypeError):
@auth_bp.route("/auth/<token>", methods=["GET"]) raise BadRequest
@login_required()
def _get_token(token, access_token, **kwargs):
logger.debug("get token {{ {} }}".format(token))
token = access_controller.get_token(token, access_token.user)
if not token:
# Return 403 error, so that users can not bruteforce tokens
# Valid tokens from other users and invalid tokens now are looking the same
raise Forbidden
return jsonify(token)
@auth_bp.route("/auth/<token>", methods=["PUT"])
@login_required()
def _set_lifetime(token, access_token, **kwargs):
token = access_controller.get_token(token, access_token.user)
if not token:
# Return 403 error, so that users can not bruteforce tokens
# Valid tokens from other users and invalid tokens now are looking the same
raise Forbidden
try:
lifetime = request.get_json()["value"]
logger.debug("set lifetime {{ {} }} to access token {{ {} }}".format(lifetime, token))
access_controller.set_lifetime(token, lifetime)
return jsonify({"ok": "ok"})
except (KeyError, TypeError):
raise BadRequest

View File

@ -1,6 +1,8 @@
import smtplib import smtplib
from email.mime.multipart import MIMEMultipart from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from flaschengeist import logger
from flaschengeist.system.models.user import User from flaschengeist.system.models.user import User
from flaschengeist.system.controller import userController from flaschengeist.system.controller import userController
from flaschengeist.system.controller.messageController import Message from flaschengeist.system.controller.messageController import Message
@ -18,9 +20,15 @@ class MailMessagePlugin(Plugin):
self.crypt = config["CRYPT"] self.crypt = config["CRYPT"]
self.mail = config["MAIL"] self.mail = config["MAIL"]
@send_message_hook @send_message_hook
def dummy_send(msg):
self.send_mail(msg)
def send_mail(self, msg: Message): def send_mail(self, msg: Message):
if isinstance(msg.receiver, User): if isinstance(msg.receiver, User):
if not msg.receiver.mail:
logger.warn("Could not send Mail, mail missing: {}".format(msg.receiver))
return
recipients = [msg.receiver.mail] recipients = [msg.receiver.mail]
else: else:
recipients = userController.get_user_by_role(msg.receiver) recipients = userController.get_user_by_role(msg.receiver)
@ -29,15 +37,17 @@ class MailMessagePlugin(Plugin):
mail["From"] = self.mail mail["From"] = self.mail
mail["To"] = ", ".join(recipients) mail["To"] = ", ".join(recipients)
mail["Subject"] = msg.subject mail["Subject"] = msg.subject
msg.attach(msg.message) mail.attach(MIMEText(msg.message))
if not self.smtp: if not hasattr(self, "smtp"):
self.__connect() self.__connect()
self.smtp.sendmail(self.mail, recipients, msg.as_string()) self.smtp.sendmail(self.mail, recipients, mail.as_string())
def __connect(self): def __connect(self):
if self.crypt == "SSL": if self.crypt == "SSL":
self.smtp = smtplib.SMTP_SSL(self.server, self.port) self.smtp = smtplib.SMTP_SSL(self.server, self.port)
if self.crypt == "STARTTLS": elif self.crypt == "STARTTLS":
self.smtp = smtplib.SMTP(self.smtpServer, self.port) self.smtp = smtplib.SMTP(self.server, self.port)
self.smtp.starttls() self.smtp.starttls()
else:
raise ValueError("Invalid CRYPT given")
self.smtp.login(self.user, self.password) self.smtp.login(self.user, self.password)

View File

@ -12,67 +12,73 @@ class RolesPlugin(Plugin):
def __init__(self, config): def __init__(self, config):
super().__init__(config, roles_bp) super().__init__(config, roles_bp)
###################################################### ######################################################
# Routes # # Routes #
# # # #
# /roles POST: register new # # /roles POST: register new #
# GET: get all roles # # GET: get all roles #
# /roles/permissions GET: get all permissions # # /roles/permissions GET: get all permissions #
# /roles/<rid> GET: get role with rid # # /roles/<rid> GET: get role with rid #
# PUT: modify role / permission # # PUT: modify role / permission #
# DELETE: remove role # # DELETE: remove role #
###################################################### ######################################################
@roles_bp.route("/roles", methods=["POST"])
@login_required()
def add_role(self):
data = request.get_json()
if not data or "name" not in data:
raise BadRequest
if "permissions" in data:
permissions = data["permissions"]
role = roleController.create_role(data["name"], permissions)
return jsonify({"ok": "ok", "id": role.id})
@roles_bp.route("/roles", methods=["GET"]) @roles_bp.route("/roles", methods=["POST"])
@login_required() @login_required()
def list_roles(self, **kwargs): def add_role(self):
roles = roleController.get_roles() data = request.get_json()
return jsonify(roles) if not data or "name" not in data:
raise BadRequest
if "permissions" in data:
permissions = data["permissions"]
role = roleController.create_role(data["name"], permissions)
return jsonify({"ok": "ok", "id": role.id})
@roles_bp.route("/roles/permissions", methods=["GET"])
@login_required()
def list_permissions(self, **kwargs):
permissions = roleController.get_permissions()
return jsonify(permissions)
@roles_bp.route("/roles/<rid>", methods=["GET"]) @roles_bp.route("/roles", methods=["GET"])
@login_required() @login_required()
def __get_role(self, rid, **kwargs): def list_roles(**kwargs):
role = roleController.get_role(rid) roles = roleController.get_roles()
if role: return jsonify(roles)
return jsonify({"id": role.id, "name": role, "permissions": role.permissions})
@roles_bp.route("/roles/permissions", methods=["GET"])
@login_required()
def list_permissions(**kwargs):
permissions = roleController.get_permissions()
return jsonify(permissions)
@roles_bp.route("/roles/<rid>", methods=["GET"])
@login_required()
def __get_role(rid, **kwargs):
role = roleController.get_role(rid)
if role:
return jsonify({"id": role.id, "name": role, "permissions": role.permissions})
raise NotFound
@roles_bp.route("/roles/<rid>", methods=["PUT"])
@login_required()
def __edit_role(rid, **kwargs):
role = roleController.get_role(rid)
if not role:
raise NotFound raise NotFound
@roles_bp.route("/roles/<rid>", methods=["PUT"]) data = request.get_json()
@login_required() if "name" in data:
def __edit_role(self, rid, **kwargs): role.name = data["name"]
role = roleController.get_role(rid) if "permissions" in data:
if not role: roleController.set_permissions(role, data["permissions"])
raise NotFound roleController.update_role(role)
return jsonify({"ok": "ok"})
data = request.get_json()
if "name" in data:
role.name = data["name"]
if "permissions" in data:
roleController.set_permissions(role, data["permissions"])
roleController.update_role(role)
return jsonify({"ok": "ok"})
@roles_bp.route("/roles/<rid>", methods=["DELETE"]) @roles_bp.route("/roles/<rid>", methods=["DELETE"])
@login_required() @login_required()
def __delete_role(self, rid, **kwargs): def __delete_role(rid, **kwargs):
if not roleController.delete_role(rid): if not roleController.delete_role(rid):
raise NotFound raise NotFound
return jsonify({"ok": "ok"}) return jsonify({"ok": "ok"})

View File

@ -16,171 +16,184 @@ class SchedulePlugin(Plugin):
def __init__(self, config): def __init__(self, config):
super().__init__(blueprint=schedule_bp) super().__init__(blueprint=schedule_bp)
#################################################################################### ####################################################################################
# Routes # # Routes #
# # # #
# /schedule/events POST: create new # # /schedule/events POST: create new #
# GET: get all events this month # # GET: get all events this month #
# /schedule/events/<year>/<month> GET: get events by month / date # # /schedule/events/<year>/<month> GET: get events by month / date #
# /<year>/<month>/<day> # # /<year>/<month>/<day> #
# /schedule/events/<id> GET: get event by ID # # /schedule/events/<id> GET: get event by ID #
# DELETE: delete specified event # # DELETE: delete specified event #
# PUT: modify specified event # # PUT: modify specified event #
# /schedule/events/<id>/slots GET: get EventSlots of Event # # /schedule/events/<id>/slots GET: get EventSlots of Event #
# POST: add new EventSlot to Event # # POST: add new EventSlot to Event #
# /schedule/events/<id>/slots/<sid> PUT: modify EventSlot # # /schedule/events/<id>/slots/<sid> PUT: modify EventSlot #
# GET: get specified EventSlot # # GET: get specified EventSlot #
# /schedule/events/<id>/slots/<sid>/jobs POST: add User # # /schedule/events/<id>/slots/<sid>/jobs POST: add User #
# /schedule/eventKinds # /schedule/eventKinds
# /schedule/eventKinds/<id> # /schedule/eventKinds/<id>
# PUT: modify user # # PUT: modify user #
# DELETE: remove user # # DELETE: remove user #
#################################################################################### ####################################################################################
@schedule_bp.route("/events/<int:id>", methods=["GET"])
@login_required() # roles=['schedule_read'])
def __get_event(self, id, **kwargs):
event = eventController.get_event(id)
if not event:
raise NotFound
return jsonify(event)
@schedule_bp.route("/events", methods=["GET"]) @schedule_bp.route("/events/<int:id>", methods=["GET"])
@schedule_bp.route("/events/<int:year>/<int:month>", methods=["GET"]) @login_required() # roles=['schedule_read'])
@schedule_bp.route("/events/<int:year>/<int:month>/<int:day>", methods=["GET"]) def __get_event(self, id, **kwargs):
@login_required() # roles=['schedule_read']) event = eventController.get_event(id)
def __get_events(self, year=datetime.now().year, month=datetime.now().month, day=None, **kwrags): if not event:
"""Get Event objects for specified date (or month or year), raise NotFound
if nothing set then events for current month are returned return jsonify(event)
Args:
year (int, optional): year to query, defaults to current year @schedule_bp.route("/events", methods=["GET"])
month (int, optional): month to query (if set), defaults to current month @schedule_bp.route("/events/<int:year>/<int:month>", methods=["GET"])
day (int, optional): day to query events for (if set) @schedule_bp.route("/events/<int:year>/<int:month>/<int:day>", methods=["GET"])
**kwrags: contains at least access_token (see flaschengeist.decorator) @login_required() # roles=['schedule_read'])
Returns: def __get_events(year=datetime.now().year, month=datetime.now().month, day=None, **kwargs):
JSON list containing events found """Get Event objects for specified date (or month or year),
Raises: if nothing set then events for current month are returned
BadRequest: If date is invalid
""" Args:
try: year (int, optional): year to query, defaults to current year
begin = datetime(year=year, month=month, day=1) month (int, optional): month to query (if set), defaults to current month
if day: day (int, optional): day to query events for (if set)
begin += timedelta(days=day - 1) **kwargs: contains at least access_token (see flaschengeist.decorator)
end = begin + timedelta(days=1) Returns:
JSON list containing events found
Raises:
BadRequest: If date is invalid
"""
try:
begin = datetime(year=year, month=month, day=1)
if day:
begin += timedelta(days=day - 1)
end = begin + timedelta(days=1)
else:
if month == 12:
end = datetime(year=year + 1, month=1, day=1)
else: else:
if month == 12: end = datetime(year=year, month=month + 1, day=1)
end = datetime(year=year + 1, month=1, day=1)
else:
end = datetime(year=year, month=month + 1, day=1)
events = eventController.get_events(begin, end) events = eventController.get_events(begin, end)
return jsonify(events) return jsonify(events)
except ValueError: except ValueError:
raise BadRequest("Invalid date given") raise BadRequest("Invalid date given")
@schedule_bp.route("/eventKinds", methods=["POST"])
@login_required()
def __new_event_kind(self, **kwargs):
data = request.get_json()
if "name" not in data:
raise BadRequest
kind = eventController.create_event_kind(data["name"])
return jsonify({"ok": "ok", "id": kind.id})
@schedule_bp.route("/slotKinds", methods=["POST"]) @schedule_bp.route("/eventKinds", methods=["POST"])
@login_required() @login_required()
def __new_slot_kind(self, **kwargs): def __new_event_kind(**kwargs):
data = request.get_json() data = request.get_json()
if not data or "name" not in data: if "name" not in data:
raise BadRequest raise BadRequest
kind = eventController.create_job_kind(data["name"]) kind = eventController.create_event_kind(data["name"])
return jsonify({"ok": "ok", "id": kind.id}) return jsonify({"ok": "ok", "id": kind.id})
@schedule_bp.route("/events", methods=["POST"])
@login_required()
def __new_event(self, **kwargs):
data = request.get_json()
event = eventController.create_event(
begin=parser.isoparse(data["begin"]),
end=parser.isoparse(data["end"]),
description=data["description"],
kind=EventKind.query.get(data["kind"]),
)
return jsonify({"ok": "ok", "id": event.id})
@schedule_bp.route("/events/<int:id>", methods=["DELETE"]) @schedule_bp.route("/slotKinds", methods=["POST"])
@login_required() @login_required()
def __delete_event(self, id, **kwargs): def __new_slot_kind(**kwargs):
if not eventController.delete_event(id): data = request.get_json()
raise NotFound if not data or "name" not in data:
db.session.commit() raise BadRequest
return jsonify({"ok": "ok"}) kind = eventController.create_job_kind(data["name"])
return jsonify({"ok": "ok", "id": kind.id})
@schedule_bp.route("/eventKinds/<int:id>", methods=["PUT"])
@login_required()
def __edit_event_kind(self, id, **kwargs):
data = request.get_json()
if not data or "name" not in data:
raise BadRequest
eventController.rename_event_kind(id, data["name"])
return jsonify({"ok": "ok"})
@schedule_bp.route("/events/<int:event_id>/slots", methods=["GET"]) @schedule_bp.route("/events", methods=["POST"])
@login_required() @login_required()
def __get_slots(self, event_id, **kwargs): def __new_event(**kwargs):
event = eventController.get_event(event_id) data = request.get_json()
if not event: event = eventController.create_event(
raise NotFound begin=parser.isoparse(data["begin"]),
return jsonify({event.slots}) end=parser.isoparse(data["end"]),
description=data["description"],
kind=EventKind.query.get(data["kind"]),
)
return jsonify({"ok": "ok", "id": event.id})
@schedule_bp.route("/events/<int:event_id>/slots/<int:slot_id>", methods=["GET"])
@login_required() @schedule_bp.route("/events/<int:event_id>", methods=["DELETE"])
def __get_slot(self, event_id, slot_id, **kwargs): @login_required()
slot = eventController.get_event_slot(slot_id, event_id) def __delete_event(event_id, **kwargs):
if slot: if not eventController.delete_event(event_id):
return jsonify(slot)
raise NotFound raise NotFound
db.session.commit()
return jsonify({"ok": "ok"})
@schedule_bp.route("/events/<int:event_id>/slots/<int:slot_id>", methods=["DELETE"])
@login_required() @schedule_bp.route("/eventKinds/<int:event_id>", methods=["PUT"])
def __delete_slot(self, event_id, slot_id, **kwargs): @login_required()
if eventController.delete_event_slot(slot_id, event_id): def __edit_event_kind(event_id, **kwargs):
return jsonify({"ok": "ok"}) data = request.get_json()
if not data or "name" not in data:
raise BadRequest
eventController.rename_event_kind(event_id, data["name"])
return jsonify({"ok": "ok"})
@schedule_bp.route("/events/<int:event_id>/slots", methods=["GET"])
@login_required()
def __get_slots(event_id, **kwargs):
event = eventController.get_event(event_id)
if not event:
raise NotFound raise NotFound
return jsonify({event.slots})
@schedule_bp.route("/events/<int:event_id>/slots/<int:slot_id>", methods=["PUT"])
@login_required()
def __update_slot(self, event_id, slot_id, **kwargs):
data = request.get_json()
if not data:
raise BadRequest
@schedule_bp.route("/events/<int:event_id>/slots/<int:slot_id>", methods=["GET"])
@login_required()
def __get_slot(event_id, slot_id, **kwargs):
slot = eventController.get_event_slot(slot_id, event_id)
if slot:
return jsonify(slot)
raise NotFound
@schedule_bp.route("/events/<int:event_id>/slots/<int:slot_id>", methods=["DELETE"])
@login_required()
def __delete_slot(event_id, slot_id, **kwargs):
if eventController.delete_event_slot(slot_id, event_id):
return jsonify({"ok": "ok"})
raise NotFound
@schedule_bp.route("/events/<int:event_id>/slots/<int:slot_id>", methods=["PUT"])
@login_required()
def __update_slot(event_id, slot_id, **kwargs):
data = request.get_json()
if not data:
raise BadRequest
for job in data["jobs"]:
eventController.add_job(job.kind, job.user)
if eventController.delete_event_slot(slot_id, event_id):
return jsonify({"ok": "ok"})
raise NotFound
@schedule_bp.route("/events/<int:event_id>/slots", methods=["POST"])
@login_required()
def __add_slot(event_id, **kwargs):
event = eventController.get_event(event_id)
if not event:
raise NotFound
data = request.get_json()
attr = {"job_slots": []}
try:
if "start" in data:
attr["start"] = parser.isoparse(data["start"])
if "end" in data:
attr["end"] = parser.isoparse(data["end"])
for job in data["jobs"]: for job in data["jobs"]:
eventController.add_job(job.kind, job.user) attr["job_slots"].append({"needed_persons": job["needed_persons"], "kind": job["kind"]})
if eventController.delete_event_slot(slot_id, event_id): except KeyError:
return jsonify({"ok": "ok"}) raise BadRequest("Missing data in request")
raise NotFound eventController.add_slot(event, **attr)
return jsonify({"ok": "ok"})
@schedule_bp.route("/events/<int:event_id>/slots", methods=["POST"])
@login_required()
def __add_slot(self, event_id, **kwargs):
event = eventController.get_event(event_id)
if not event:
raise NotFound
data = request.get_json()
attr = {"job_slots": []}
try:
if "start" in data:
attr["start"] = parser.isoparse(data["start"])
if "end" in data:
attr["end"] = parser.isoparse(data["end"])
for job in data["jobs"]:
attr["job_slots"].append({"needed_persons": job["needed_persons"], "kind": job["kind"]})
except KeyError:
raise BadRequest("Missing data in request")
eventController.add_slot(event, **attr)
return jsonify({"ok": "ok"})
def __edit_event(self): def __edit_event():
... ...

View File

@ -24,45 +24,49 @@ class UsersPlugin(Plugin):
# DELETE: remove user # # DELETE: remove user #
################################################# #################################################
@users_bp.route("/users", methods=["POST"])
def __registration(self):
logger.debug("Register new User...")
return jsonify({"ok": "ok... well not implemented"})
@users_bp.route("/users", methods=["GET"]) @users_bp.route("/users", methods=["POST"])
@login_required() def __registration(self):
def __list_users(self, **kwargs): logger.debug("Register new User...")
logger.debug("Retrieve list of all users") return jsonify({"ok": "ok... well not implemented"})
users = userController.get_users()
return jsonify(users)
@users_bp.route("/users/<uid>", methods=["GET"])
@login_required() @users_bp.route("/users", methods=["GET"])
def __get_user(self, uid, **kwargs): @login_required()
logger.debug("Get information of user {{ {} }}".format(uid)) def __list_users(**kwargs):
user = userController.get_user(uid) logger.debug("Retrieve list of all users")
if user: users = userController.get_users()
return jsonify(user) return jsonify(users)
@users_bp.route("/users/<uid>", methods=["GET"])
@login_required()
def __get_user(uid, **kwargs):
logger.debug("Get information of user {{ {} }}".format(uid))
user = userController.get_user(uid)
if user:
return jsonify(user)
raise NotFound
@users_bp.route("/users/<uid>", methods=["PUT"])
@login_required()
def __edit_user(uid, **kwargs):
logger.debug("Modify information of user {{ {} }}".format(uid))
user = userController.get_user(uid)
if not user:
raise NotFound raise NotFound
@users_bp.route("/users/<uid>", methods=["PUT"]) if uid != kwargs["access_token"].user.uid and user.has_permissions(permissions["EDIT_USER"]):
@login_required() return Forbidden
def __edit_user(self, uid, **kwargs):
logger.debug("Modify information of user {{ {} }}".format(uid))
user = userController.get_user(uid)
if not user:
raise NotFound
if uid != kwargs["access_token"].user.uid and user.has_permissions(permissions["EDIT_USER"]): data = request.get_json()
return Forbidden if "password" not in data:
raise BadRequest("Password is missing")
data = request.get_json() for key in ["firstname", "lastname", "display_name", "mail"]:
if "password" not in data: if key in data:
raise BadRequest("Password is missing") setattr(user, key, data[key])
for key in ["firstname", "lastname", "display_name", "mail"]: new_password = data["new_password"] if "new_password" in data else None
if key in data: userController.modify_user(user, data["password"], new_password)
setattr(user, key, data[key]) userController.update_user(user)
new_password = data["new_password"] if "new_password" in data else None return jsonify({"ok": "ok"})
userController.modify_user(user, data["password"], new_password)
userController.update_user(user)
return jsonify({"ok": "ok"})

View File

@ -28,7 +28,22 @@ or with debug messages:
run_flaschengeist --debug run_flaschengeist --debug
## Development ## Development
### Code Style
We enforce you to use PEP 8 code style with a line length of 120 as used by Black.
See also [Black Code Style](https://github.com/psf/black/blob/master/docs/the_black_code_style.md).
#### Code formatting
We use [Black](https://github.com/psf/black) as the code formatter.
Installation:
pip install black
Usage:
black -l 120 DIRECTORY_OR_FILE
### Misc ### Misc
#### Git blame
When using `git blame` use this to ignore the code formatting commits: When using `git blame` use this to ignore the code formatting commits:
$ git blame FILE.py --ignore-revs-file .git-blame-ignore-revs $ git blame FILE.py --ignore-revs-file .git-blame-ignore-revs

View File

@ -1,5 +1,6 @@
from flaschengeist import logger
from flaschengeist.system.hook import Hook
from flaschengeist.system.models.user import User, Role from flaschengeist.system.models.user import User, Role
from pyhooks import Hook
class Message: class Message:

View File

@ -0,0 +1,20 @@
_hook_dict = {}
class Hook(object):
def __init__(self, function):
self.function = function
def __call__(self, *args, **kwargs):
if self.function.__name__ in _hook_dict:
_hook_dict[self.function.__name__](*args, **kwargs)
self.function(*args, **kwargs)
class HookCall(object):
def __init__(self, name):
self.name = name
def __call__(self, function):
_hook_dict[self.name] = function
return function

View File

@ -19,7 +19,6 @@ setup(
"werkzeug", "werkzeug",
"bjoern", "bjoern",
"python-dateutil", "python-dateutil",
"pyhooks",
], ],
extras_require={"ldap": ["flask_ldapconn", "ldap3"]}, extras_require={"ldap": ["flask_ldapconn", "ldap3"]},
entry_points={ entry_points={