add: markdown permission setting
improve: template
This commit is contained in:
@@ -79,6 +79,17 @@ def verify_token(token):
|
|||||||
print(e)
|
print(e)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def is_user_admin():
|
||||||
|
is_admin = False
|
||||||
|
auth_header = request.headers.get('Authorization')
|
||||||
|
if auth_header and auth_header.startswith('Bearer'):
|
||||||
|
token = auth_header.split(" ")[1]
|
||||||
|
decoded = verify_token(token)
|
||||||
|
if decoded:
|
||||||
|
user_roles = decoded.get("resource_access", {}).get(env_provider.KC_CLIENT_ID, {}).get("roles", [])
|
||||||
|
is_admin = 'admin' in user_roles
|
||||||
|
return is_admin
|
||||||
|
|
||||||
def require_auth(roles=[]):
|
def require_auth(roles=[]):
|
||||||
def decorator(func):
|
def decorator(func):
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
@@ -158,4 +169,3 @@ def etag_response(f):
|
|||||||
return resp
|
return resp
|
||||||
return response
|
return response
|
||||||
return decorator
|
return decorator
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
from flask import Blueprint, request, jsonify
|
from flask import Blueprint, request, jsonify
|
||||||
from sqlalchemy import or_
|
from sqlalchemy import or_
|
||||||
from api import limiter
|
from api import limiter
|
||||||
from api import require_auth, etag_response
|
from api import require_auth, etag_response, verify_token, is_user_admin
|
||||||
from contexts.RequestContext import RequestContext
|
from contexts.RequestContext import RequestContext
|
||||||
from db import get_db
|
from db import get_db
|
||||||
from db.models.Markdown import Markdown
|
from db.models.Markdown import Markdown
|
||||||
|
from db.models.MarkdownSetting import MarkdownSetting
|
||||||
|
from db.models.MarkdownPermissionSetting import MarkdownPermissionSetting
|
||||||
from events import markdown_created, markdown_updated, markdown_deleted
|
from events import markdown_created, markdown_updated, markdown_deleted
|
||||||
import api
|
import api
|
||||||
|
import env_provider
|
||||||
import logging
|
import logging
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -54,10 +57,23 @@ def get_index(path_id):
|
|||||||
@limiter.limit(api.get_rate_limit)
|
@limiter.limit(api.get_rate_limit)
|
||||||
@etag_response
|
@etag_response
|
||||||
def get_markdown(markdown_id):
|
def get_markdown(markdown_id):
|
||||||
|
is_admin = is_user_admin()
|
||||||
|
|
||||||
with get_db() as session:
|
with get_db() as session:
|
||||||
markdown = session.query(Markdown).get(markdown_id)
|
markdown = session.query(Markdown).get(markdown_id)
|
||||||
if markdown is None:
|
if markdown is None:
|
||||||
return jsonify({"error": "file not found"}), 404
|
return jsonify({"error": "file not found"}), 404
|
||||||
|
|
||||||
|
if not is_admin and markdown.setting_id is not None:
|
||||||
|
setting = session.query(MarkdownSetting).get(markdown.setting_id)
|
||||||
|
if setting and setting.permission_setting_id:
|
||||||
|
permission_setting = session.query(MarkdownPermissionSetting).get(setting.permission_setting_id)
|
||||||
|
if permission_setting:
|
||||||
|
if permission_setting.permission == 'private':
|
||||||
|
return jsonify({"msg": "permission denied"}), 403
|
||||||
|
elif permission_setting.permission == 'protected':
|
||||||
|
return jsonify({"msg": "permission denied"}), 203
|
||||||
|
|
||||||
return jsonify(markdown.to_dict()), 200
|
return jsonify(markdown.to_dict()), 200
|
||||||
|
|
||||||
@markdown_bp.route('/', methods=['POST'])
|
@markdown_bp.route('/', methods=['POST'])
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
#api/resource.py
|
|
||||||
import api
|
import api
|
||||||
from flask import Blueprint, jsonify, request
|
from flask import Blueprint, jsonify, request
|
||||||
from contexts.RequestContext import RequestContext
|
from contexts.RequestContext import RequestContext
|
||||||
|
|||||||
@@ -23,7 +23,11 @@ def get_markdown_path(setting_id):
|
|||||||
def create_markdown_setting():
|
def create_markdown_setting():
|
||||||
data = request.json
|
data = request.json
|
||||||
template_setting_id = data.get('template_setting_id')
|
template_setting_id = data.get('template_setting_id')
|
||||||
setting = MarkdownSetting(template_setting_id=template_setting_id)
|
permission_setting_id = data.get('permission_setting_id')
|
||||||
|
setting = MarkdownSetting(
|
||||||
|
template_setting_id=template_setting_id,
|
||||||
|
permission_setting_id=permission_setting_id
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
with get_db() as session:
|
with get_db() as session:
|
||||||
session.add(setting)
|
session.add(setting)
|
||||||
@@ -42,7 +46,9 @@ def update_markdown_setting(setting_id):
|
|||||||
if setting is None:
|
if setting is None:
|
||||||
return jsonify({"error": "setting not exists"}), 400
|
return jsonify({"error": "setting not exists"}), 400
|
||||||
template_setting_id = data.get('template_setting_id', setting.template_setting_id)
|
template_setting_id = data.get('template_setting_id', setting.template_setting_id)
|
||||||
|
permission_setting_id = data.get('permission_setting_id', setting.permission_setting_id)
|
||||||
setting.template_setting_id = template_setting_id
|
setting.template_setting_id = template_setting_id
|
||||||
|
setting.permission_setting_id = permission_setting_id
|
||||||
session.commit()
|
session.commit()
|
||||||
return jsonify(setting.to_dict()), 200
|
return jsonify(setting.to_dict()), 200
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|||||||
56
api/setting/markdown/permission.py
Normal file
56
api/setting/markdown/permission.py
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
from flask import jsonify, request
|
||||||
|
import api
|
||||||
|
from api import etag_response, limiter, require_auth
|
||||||
|
from api.setting import setting_bp
|
||||||
|
from db import get_db
|
||||||
|
from db.models.MarkdownPermissionSetting import MarkdownPermissionSetting
|
||||||
|
|
||||||
|
|
||||||
|
@setting_bp.route('/markdown/permission/<int:setting_id>/', methods=['GET'])
|
||||||
|
@etag_response
|
||||||
|
@limiter.limit(api.get_rate_limit)
|
||||||
|
def get_permission_setting(setting_id):
|
||||||
|
with get_db() as session:
|
||||||
|
setting = session.query(MarkdownPermissionSetting).get(setting_id)
|
||||||
|
if not setting:
|
||||||
|
return jsonify({}), 204
|
||||||
|
return jsonify(setting.to_dict()), 200
|
||||||
|
|
||||||
|
|
||||||
|
@setting_bp.route('/markdown/permission/', methods=['POST'])
|
||||||
|
@require_auth(roles=['admin'])
|
||||||
|
def create_permission_setting():
|
||||||
|
data = request.json
|
||||||
|
permission = data.get('permission')
|
||||||
|
new_setting = MarkdownPermissionSetting(permission=permission)
|
||||||
|
with get_db() as session:
|
||||||
|
session.add(new_setting)
|
||||||
|
session.commit()
|
||||||
|
return jsonify(new_setting.to_dict()), 201
|
||||||
|
|
||||||
|
|
||||||
|
@setting_bp.route('/markdown/permission/<int:setting_id>', methods=['PUT', 'PATCH'])
|
||||||
|
@require_auth(roles=['admin'])
|
||||||
|
def update_permission_setting(setting_id):
|
||||||
|
with get_db() as session:
|
||||||
|
setting = session.get(MarkdownPermissionSetting, setting_id)
|
||||||
|
if setting is None:
|
||||||
|
return jsonify({"error": "permission setting not found"}), 404
|
||||||
|
data = request.json
|
||||||
|
if request.method == 'PUT':
|
||||||
|
setting.permission = data.get('permission')
|
||||||
|
elif request.method == 'PATCH':
|
||||||
|
if 'permission' in data:
|
||||||
|
setting.permission = data.get('permission')
|
||||||
|
session.commit()
|
||||||
|
return jsonify(setting.to_dict()), 200
|
||||||
|
|
||||||
|
@setting_bp.route('/markdown/permission/<int:setting_id>', methods=['DELETE'])
|
||||||
|
@require_auth(roles=['admin'])
|
||||||
|
def delete_permission_setting(setting_id):
|
||||||
|
with get_db() as session:
|
||||||
|
setting = session.get(MarkdownPermissionSetting, setting_id)
|
||||||
|
st = setting.to_dict()
|
||||||
|
session.delete(setting)
|
||||||
|
session.commit()
|
||||||
|
return jsonify(st), 200
|
||||||
@@ -59,8 +59,5 @@ def delete_template_setting(setting_id):
|
|||||||
setting = session.get(MarkdownTemplateSetting, setting_id)
|
setting = session.get(MarkdownTemplateSetting, setting_id)
|
||||||
st = setting.to_dict()
|
st = setting.to_dict()
|
||||||
session.delete(setting)
|
session.delete(setting)
|
||||||
|
session.commit()
|
||||||
return jsonify(st), 200
|
return jsonify(st), 200
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
36
api/tree.py
36
api/tree.py
@@ -1,27 +1,49 @@
|
|||||||
from flask import Blueprint, request, jsonify
|
from flask import Blueprint, request, jsonify
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
|
from sqlalchemy import and_, or_
|
||||||
|
|
||||||
import api
|
import api
|
||||||
from api import etag_response
|
from api import etag_response, verify_token, is_user_admin
|
||||||
from db import get_db
|
from db import get_db
|
||||||
from db.models.Markdown import Markdown
|
from db.models.Markdown import Markdown
|
||||||
from db.models.Path import Path
|
from db.models.Path import Path
|
||||||
|
from db.models.MarkdownSetting import MarkdownSetting
|
||||||
|
from db.models.MarkdownPermissionSetting import MarkdownPermissionSetting
|
||||||
from api import limiter
|
from api import limiter
|
||||||
|
import env_provider
|
||||||
import logging
|
import logging
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
tree_bp = Blueprint('tree', __name__, url_prefix='/api/tree')
|
tree_bp = Blueprint('tree', __name__, url_prefix='/api/tree')
|
||||||
|
|
||||||
|
|
||||||
def build_tree(db: Session, parent_id: int = None):
|
def build_tree(db: Session, parent_id: int = None, is_admin=False):
|
||||||
path_nodes = db.query(Path).filter(Path.parent_id == parent_id).all()
|
path_nodes = db.query(Path).filter(Path.parent_id == parent_id).all()
|
||||||
md_nodes = db.query(
|
|
||||||
|
markdown_query = db.query(
|
||||||
Markdown.id,
|
Markdown.id,
|
||||||
Markdown.title,
|
Markdown.title,
|
||||||
Markdown.order,
|
Markdown.order,
|
||||||
Markdown.shortcut,
|
Markdown.shortcut,
|
||||||
Markdown.setting_id
|
Markdown.setting_id
|
||||||
).filter(Markdown.path_id == parent_id).all()
|
).filter(Markdown.path_id == parent_id)
|
||||||
|
|
||||||
|
if not is_admin:
|
||||||
|
markdown_query = markdown_query.outerjoin(
|
||||||
|
MarkdownSetting,
|
||||||
|
Markdown.setting_id == MarkdownSetting.id
|
||||||
|
).outerjoin(
|
||||||
|
MarkdownPermissionSetting,
|
||||||
|
MarkdownSetting.permission_setting_id == MarkdownPermissionSetting.id
|
||||||
|
).filter(
|
||||||
|
or_(
|
||||||
|
MarkdownPermissionSetting.permission != 'private',
|
||||||
|
MarkdownPermissionSetting.permission == None
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
md_nodes = markdown_query.all()
|
||||||
|
|
||||||
t0 = [
|
t0 = [
|
||||||
{
|
{
|
||||||
"id": node.id,
|
"id": node.id,
|
||||||
@@ -32,7 +54,7 @@ def build_tree(db: Session, parent_id: int = None):
|
|||||||
} for node in md_nodes
|
} for node in md_nodes
|
||||||
]
|
]
|
||||||
t1 = [
|
t1 = [
|
||||||
{**node.to_dict(), "type": "path", "children": build_tree(db, node.id)} for node in path_nodes
|
{**node.to_dict(), "type": "path", "children": build_tree(db, node.id, is_admin)} for node in path_nodes
|
||||||
]
|
]
|
||||||
for node in t1:
|
for node in t1:
|
||||||
for child in node["children"]:
|
for child in node["children"]:
|
||||||
@@ -45,8 +67,10 @@ def build_tree(db: Session, parent_id: int = None):
|
|||||||
@limiter.limit(api.get_rate_limit)
|
@limiter.limit(api.get_rate_limit)
|
||||||
@etag_response
|
@etag_response
|
||||||
def get_tree():
|
def get_tree():
|
||||||
|
is_admin = is_user_admin()
|
||||||
|
|
||||||
with get_db() as session:
|
with get_db() as session:
|
||||||
children = build_tree(session, 1)
|
children = build_tree(session, 1, is_admin)
|
||||||
root = session.query(Path).get(1)
|
root = session.query(Path).get(1)
|
||||||
|
|
||||||
return jsonify(
|
return jsonify(
|
||||||
|
|||||||
15
db/models/MarkdownPermissionSetting.py
Normal file
15
db/models/MarkdownPermissionSetting.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
from sqlalchemy import Column, Integer, ForeignKey, String
|
||||||
|
|
||||||
|
from db.models import Base
|
||||||
|
|
||||||
|
|
||||||
|
class MarkdownPermissionSetting(Base):
|
||||||
|
__tablename__ = 'markdown_permission_setting'
|
||||||
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||||
|
permission = Column(String(255), nullable=True)
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
return {
|
||||||
|
"id": self.id,
|
||||||
|
"permission": self.permission,
|
||||||
|
}
|
||||||
@@ -1,15 +1,14 @@
|
|||||||
from sqlalchemy import Column, Integer, ForeignKey
|
from sqlalchemy import Column, Integer, ForeignKey
|
||||||
|
|
||||||
from db.models import Base
|
from db.models import Base
|
||||||
|
|
||||||
|
|
||||||
class MarkdownSetting(Base):
|
class MarkdownSetting(Base):
|
||||||
__tablename__ = 'markdown_setting'
|
__tablename__ = 'markdown_setting'
|
||||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||||
template_setting_id = Column(Integer, ForeignKey('markdown_template_setting.id'), nullable=True)
|
template_setting_id = Column(Integer, ForeignKey('markdown_template_setting.id'), nullable=True)
|
||||||
|
permission_setting_id = Column(Integer, ForeignKey('markdown_permission_setting.id'), nullable=True)
|
||||||
def to_dict(self):
|
def to_dict(self):
|
||||||
return {
|
return {
|
||||||
"id": self.id,
|
"id": self.id,
|
||||||
"template_setting_id": self.template_setting_id,
|
"template_setting_id": self.template_setting_id,
|
||||||
|
"permission_setting_id": self.permission_setting_id,
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
#env_provider.py
|
|
||||||
import os
|
import os
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
#logging_handlers/DatabaseLogHandler.py
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from db import get_db
|
from db import get_db
|
||||||
from db.models.Log import Log
|
from db.models.Log import Log
|
||||||
|
|||||||
Reference in New Issue
Block a user