Compare commits
1 Commits
41ff76e6c9
...
038efb745a
| Author | SHA1 | Date | |
|---|---|---|---|
| 038efb745a |
@@ -1,11 +1,10 @@
|
||||
#api/__init__.py
|
||||
import base64
|
||||
import os
|
||||
from functools import wraps
|
||||
|
||||
from cryptography import x509
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
from flask import jsonify, Blueprint, request
|
||||
from flask import jsonify, Blueprint, request, make_response
|
||||
from flask_limiter import Limiter
|
||||
from flask_limiter.util import get_remote_address
|
||||
from jwt import decode, ExpiredSignatureError, InvalidTokenError, get_unverified_header
|
||||
@@ -14,6 +13,11 @@ import requests
|
||||
from threading import Lock
|
||||
|
||||
import env_provider
|
||||
import hashlib
|
||||
import json
|
||||
|
||||
|
||||
|
||||
|
||||
_public_key_cache = {}
|
||||
_lock = Lock()
|
||||
@@ -135,3 +139,24 @@ def register_blueprints(app):
|
||||
app.register_blueprint(bp)
|
||||
|
||||
|
||||
|
||||
def generate_etag(data):
|
||||
serialized = json.dumps(data, sort_keys=True).encode('utf-8')
|
||||
return hashlib.md5(serialized).hexdigest()
|
||||
|
||||
def etag_response(f):
|
||||
@wraps(f)
|
||||
def decorator(*args, **kwargs):
|
||||
response = f(*args, **kwargs)
|
||||
if response[1] in (200, 201):
|
||||
if isinstance(response[0], (dict, list)):
|
||||
etag = generate_etag(response[0])
|
||||
if_none_match = request.headers.get("if_none_match")
|
||||
if if_none_match == etag:
|
||||
return jsonify({}), 200
|
||||
resp = make_response(response[0], response[1])
|
||||
resp.headers["ETag"] = etag
|
||||
return resp
|
||||
return response
|
||||
return decorator
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
from flask import Blueprint, jsonify, request
|
||||
|
||||
from api import require_auth, rate_limits
|
||||
from api import require_auth, rate_limits, etag_response
|
||||
import re
|
||||
config_bp = Blueprint('config', __name__, url_prefix='/api/config')
|
||||
|
||||
@@ -10,6 +10,7 @@ def is_valid_rate_limit(limit):
|
||||
return bool(RATE_LIMIT_REGEX.match(limit))
|
||||
@config_bp.route('/limits', methods=['GET'])
|
||||
@require_auth(roles=['admin'])
|
||||
@etag_response
|
||||
def limits():
|
||||
return jsonify(rate_limits), 200
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
from flask import Blueprint, request, jsonify
|
||||
|
||||
import api
|
||||
from api import require_auth
|
||||
from api import require_auth, etag_response
|
||||
from contexts.RequestContext import RequestContext
|
||||
from db import get_db
|
||||
from db.models.Markdown import Markdown
|
||||
@@ -14,6 +14,7 @@ markdown_bp = Blueprint('markdown', __name__, url_prefix='/api/markdown')
|
||||
|
||||
@markdown_bp.route('/', methods=['GET'])
|
||||
@limiter.limit(api.get_rate_limit)
|
||||
@etag_response
|
||||
def get_markdowns():
|
||||
with get_db() as session:
|
||||
mds = session.query(Markdown).all()
|
||||
@@ -21,12 +22,14 @@ def get_markdowns():
|
||||
|
||||
@markdown_bp.route('/by_path/<int:path_id>', methods=['GET'])
|
||||
@limiter.limit(api.get_rate_limit)
|
||||
@etag_response
|
||||
def get_markdowns_by_path(path_id):
|
||||
with get_db() as session:
|
||||
markdowns = session.query(Markdown).filter(Markdown.path_id == path_id).all()
|
||||
return jsonify([md.to_dict() for md in markdowns]), 200
|
||||
@markdown_bp.route('/get_index/<int:path_id>', methods=['GET'])
|
||||
@limiter.limit(api.get_rate_limit)
|
||||
@etag_response
|
||||
def get_index(path_id):
|
||||
with get_db() as session:
|
||||
markdown = session.query(Markdown).filter(Markdown.path_id == path_id).filter(Markdown.title == "index").first()
|
||||
@@ -38,6 +41,7 @@ def get_index(path_id):
|
||||
|
||||
@markdown_bp.route('/<int:markdown_id>', methods=['GET'])
|
||||
@limiter.limit(api.get_rate_limit)
|
||||
@etag_response
|
||||
def get_markdown(markdown_id):
|
||||
with get_db() as session:
|
||||
markdown = session.query(Markdown).get(markdown_id)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
from flask import Blueprint, request, jsonify
|
||||
|
||||
import api
|
||||
from api import require_auth
|
||||
from api import require_auth, etag_response
|
||||
from db import get_db
|
||||
from db.models.Markdown import Markdown
|
||||
from db.models.Path import Path
|
||||
@@ -13,6 +13,7 @@ path_bp = Blueprint('path', __name__, url_prefix='/api/path')
|
||||
|
||||
@path_bp.route('/', methods=['GET'])
|
||||
@limiter.limit(api.get_rate_limit)
|
||||
@etag_response
|
||||
def get_root_paths():
|
||||
with get_db() as session:
|
||||
paths = session.query(Path).filter(Path.parent_id == 1)
|
||||
@@ -20,6 +21,7 @@ def get_root_paths():
|
||||
|
||||
@path_bp.route('/<int:path_id>', methods=['GET'])
|
||||
@limiter.limit(api.get_rate_limit)
|
||||
@etag_response
|
||||
def get_path(path_id):
|
||||
with get_db() as session:
|
||||
path = session.query(Path).get(path_id)
|
||||
@@ -29,6 +31,7 @@ def get_path(path_id):
|
||||
|
||||
@path_bp.route('/parent/<int:parent_id>', methods=['GET'])
|
||||
@limiter.limit(api.get_rate_limit)
|
||||
@etag_response
|
||||
def get_path_by_parent(parent_id):
|
||||
with get_db() as session:
|
||||
paths = session.query(Path).filter(Path.parent_id == parent_id).all()
|
||||
|
||||
@@ -4,12 +4,13 @@ from flask import Blueprint, jsonify, request
|
||||
from contexts.RequestContext import RequestContext
|
||||
from db import get_db
|
||||
from db.models.Resource import Resource
|
||||
from api import require_auth, limiter
|
||||
from api import require_auth, limiter, etag_response
|
||||
import logging
|
||||
resource_bp = Blueprint('resource', __name__, url_prefix='/api/resource')
|
||||
logger = logging.getLogger(__name__)
|
||||
@resource_bp.route('/<identifier>', methods=['GET'])
|
||||
@limiter.limit(api.get_rate_limit)
|
||||
|
||||
def get_resource(identifier):
|
||||
with get_db() as session:
|
||||
resource = session.query(Resource).get(identifier)
|
||||
|
||||
Reference in New Issue
Block a user