mirror of
https://github.com/TitanEmbeds/Titan.git
synced 2024-12-24 14:07:03 +01:00
Add a bit of rate limiting
This commit is contained in:
parent
27c6b7d396
commit
06d86e1046
@ -1,7 +1,7 @@
|
|||||||
from config import config
|
from config import config
|
||||||
from database import db
|
from database import db
|
||||||
from flask import Flask, render_template, request, session, url_for, redirect, jsonify
|
from flask import Flask, render_template, request, session, url_for, redirect, jsonify
|
||||||
from titanembeds.utils import cache
|
from titanembeds.utils import cache, rate_limiter
|
||||||
import blueprints.api
|
import blueprints.api
|
||||||
import blueprints.user
|
import blueprints.user
|
||||||
import blueprints.embed
|
import blueprints.embed
|
||||||
@ -16,6 +16,7 @@ app.secret_key = config['app-secret']
|
|||||||
|
|
||||||
db.init_app(app)
|
db.init_app(app)
|
||||||
cache.init_app(app, config={'CACHE_TYPE': 'simple'})
|
cache.init_app(app, config={'CACHE_TYPE': 'simple'})
|
||||||
|
rate_limiter.init_app(app)
|
||||||
|
|
||||||
app.register_blueprint(blueprints.api.api, url_prefix="/api", template_folder="/templates")
|
app.register_blueprint(blueprints.api.api, url_prefix="/api", template_folder="/templates")
|
||||||
app.register_blueprint(blueprints.user.user, url_prefix="/user", template_folder="/templates")
|
app.register_blueprint(blueprints.user.user, url_prefix="/user", template_folder="/templates")
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
from titanembeds.database import db, Guilds, UnauthenticatedUsers, UnauthenticatedBans, AuthenticatedUsers
|
from titanembeds.database import db, Guilds, UnauthenticatedUsers, UnauthenticatedBans, AuthenticatedUsers
|
||||||
from titanembeds.decorators import valid_session_required, discord_users_only
|
from titanembeds.decorators import valid_session_required, discord_users_only
|
||||||
from titanembeds.utils import get_client_ipaddr, discord_api
|
from titanembeds.utils import get_client_ipaddr, discord_api, rate_limiter, channel_ratelimit_key, guild_ratelimit_key
|
||||||
from flask import Blueprint, abort, jsonify, session, request
|
from flask import Blueprint, abort, jsonify, session, request
|
||||||
from sqlalchemy import and_
|
from sqlalchemy import and_
|
||||||
import random
|
import random
|
||||||
@ -78,11 +78,23 @@ def update_user_status(guild_id, username, user_key=None):
|
|||||||
dbUser.ip_address = ip_address
|
dbUser.ip_address = ip_address
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
else:
|
else:
|
||||||
pass #authenticated user todo
|
status = {
|
||||||
|
'username': username,
|
||||||
|
'guild_id': guild_id,
|
||||||
|
'user_id': session['user_id'],
|
||||||
|
'banned': checkUserBanned(guild_id),
|
||||||
|
'revoked': checkUserRevoke(guild_id)
|
||||||
|
}
|
||||||
|
if status['banned'] or status['revoked']:
|
||||||
|
return status
|
||||||
|
dbUser = db.session.query(AuthenticatedUsers).filter(AuthenticatedUsers.guild_id == guild_id, AuthenticatedUsers.client_id == status['user_id']).first()
|
||||||
|
dbUser.bumpTimestamp()
|
||||||
return status
|
return status
|
||||||
|
|
||||||
@api.route("/fetch", methods=["GET"])
|
@api.route("/fetch", methods=["GET"])
|
||||||
@valid_session_required(api=True)
|
@valid_session_required(api=True)
|
||||||
|
@rate_limiter.limit("2500/hour")
|
||||||
|
@rate_limiter.limit("12/minute", key_func = channel_ratelimit_key)
|
||||||
def fetch():
|
def fetch():
|
||||||
channel_id = request.args.get('channel_id')
|
channel_id = request.args.get('channel_id')
|
||||||
after_snowflake = request.args.get('after', None, type=int)
|
after_snowflake = request.args.get('after', None, type=int)
|
||||||
@ -93,12 +105,18 @@ def fetch():
|
|||||||
status = update_user_status(channel_id, session['username'], key)
|
status = update_user_status(channel_id, session['username'], key)
|
||||||
if status['banned'] or status['revoked']:
|
if status['banned'] or status['revoked']:
|
||||||
messages = {}
|
messages = {}
|
||||||
|
status_code = 401
|
||||||
else:
|
else:
|
||||||
messages = discord_api.get_channel_messages(channel_id, after_snowflake)
|
messages = discord_api.get_channel_messages(channel_id, after_snowflake)
|
||||||
return jsonify(messages=messages, status=status)
|
status_code = messages['code']
|
||||||
|
response = jsonify(messages=messages.get('content', messages), status=status)
|
||||||
|
resonse.status_code = status_code
|
||||||
|
return response
|
||||||
|
|
||||||
@api.route("/post", methods=["POST"])
|
@api.route("/post", methods=["POST"])
|
||||||
@valid_session_required(api=True)
|
@valid_session_required(api=True)
|
||||||
|
@rate_limiter.limit("1200/hour")
|
||||||
|
@rate_limiter.limit("6/minute", key_func = channel_ratelimit_key)
|
||||||
def post():
|
def post():
|
||||||
channel_id = request.form.get('channel_id')
|
channel_id = request.form.get('channel_id')
|
||||||
content = request.form.get('content')
|
content = request.form.get('content')
|
||||||
@ -108,11 +126,17 @@ def post():
|
|||||||
key = None
|
key = None
|
||||||
status = update_user_status(channel_id, session['username'], key)
|
status = update_user_status(channel_id, session['username'], key)
|
||||||
if status['banned'] or status['revoked']:
|
if status['banned'] or status['revoked']:
|
||||||
return jsonify(status=status)
|
message = {}
|
||||||
message = discord_api.create_message(channel_id, content)
|
status_code = 401
|
||||||
return jsonify(message=message, status=status)
|
else:
|
||||||
|
message = discord_api.create_message(channel_id, content)
|
||||||
|
status_code = messages['code']
|
||||||
|
response = jsonify(message=message.get('content', message), status=status)
|
||||||
|
response.status_code = status_code
|
||||||
|
return response
|
||||||
|
|
||||||
@api.route("/create_unauthenticated_user", methods=["POST"])
|
@api.route("/create_unauthenticated_user", methods=["POST"])
|
||||||
|
@rate_limiter.limit("4/hour", key_func=guild_ratelimit_key)
|
||||||
def create_unauthenticated_user():
|
def create_unauthenticated_user():
|
||||||
session['unauthenticated'] = True
|
session['unauthenticated'] = True
|
||||||
username = request.form['username']
|
username = request.form['username']
|
||||||
|
@ -6,6 +6,7 @@ from titanembeds.database import db, Guilds, UnauthenticatedUsers, Unauthenticat
|
|||||||
from titanembeds.oauth import authorize_url, token_url, make_authenticated_session, get_current_authenticated_user, get_user_managed_servers, check_user_can_administrate_guild, check_user_permission, generate_avatar_url, generate_guild_icon_url, generate_bot_invite_url
|
from titanembeds.oauth import authorize_url, token_url, make_authenticated_session, get_current_authenticated_user, get_user_managed_servers, check_user_can_administrate_guild, check_user_permission, generate_avatar_url, generate_guild_icon_url, generate_bot_invite_url
|
||||||
|
|
||||||
user = Blueprint("user", __name__)
|
user = Blueprint("user", __name__)
|
||||||
|
|
||||||
@user.route("/login_authenticated", methods=["GET"])
|
@user.route("/login_authenticated", methods=["GET"])
|
||||||
def login_authenticated():
|
def login_authenticated():
|
||||||
session["redirect"] = request.args.get("redirect")
|
session["redirect"] = request.args.get("redirect")
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from titanembeds.discordrest import DiscordREST
|
from titanembeds.discordrest import DiscordREST
|
||||||
from flask import request, session
|
from flask import request, session
|
||||||
from flask.ext.cache import Cache
|
from flask.ext.cache import Cache
|
||||||
|
from flask_limiter import Limiter
|
||||||
from config import config
|
from config import config
|
||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
@ -15,11 +16,11 @@ def get_client_ipaddr():
|
|||||||
return request.remote_addr
|
return request.remote_addr
|
||||||
|
|
||||||
def generate_session_key():
|
def generate_session_key():
|
||||||
sess = session.get("cachestring", None)
|
sess = session.get("sessionunique", None)
|
||||||
if not sess:
|
if not sess:
|
||||||
rand_str = lambda n: ''.join([random.choice(string.lowercase) for i in xrange(n)])
|
rand_str = lambda n: ''.join([random.choice(string.lowercase) for i in xrange(n)])
|
||||||
session['cachestring'] = rand_str(25)
|
session['sessionunique'] = rand_str(25)
|
||||||
sess = session['cachestring']
|
sess = session['sessionunique']
|
||||||
return sess #Totally unique
|
return sess #Totally unique
|
||||||
|
|
||||||
def make_cache_key(*args, **kwargs):
|
def make_cache_key(*args, **kwargs):
|
||||||
@ -33,3 +34,16 @@ def make_guilds_cache_key():
|
|||||||
sess = generate_session_key()
|
sess = generate_session_key()
|
||||||
ip = get_client_ipaddr()
|
ip = get_client_ipaddr()
|
||||||
return (sess + ip + "user_guilds").encode('utf-8')
|
return (sess + ip + "user_guilds").encode('utf-8')
|
||||||
|
|
||||||
|
def channel_ratelimit_key(): # Generate a bucket with given channel & unique session key
|
||||||
|
sess = generate_session_key()
|
||||||
|
channel_id = request.args.get('channel_id', "0")
|
||||||
|
return (sess + channel_id).encode('utf-8')
|
||||||
|
|
||||||
|
def guild_ratelimit_key():
|
||||||
|
sess = generate_session_key()
|
||||||
|
guild_id = request.args.get('guild_id', "0")
|
||||||
|
return (sess + guild_id).encode('utf-8')
|
||||||
|
|
||||||
|
|
||||||
|
rate_limiter = Limiter(key_func=get_client_ipaddr) # Default limit by ip address
|
||||||
|
Loading…
Reference in New Issue
Block a user