sachet/server: auth_required now has more modular permissions
there is no more require_admin, because ADMIN is just one of many permissions
This commit is contained in:
parent
6749391b3c
commit
2fba574773
@ -1,6 +1,6 @@
|
||||
from flask import Blueprint, request, jsonify
|
||||
from flask.views import MethodView
|
||||
from sachet.server.models import ServerSettings
|
||||
from sachet.server.models import ServerSettings, Permissions
|
||||
from sachet.server import db
|
||||
from sachet.server.views_common import auth_required, ModelAPI
|
||||
|
||||
@ -18,17 +18,17 @@ class ServerSettingsAPI(ModelAPI):
|
||||
return settings
|
||||
return rows[-1]
|
||||
|
||||
@auth_required(require_admin=True)
|
||||
@auth_required(required_permissions=(Permissions.ADMIN,))
|
||||
def get(self, auth_user=None):
|
||||
settings = self.get_settings()
|
||||
return super().get(settings)
|
||||
|
||||
@auth_required(require_admin=True)
|
||||
@auth_required(required_permissions=(Permissions.ADMIN,))
|
||||
def patch(self, auth_user=None):
|
||||
settings = self.get_settings()
|
||||
return super().patch(settings)
|
||||
|
||||
@auth_required(require_admin=True)
|
||||
@auth_required(required_permissions=(Permissions.ADMIN,))
|
||||
def put(self, auth_user=None):
|
||||
settings = self.get_settings()
|
||||
return super().put(settings)
|
||||
|
35
sachet/server/files/views.py
Normal file
35
sachet/server/files/views.py
Normal file
@ -0,0 +1,35 @@
|
||||
import jwt
|
||||
from flask import Blueprint, request, jsonify
|
||||
from flask.views import MethodView
|
||||
from sachet.server.models import File, Permissions
|
||||
from sachet.server.views_common import ModelAPI, auth_required
|
||||
|
||||
files_blueprint = Blueprint("files_blueprint", __name__)
|
||||
|
||||
|
||||
class FilesAPI(ModelAPI):
|
||||
"""Files metadata API."""
|
||||
|
||||
@auth_required
|
||||
def get(self, id, auth_user=None):
|
||||
pass
|
||||
|
||||
|
||||
files_blueprint.add_url_rule(
|
||||
"/files/<id>",
|
||||
view_func=FilesAPI.as_view("files_api"),
|
||||
methods=["POST", "PUT", "PATCH", "GET", "DELETE"],
|
||||
)
|
||||
|
||||
files_blueprint.add_url_rule(
|
||||
"/files/<id>/content",
|
||||
view_func=FilesContentAPI.as_view("files_content_api"),
|
||||
methods=["PUT", "GET"],
|
||||
)
|
||||
|
||||
|
||||
users_blueprint.add_url_rule(
|
||||
"/users/<username>",
|
||||
view_func=UserAPI.as_view("user_api"),
|
||||
methods=["GET", "PATCH", "PUT"],
|
||||
)
|
@ -126,12 +126,12 @@ class UserAPI(ModelAPI):
|
||||
|
||||
return super().get(info_user)
|
||||
|
||||
@auth_required(require_admin=True)
|
||||
@auth_required(required_permissions=(Permissions.ADMIN,))
|
||||
def patch(self, username, auth_user=None):
|
||||
patch_user = User.query.filter_by(username=username).first()
|
||||
return super().patch(patch_user)
|
||||
|
||||
@auth_required(require_admin=True)
|
||||
@auth_required(required_permissions=(Permissions.ADMIN,))
|
||||
def put(self, username, auth_user=None):
|
||||
put_user = User.query.filter_by(username=username).first()
|
||||
return super().put(put_user)
|
||||
|
@ -1,16 +1,24 @@
|
||||
from flask import request, jsonify
|
||||
from flask.views import MethodView
|
||||
from sachet.server.models import Permissions, User, BlacklistToken
|
||||
from sachet.server import db
|
||||
from functools import wraps
|
||||
from marshmallow import ValidationError
|
||||
from bitmask import Bitmask
|
||||
import jwt
|
||||
|
||||
|
||||
def auth_required(func=None, *, require_admin=False):
|
||||
def auth_required(func=None, *, required_permissions=()):
|
||||
"""Decorator to require authentication.
|
||||
|
||||
Passes an argument 'user' to the function, with a User object corresponding
|
||||
to the authenticated session.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
|
||||
required_permissions : tuple of Permissions
|
||||
Permissions required to access this endpoint.
|
||||
"""
|
||||
|
||||
# see https://stackoverflow.com/questions/3888158/making-decorators-with-optional-arguments
|
||||
@ -44,12 +52,15 @@ def auth_required(func=None, *, require_admin=False):
|
||||
401,
|
||||
)
|
||||
|
||||
if require_admin and Permissions.ADMIN not in user.permissions:
|
||||
if (
|
||||
Bitmask(AllFlags=Permissions, *required_permissions)
|
||||
not in user.permissions
|
||||
):
|
||||
return (
|
||||
jsonify(
|
||||
{
|
||||
"status": "fail",
|
||||
"message": "Administrator permission is required to see this page.",
|
||||
"message": "Missing permissions to access this page.",
|
||||
}
|
||||
),
|
||||
403,
|
||||
@ -112,6 +123,8 @@ class ModelAPI(MethodView):
|
||||
for k, v in deserialized.items():
|
||||
setattr(model, k, v)
|
||||
|
||||
db.session.commit()
|
||||
|
||||
resp = {
|
||||
"status": "success",
|
||||
}
|
||||
@ -138,7 +151,37 @@ class ModelAPI(MethodView):
|
||||
for k, v in deserialized.items():
|
||||
setattr(model, k, v)
|
||||
|
||||
db.session.commit()
|
||||
|
||||
resp = {
|
||||
"status": "success",
|
||||
}
|
||||
return jsonify(resp), 200
|
||||
|
||||
def delete(self, model):
|
||||
if not model:
|
||||
resp = {
|
||||
"status": "fail",
|
||||
"message": "This resource does not exist.",
|
||||
}
|
||||
return jsonify(resp), 404
|
||||
|
||||
model.delete()
|
||||
db.session.commit()
|
||||
|
||||
return jsonify({"status": "success"})
|
||||
|
||||
def post(self, ModelClass, data):
|
||||
model_schema = ModelClass.get_schema()
|
||||
|
||||
post_json = request.get_json()
|
||||
try:
|
||||
deserialized = model_schema.load(post_json)
|
||||
except ValidationError as e:
|
||||
resp = {"status": "fail", "message": f"Invalid data: {str(e)}"}
|
||||
return jsonify(resp), 400
|
||||
|
||||
# create new ModelClass instance with all the parameters given in the request
|
||||
model = ModelClass(**deserialized)
|
||||
|
||||
return jsonify({"status": "success"}), 201
|
||||
|
Loading…
Reference in New Issue
Block a user