Added some permissions, reworked permission system.
This commit is contained in:
parent
ba0c76a727
commit
d3a2b40834
|
@ -18,10 +18,7 @@ class Plugin:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
return {
|
return {"version": self.version, "permissions": self.permissions}
|
||||||
"version": self.version,
|
|
||||||
"permissions": self.permissions
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class AuthPlugin(Plugin):
|
class AuthPlugin(Plugin):
|
||||||
|
@ -38,7 +35,7 @@ class AuthPlugin(Plugin):
|
||||||
|
|
||||||
def update_user(self, user):
|
def update_user(self, user):
|
||||||
"""If backend is using external data, then update this user instance with external data
|
"""If backend is using external data, then update this user instance with external data
|
||||||
|
)
|
||||||
Args:
|
Args:
|
||||||
user: User object
|
user: User object
|
||||||
"""
|
"""
|
||||||
|
@ -57,3 +54,12 @@ class AuthPlugin(Plugin):
|
||||||
Error: Other errors if backend went mad (are not handled and will result in a 500 error)
|
Error: Other errors if backend went mad (are not handled and will result in a 500 error)
|
||||||
"""
|
"""
|
||||||
raise NotImplemented
|
raise NotImplemented
|
||||||
|
|
||||||
|
def delete_user(self, user):
|
||||||
|
"""If backend is using (writeable) external data, then delete the user from external database.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
user: User object
|
||||||
|
|
||||||
|
"""
|
||||||
|
pass
|
||||||
|
|
|
@ -6,12 +6,13 @@ from flaschengeist.system.decorator import login_required
|
||||||
from flaschengeist.system.controller import roleController
|
from flaschengeist.system.controller import roleController
|
||||||
|
|
||||||
roles_bp = Blueprint("roles", __name__)
|
roles_bp = Blueprint("roles", __name__)
|
||||||
roles_permission = "roles_edit"
|
_permission_edit = "roles_edit"
|
||||||
|
_permission_delete = "roles_delete"
|
||||||
|
|
||||||
|
|
||||||
class RolesPlugin(Plugin):
|
class RolesPlugin(Plugin):
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
super().__init__(config, roles_bp, permissions=[roles_permission])
|
super().__init__(config, roles_bp, permissions=[_permission_edit, _permission_delete])
|
||||||
|
|
||||||
|
|
||||||
######################################################
|
######################################################
|
||||||
|
@ -27,7 +28,7 @@ class RolesPlugin(Plugin):
|
||||||
|
|
||||||
|
|
||||||
@roles_bp.route("/roles", methods=["POST"])
|
@roles_bp.route("/roles", methods=["POST"])
|
||||||
@login_required(permissions=[roles_permission])
|
@login_required(permission=_permission_edit)
|
||||||
def add_role(**kwargs):
|
def add_role(**kwargs):
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
if not data or "name" not in data:
|
if not data or "name" not in data:
|
||||||
|
@ -41,7 +42,7 @@ def add_role(**kwargs):
|
||||||
@roles_bp.route("/roles", methods=["GET"])
|
@roles_bp.route("/roles", methods=["GET"])
|
||||||
@login_required()
|
@login_required()
|
||||||
def list_roles(**kwargs):
|
def list_roles(**kwargs):
|
||||||
roles = roleController.get_roles()
|
roles = roleController.get_all()
|
||||||
return jsonify(roles)
|
return jsonify(roles)
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,18 +56,16 @@ def list_permissions(**kwargs):
|
||||||
@roles_bp.route("/roles/<rid>", methods=["GET"])
|
@roles_bp.route("/roles/<rid>", methods=["GET"])
|
||||||
@login_required()
|
@login_required()
|
||||||
def __get_role(rid, **kwargs):
|
def __get_role(rid, **kwargs):
|
||||||
role = roleController.get_role(rid)
|
role = roleController.get(rid)
|
||||||
if role:
|
if role:
|
||||||
return jsonify({"id": role.id, "name": role, "permissions": role.permissions})
|
return jsonify({"id": role.id, "name": role, "permissions": role.permissions})
|
||||||
raise NotFound
|
raise NotFound
|
||||||
|
|
||||||
|
|
||||||
@roles_bp.route("/roles/<rid>", methods=["PUT"])
|
@roles_bp.route("/roles/<rid>", methods=["PUT"])
|
||||||
@login_required(permissions=[roles_permission])
|
@login_required(permission=_permission_edit)
|
||||||
def __edit_role(rid, **kwargs):
|
def __edit_role(rid, **kwargs):
|
||||||
role = roleController.get_role(rid)
|
role = roleController.get(rid)
|
||||||
if not role:
|
|
||||||
raise NotFound
|
|
||||||
|
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
if "name" in data:
|
if "name" in data:
|
||||||
|
@ -78,9 +77,9 @@ def __edit_role(rid, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
@roles_bp.route("/roles/<rid>", methods=["DELETE"])
|
@roles_bp.route("/roles/<rid>", methods=["DELETE"])
|
||||||
@login_required(permissions=[roles_permission])
|
@login_required(permission=_permission_delete)
|
||||||
def __delete_role(rid, **kwargs):
|
def __delete_role(rid, **kwargs):
|
||||||
if not roleController.delete_role(rid):
|
role = roleController.get(rid)
|
||||||
raise NotFound
|
roleController.delete(role)
|
||||||
|
|
||||||
return jsonify({"ok": "ok"})
|
return jsonify({"ok": "ok"})
|
||||||
|
|
|
@ -10,13 +10,25 @@ from flaschengeist.system.decorator import login_required
|
||||||
from flaschengeist.system.controller import eventController
|
from flaschengeist.system.controller import eventController
|
||||||
|
|
||||||
schedule_bp = Blueprint("schedule", __name__, url_prefix="/schedule")
|
schedule_bp = Blueprint("schedule", __name__, url_prefix="/schedule")
|
||||||
schedule_perms = {"EDIT_EVENT": "schedule_edit_event",
|
_permission_edit_type = "schedule_edit_type"
|
||||||
"NEW_EVENT": "schedule_create_event"}
|
_permission_edit = "schedule_edit"
|
||||||
|
_permission_create = "schedule_create"
|
||||||
|
_permission_delete = "schedule_delete"
|
||||||
|
_permission_assign = "schedule_assign_other"
|
||||||
|
|
||||||
|
|
||||||
class SchedulePlugin(Plugin):
|
class SchedulePlugin(Plugin):
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
super().__init__(blueprint=schedule_bp, permissions=schedule_perms.values())
|
super().__init__(
|
||||||
|
blueprint=schedule_bp,
|
||||||
|
permissions=[
|
||||||
|
_permission_create,
|
||||||
|
_permission_edit,
|
||||||
|
_permission_edit_type,
|
||||||
|
_permission_delete,
|
||||||
|
_permission_assign,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
####################################################################################
|
####################################################################################
|
||||||
|
@ -41,10 +53,10 @@ class SchedulePlugin(Plugin):
|
||||||
####################################################################################
|
####################################################################################
|
||||||
|
|
||||||
|
|
||||||
@schedule_bp.route("/events/<int:id>", methods=["GET"])
|
@schedule_bp.route("/events/<int:eid>", methods=["GET"])
|
||||||
@login_required()
|
@login_required()
|
||||||
def __get_event(id, **kwargs):
|
def __get_event(eid, **kwargs):
|
||||||
event = eventController.get_event(id)
|
event = eventController.get_event(eid)
|
||||||
if not event:
|
if not event:
|
||||||
raise NotFound
|
raise NotFound
|
||||||
return jsonify(event)
|
return jsonify(event)
|
||||||
|
@ -86,7 +98,7 @@ def __get_events(year=datetime.now().year, month=datetime.now().month, day=None,
|
||||||
|
|
||||||
|
|
||||||
@schedule_bp.route("/eventKinds", methods=["POST"])
|
@schedule_bp.route("/eventKinds", methods=["POST"])
|
||||||
@login_required()
|
@login_required(permission=_permission_edit_type)
|
||||||
def __new_event_kind(**kwargs):
|
def __new_event_kind(**kwargs):
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
if "name" not in data:
|
if "name" not in data:
|
||||||
|
@ -96,7 +108,7 @@ def __new_event_kind(**kwargs):
|
||||||
|
|
||||||
|
|
||||||
@schedule_bp.route("/slotKinds", methods=["POST"])
|
@schedule_bp.route("/slotKinds", methods=["POST"])
|
||||||
@login_required()
|
@login_required(permission=_permission_edit_type)
|
||||||
def __new_slot_kind(**kwargs):
|
def __new_slot_kind(**kwargs):
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
if not data or "name" not in data:
|
if not data or "name" not in data:
|
||||||
|
@ -106,7 +118,7 @@ def __new_slot_kind(**kwargs):
|
||||||
|
|
||||||
|
|
||||||
@schedule_bp.route("/events", methods=["POST"])
|
@schedule_bp.route("/events", methods=["POST"])
|
||||||
@login_required(permissions=[schedule_perms["NEW_EVENT"]])
|
@login_required(permission=_permission_create)
|
||||||
def __new_event(**kwargs):
|
def __new_event(**kwargs):
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
event = eventController.create_event(
|
event = eventController.create_event(
|
||||||
|
@ -119,7 +131,7 @@ def __new_event(**kwargs):
|
||||||
|
|
||||||
|
|
||||||
@schedule_bp.route("/events/<int:event_id>", methods=["DELETE"])
|
@schedule_bp.route("/events/<int:event_id>", methods=["DELETE"])
|
||||||
@login_required(permissions=[schedule_perms["EDIT_EVENT"]])
|
@login_required(permission=_permission_delete)
|
||||||
def __delete_event(event_id, **kwargs):
|
def __delete_event(event_id, **kwargs):
|
||||||
if not eventController.delete_event(event_id):
|
if not eventController.delete_event(event_id):
|
||||||
raise NotFound
|
raise NotFound
|
||||||
|
@ -128,7 +140,7 @@ def __delete_event(event_id, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
@schedule_bp.route("/eventKinds/<int:event_id>", methods=["PUT"])
|
@schedule_bp.route("/eventKinds/<int:event_id>", methods=["PUT"])
|
||||||
@login_required()
|
@login_required(permission=_permission_edit_type)
|
||||||
def __edit_event_kind(event_id, **kwargs):
|
def __edit_event_kind(event_id, **kwargs):
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
if not data or "name" not in data:
|
if not data or "name" not in data:
|
||||||
|
@ -156,7 +168,7 @@ def __get_slot(event_id, slot_id, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
@schedule_bp.route("/events/<int:event_id>/slots/<int:slot_id>", methods=["DELETE"])
|
@schedule_bp.route("/events/<int:event_id>/slots/<int:slot_id>", methods=["DELETE"])
|
||||||
@login_required()
|
@login_required(permission=_permission_delete)
|
||||||
def __delete_slot(event_id, slot_id, **kwargs):
|
def __delete_slot(event_id, slot_id, **kwargs):
|
||||||
if eventController.delete_event_slot(slot_id, event_id):
|
if eventController.delete_event_slot(slot_id, event_id):
|
||||||
return jsonify({"ok": "ok"})
|
return jsonify({"ok": "ok"})
|
||||||
|
@ -164,7 +176,7 @@ def __delete_slot(event_id, slot_id, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
@schedule_bp.route("/events/<int:event_id>/slots/<int:slot_id>", methods=["PUT"])
|
@schedule_bp.route("/events/<int:event_id>/slots/<int:slot_id>", methods=["PUT"])
|
||||||
@login_required()
|
@login_required(permission=_permission_edit)
|
||||||
def __update_slot(event_id, slot_id, **kwargs):
|
def __update_slot(event_id, slot_id, **kwargs):
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
if not data:
|
if not data:
|
||||||
|
@ -178,7 +190,7 @@ def __update_slot(event_id, slot_id, **kwargs):
|
||||||
|
|
||||||
|
|
||||||
@schedule_bp.route("/events/<int:event_id>/slots", methods=["POST"])
|
@schedule_bp.route("/events/<int:event_id>/slots", methods=["POST"])
|
||||||
@login_required()
|
@login_required(permission=_permission_edit)
|
||||||
def __add_slot(event_id, **kwargs):
|
def __add_slot(event_id, **kwargs):
|
||||||
event = eventController.get_event(event_id)
|
event = eventController.get_event(event_id)
|
||||||
if not event:
|
if not event:
|
||||||
|
|
|
@ -7,12 +7,13 @@ from flaschengeist.system.decorator import login_required
|
||||||
from flaschengeist.system.controller import userController
|
from flaschengeist.system.controller import userController
|
||||||
|
|
||||||
users_bp = Blueprint("users", __name__)
|
users_bp = Blueprint("users", __name__)
|
||||||
users_perm = "users_edit_other"
|
_permission_edit = "users_edit_other"
|
||||||
|
_permission_delete = "users_delete_other"
|
||||||
|
|
||||||
|
|
||||||
class UsersPlugin(Plugin):
|
class UsersPlugin(Plugin):
|
||||||
def __init__(self, config):
|
def __init__(self, config):
|
||||||
super().__init__(blueprint=users_bp, permissions=[users_perm])
|
super().__init__(blueprint=users_bp, permissions=[_permission_edit, _permission_delete])
|
||||||
|
|
||||||
#################################################
|
#################################################
|
||||||
# Routes #
|
# Routes #
|
||||||
|
@ -49,15 +50,22 @@ def __get_user(uid, **kwargs):
|
||||||
raise NotFound
|
raise NotFound
|
||||||
|
|
||||||
|
|
||||||
|
@users_bp.route("/users/<uid>", methods=["DELETE"])
|
||||||
|
@login_required(permission=_permission_delete)
|
||||||
|
def __delete_user(uid, **kwargs):
|
||||||
|
logger.debug("Delete user {{ {} }}".format(uid))
|
||||||
|
user = userController.get_user(uid)
|
||||||
|
userController.delete(user)
|
||||||
|
return jsonify({"ok": "ok"})
|
||||||
|
|
||||||
|
|
||||||
@users_bp.route("/users/<uid>", methods=["PUT"])
|
@users_bp.route("/users/<uid>", methods=["PUT"])
|
||||||
@login_required()
|
@login_required()
|
||||||
def __edit_user(uid, **kwargs):
|
def __edit_user(uid, **kwargs):
|
||||||
logger.debug("Modify information of user {{ {} }}".format(uid))
|
logger.debug("Modify information of user {{ {} }}".format(uid))
|
||||||
user = userController.get_user(uid)
|
user = userController.get_user(uid)
|
||||||
if not user:
|
|
||||||
raise NotFound
|
|
||||||
|
|
||||||
if uid != kwargs["access_token"].user.userid and user.has_permissions([users_perm]):
|
if uid != kwargs["access_token"].user.userid and user.has_permission(_permission_edit):
|
||||||
return Forbidden
|
return Forbidden
|
||||||
|
|
||||||
data = request.get_json()
|
data = request.get_json()
|
||||||
|
|
|
@ -1,17 +1,19 @@
|
||||||
from sqlalchemy.exc import IntegrityError
|
from sqlalchemy.exc import IntegrityError
|
||||||
from werkzeug.exceptions import BadRequest
|
from werkzeug.exceptions import BadRequest, NotFound
|
||||||
|
|
||||||
from flaschengeist.system.models.user import Role, Permission
|
from flaschengeist.system.models.user import Role, Permission
|
||||||
from flaschengeist.system.database import db
|
from flaschengeist.system.database import db
|
||||||
from flaschengeist import logger
|
from flaschengeist import logger
|
||||||
|
|
||||||
|
|
||||||
def get_roles():
|
def get_all():
|
||||||
return Role.query.all()
|
return Role.query.all()
|
||||||
|
|
||||||
|
|
||||||
def get_role(rid):
|
def get(rid):
|
||||||
return Role.query.get(rid)
|
role = Role.query.get(rid).one_or_none()
|
||||||
|
if not role:
|
||||||
|
raise NotFound
|
||||||
|
|
||||||
|
|
||||||
def get_permissions():
|
def get_permissions():
|
||||||
|
@ -47,9 +49,9 @@ def create_role(name, permissions=[]):
|
||||||
return role.id
|
return role.id
|
||||||
|
|
||||||
|
|
||||||
def delete_role(id):
|
def delete(role):
|
||||||
try:
|
try:
|
||||||
num = Role.query.filter(Role.id == id).delete()
|
num = Role.query.filter(Role.id == role.id).delete()
|
||||||
except IntegrityError:
|
except IntegrityError:
|
||||||
logger.debug("IntegrityError: Role might still be in use", exc_info=True)
|
logger.debug("IntegrityError: Role might still be in use", exc_info=True)
|
||||||
raise BadRequest("Role still in use")
|
raise BadRequest("Role still in use")
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
|
from werkzeug.exceptions import NotFound
|
||||||
|
|
||||||
from flaschengeist.system.models.user import User, Role
|
from flaschengeist.system.models.user import User, Role
|
||||||
from flaschengeist.system.database import db
|
from flaschengeist.system.database import db
|
||||||
|
@ -51,4 +52,13 @@ def get_user_by_role(role: Role):
|
||||||
|
|
||||||
|
|
||||||
def get_user(uid):
|
def get_user(uid):
|
||||||
return User.query.filter(User.userid == uid).one_or_none()
|
user = User.query.filter(User.userid == uid).one_or_none()
|
||||||
|
if not user:
|
||||||
|
raise NotFound
|
||||||
|
return user
|
||||||
|
|
||||||
|
|
||||||
|
def delete(user):
|
||||||
|
current_app.config["FG_AUTH_BACKEND"].delete_user(user)
|
||||||
|
db.session.delete(user)
|
||||||
|
db.session.commit()
|
||||||
|
|
|
@ -6,12 +6,12 @@ from flaschengeist import logger
|
||||||
from flaschengeist.system.controller import sessionController
|
from flaschengeist.system.controller import sessionController
|
||||||
|
|
||||||
|
|
||||||
def login_required(permissions=None):
|
def login_required(permission=None):
|
||||||
def wrap(func):
|
def wrap(func):
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def wrapped_f(*args, **kwargs):
|
def wrapped_f(*args, **kwargs):
|
||||||
token = list(filter(None, request.headers.get("Authorization").split(" ")))[-1]
|
token = list(filter(None, request.headers.get("Authorization").split(" ")))[-1]
|
||||||
access_token = sessionController.validate_token(token, request.user_agent, permissions)
|
access_token = sessionController.validate_token(token, request.user_agent, permission)
|
||||||
if access_token:
|
if access_token:
|
||||||
kwargs["access_token"] = access_token
|
kwargs["access_token"] = access_token
|
||||||
logger.debug("token {{ {} }} is valid".format(token))
|
logger.debug("token {{ {} }} is valid".format(token))
|
||||||
|
@ -19,5 +19,7 @@ def login_required(permissions=None):
|
||||||
else:
|
else:
|
||||||
logger.info("token {{ {} }} is not valid".format(token))
|
logger.info("token {{ {} }} is not valid".format(token))
|
||||||
raise Unauthorized
|
raise Unauthorized
|
||||||
|
|
||||||
return wrapped_f
|
return wrapped_f
|
||||||
|
|
||||||
return wrap
|
return wrap
|
||||||
|
|
|
@ -45,15 +45,19 @@ class Event(db.Model, ModelSerializeMixin):
|
||||||
|
|
||||||
class Job(db.Model, ModelSerializeMixin):
|
class Job(db.Model, ModelSerializeMixin):
|
||||||
__tablename__ = "job"
|
__tablename__ = "job"
|
||||||
_user: User = db.relationship("User")
|
user: str = None
|
||||||
# user: str = column_property(_user.userid)
|
|
||||||
value: float = db.Column(db.Numeric(precision=3, scale=2))
|
value: float = db.Column(db.Numeric(precision=3, scale=2))
|
||||||
|
|
||||||
_id = db.Column("id", db.Integer, primary_key=True)
|
_id = db.Column("id", db.Integer, primary_key=True)
|
||||||
_user_id = db.Column("user_id", db.Integer, db.ForeignKey("user.id"))
|
_user_id = db.Column("user_id", db.Integer, db.ForeignKey("user.id"))
|
||||||
|
_user: User = db.relationship("User")
|
||||||
_slot_id = db.Column("slot_id", db.Integer, db.ForeignKey("job_slot.id"))
|
_slot_id = db.Column("slot_id", db.Integer, db.ForeignKey("job_slot.id"))
|
||||||
_slot = db.relationship("JobSlot")
|
_slot = db.relationship("JobSlot")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def user(self):
|
||||||
|
return self._user.userid
|
||||||
|
|
||||||
|
|
||||||
class JobKind(db.Model, ModelSerializeMixin):
|
class JobKind(db.Model, ModelSerializeMixin):
|
||||||
__tablename__ = "job_kind"
|
__tablename__ = "job_kind"
|
||||||
|
|
Loading…
Reference in New Issue