Adding feed to public API

This commit is contained in:
Yusur 2019-10-27 11:30:14 +01:00
parent 5536e764e7
commit dc33b5567a
5 changed files with 113 additions and 8 deletions

View file

@ -16,7 +16,6 @@ from flask import (
Flask, abort, flash, g, jsonify, redirect, render_template, request,
send_from_directory, session, url_for, __version__ as flask_version)
import hashlib
from peewee import *
import datetime, time, re, os, sys, string, json, html
from functools import wraps
from flask_login import LoginManager
@ -76,12 +75,46 @@ def robots_txt():
def uploads(id, type='jpg'):
return send_from_directory(UPLOAD_DIRECTORY, id + '.' + type)
@app.route('/get_access_token', methods=['POST'])
def send_access_token():
try:
try:
user = User.get(
(User.username == request.form['username']) &
(User.password == pwdhash(request.form['password'])))
except User.DoesNotExist:
return jsonify({
'message': 'Invalid username or password',
'login_correct': False,
'status': 'ok'
})
if user.is_disabled == 1:
user.is_disabled = 0
elif user.is_disabled == 2:
return jsonify({
'message': 'Your account has been disabled by violating our Terms.',
'login_correct': False,
'status': 'ok'
})
return jsonify({
'token': generate_access_token(user),
'login_correct': True,
'status': 'ok'
})
except Exception:
sys.excepthook(*sys.exc_info())
return jsonify({
'message': 'An unknown error has occurred.',
'status': 'fail'
})
from .website import bp
app.register_blueprint(bp)
from .ajax import bp
app.register_blueprint(bp)
from .api import bp
app.register_blueprint(bp)

67
app/api.py Normal file
View file

@ -0,0 +1,67 @@
from flask import Blueprint, jsonify, request
import sys, datetime
from functools import wraps
from .models import User, Message
from .utils import check_access_token, Visibility
bp = Blueprint('api', __name__, url_prefix='/api/V1')
def get_message_info(message):
return {
'id': message.id,
'user': {
'id': message.user.id,
'username': message.user.username,
},
'text': message.text,
'privacy': message.privacy,
'pub_date': message.pub_date.timestamp()
}
def validate_access(func):
@wraps(func)
def wrapper(*args, **kwargs):
access_token = request.args.get('access_token')
if access_token is None:
return jsonify({
'message': 'missing access_token',
'status': 'fail'
})
user = check_access_token(access_token)
if user is None:
return jsonify({
'message': 'invalid access_token',
'status': 'fail'
})
try:
result = func(user, *args, **kwargs)
assert isinstance(result, dict)
except Exception:
sys.excepthook(*sys.exc_info())
return jsonify({
'message': str(sys.exc_info()[1]),
'status': 'fail'
})
result['status'] = 'ok'
return jsonify(result)
return wrapper
@bp.route('/feed')
@validate_access
def feed(self):
timeline_media = []
date = request.args.get('offset')
if date is None:
date = datetime.datetime.now()
else:
date = datetime.datetime.fromtimestamp(date)
query = Visibility(Message
.select()
.where(((Message.user << self.following())
| (Message.user == self))
& (Message.pub_date < date))
.order_by(Message.pub_date.desc())
.limit(20))
for message in query:
timeline_media.append(get_message_info(message))
return {'timeline_media': timeline_media}

View file

@ -178,13 +178,16 @@ def generate_access_token(user):
h.update(str(user.password).encode('utf-8'))
return str(user.id) + ':' + h.hexdigest()[:32]
def check_access_token(user, token):
def check_access_token(token):
uid, hh = token.split(':')
if uid != user.get_id():
return False
try:
user = User[uid]
except User.DoesNotExist:
return
h = hashlib.sha256(get_secret_key())
h.update(b':')
h.update(str(user.id).encode('utf-8'))
h.update(b':')
h.update(str(user.password).encode('utf-8'))
return h.hexdigest()[:32] == hh
if h.hexdigest()[:32] == hh:
return user