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