You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

256 lines
9.4 KiB
Python

from quart import request, Response, render_template, session, redirect, jsonify, abort, current_app, url_for
import aiohttp
from app import app, db
from app.models import User, Blog, Post
from nanoid import generate
from functools import wraps
import json
from quart_cors import route_cors
@app.before_first_request
def create_tables():
db.create_all()
def user_cook(f):
@wraps(f)
async def decorated_function(*args, **kwargs):
if session.get('username'):
return await current_app.ensure_async(f)(*args, **kwargs)
else:
return abort(403)
return decorated_function
@app.route('/health_check')
#@route_cors()
async def health_check():
status1, _, _, _ = await get_request(f"http://{app.config.get('REDIRECT_SERVER')}/health_check")
status2, _, _, _ = await get_request(f"http://{app.config.get('CONTENT_SERVER')}/health_check")
if status1 == 200 and status2 == 200:
return "OK"
else:
return "Not OK", 500
@app.route('/health_check2')
#@route_cors()
async def health_check2():
return "OK"
@app.route('/image/<path>')
#@route_cors()
async def get_image(path): # put application's code here
#if x.get(""): #if valid image (example 404, 405, corrupted_image)
#...
#else:
path2 = request.args.get("another") #путь до картинки (логика хранения картинки как в CDN (начало пути - начало хеша).
filename = request.args.get("filename")
content_server = app.config.get("CONTENT_SERVER")
if path2 == 'secrets' or path == 'secrets':
return abort(403)
status_code, json_data, data_data, headers = await get_request(f"http://{app.config.get('REDIRECT_SERVER')}/{path}/{content_server}?filename={filename}")
if status_code == 200:
if len(filename.split('.')) > 0 and filename.split('.')[-1] == 'png':
content_type = "Content-Type: image/png"
return Response(
response=data_data,
content_type=content_type,
status=status_code
)
else:
status_code, json_data, data_data, headers = await get_request(f"http://{app.config.get('REDIRECT_SERVER')}/{path2}/{content_server}?filename={filename}")
content_type = headers.get("Content-Type")
if len(filename.split('.')) > 0 and filename.split('.')[-1] == 'png':
content_type = "Content-Type: image/png"
return Response(
response=data_data,
content_type=content_type,
status=status_code
)
async def post_request(url, headers={}, json_inp=None, data=None, cookies=None):
async with aiohttp.ClientSession(cookies=cookies, skip_auto_headers={"User-Agent"}) as session:
async with session.post(url, headers=headers, json=json_inp, data=data) as r:
data = ""
json_data = ""
if hasattr(r, "data"):
data = await r.data
if r.content_type == 'application/json':
json_data = await r.json()
return r.status, json_data, data, r.headers
async def get_request(url, headers={}, cookies={}):
async with aiohttp.ClientSession(cookies=cookies, skip_auto_headers={"User-Agent"}) as session:
async with session.get(url, headers=headers) as r:
data = ""
json_data = ""
if r.content_type == 'application/json':
json_data = await r.json()
return r.status, json_data, data, r.headers
if hasattr(r, "data"):
data = r.data
elif hasattr(r, "content"):
data = await r.content.read()
return r.status, json_data, data, r.headers
@app.route('/file/get/<path>', methods=['GET'])
#@route_cors()
@user_cook
async def get_file(path): # put application's code here
async def check_access(username, filename):
status_code, _, _, _ = await get_request(f"http://{app.config.get('REDIRECT_SERVER')}/check_access?filename={filename}&username={username}")
if status_code == 200:
return True
else:
return False
filename = request.args.get("filename")
content_server = app.config.get("CONTENT_SERVER")
if not await check_access(session.get("username"), filename):
return abort(403)
status_code, json_data, data_data, header = await get_request(f"http://{app.config.get('REDIRECT_SERVER')}/{path}/{content_server}?filename={filename}")
content_type = header.get("Content-Type")
if len(filename.split('.')) > 0 and filename.split('.')[-1] == 'png':
content_type = "Content-Type: image/png"
return Response(
response=data_data,
content_type=content_type,
status=status_code
)
@app.route('/file/list')
#@route_cors()
async def file_list():
content_server = app.config.get("CONTENT_SERVER")
path = request.args.get('path')
status_code, json_data, _, headers = await get_request(f"http://{app.config.get('REDIRECT_SERVER')}/file_list/{path}/{content_server}")
return Response(
response=json.dumps(json_data),
content_type=headers.get('Content-Type'),
status=status_code)
@app.route('/file/upload', methods=['POST'])
#@route_cors()
@user_cook
async def upload_image():
if request.method == 'POST':
if 'file' not in await request.files:
return abort(403)
content_server = app.config.get("CONTENT_SERVER")
path = request.args.get("path")
username = session.get("username")
form_data = aiohttp.FormData()
file_bytes = (await request.files).get('file').stream.read()
filename = (await request.files).get("file").filename
form_data.add_field(name='file', value=file_bytes , filename=filename)
form_data.add_field(name="username", value=username)
form_data.add_field(name="filename", value=filename)
status_code, json_data, data_data, headers = await post_request(f"http://{app.config.get('REDIRECT_SERVER')}/{path}/{content_server}",
data=form_data)
return Response(
response=json.dumps(json_data),
content_type=headers.get('Content-Type'),
status=status_code
)
@app.route('/api/auth/sign_up', methods=["POST"])
#@route_cors()
async def sign_up():
username = (await request.json).get("username")
password = (await request.json).get("password")
is_private = (await request.json).get("is_private")
if username and password:
url_id = generate('1234567890abcdef', 12)
user = User(username=username, blog_url=url_id)
user.set_password(password)
blog = Blog(url_id, is_private)
db.session.add(user)
db.session.add(blog)
db.session.commit()
session["username"] = user.username
return jsonify({"Status": "OK"})
else:
return abort(403)
@app.route('/api/auth/sign_in', methods=["POST"])
async def sign_in():
username = (await request.json).get("username")
password = (await request.json).get("password")
if username and password:
user = User.query.filter_by(username=username).first()
if user is None or not user.check_password(password):
return jsonify({"Result": "Bad creads"}), 400
else:
session["username"] = user.username
return jsonify({"Result": "OK"})
@app.route('/api/self_delete')
#@route_cors()
@user_cook
async def self_remove_acc():
username = session.get("username")
user = User.query.filter_by(username=username).first()
db.session.delete(user)
db.session.commit()
await get_request(f"http://{app.config.get('REDIRECT_SERVER')}/delete/{username}/{app.config.get('CONTENT_SERVER')}")
return jsonify({"result": "OK"})
@app.route('/api/blog')
#@route_cors()
@user_cook
async def get_my_blog():
user = User.query.filter_by(username=session.get("username")).first()
blog = Blog.query.filter_by(url=user.blog_url).first()
return jsonify({"url": blog.url, "is_private": blog.is_private})
@app.route('/api/blogs')
#@route_cors()
async def get_blogs():
blogs = Blog.query.with_entities(Blog.url, Blog.is_private).all()
blogs_list = [{"url": i.url, "is_private": i.is_private} for i in blogs]
return jsonify(blogs_list)
@app.route('/api/blog/<url_id>')
#@route_cors()
@user_cook
async def blog_get_posts(url_id):
blog = Blog.query.filter_by(url=url_id).first()
if blog:
if blog.posts:
return jsonify({"posts": list(map(lambda x: {"id":x.id, "title":x.title}, blog.posts))})
else:
return jsonify({"error": "?"})
else:
return jsonify({"error": "?"})
@app.route('/api/blog/<url_id>/create_post', methods=["POST"])
#@route_cors()
@user_cook
async def blog_create_post(url_id):
blog = Blog.query.filter_by(url=url_id).first()
title = (await request.json).get("title")
body = (await request.json).get("body")
post = Post(title=title, body=body, blog_url=blog.url)
db.session.add(post)
db.session.commit()
this_post = Post.query.filter_by(title=title, body=body).all()[-1]
return jsonify({"Result": "OK", "post_id": this_post.id})
@app.route('/api/blog/<url_id>/post/<int:post_id>')
#@route_cors()
@user_cook
async def blog_read_post(url_id, post_id):
post = Post.query.filter_by(blog_url=url_id, id=post_id).first()
return jsonify({"title": post.title, "body": post.body})
if __name__ == '__main__':
app.run(port=13377, host="0.0.0.0", debug=False)