better ratelimiting

master
Aevann 2023-02-26 03:42:39 +02:00
parent 5e984d8640
commit 7aaeedea36
24 changed files with 405 additions and 226 deletions

View File

@ -57,10 +57,9 @@ class Service(Enum):
RDRAMA = auto() RDRAMA = auto()
CHAT = auto() CHAT = auto()
POST_RATELIMIT = '1/second;10/hour;20/day' POST_RATELIMIT = '10/hour;20/day'
DEFAULT_RATELIMIT_SLOWER = "1/second;30/minute;200/hour;1000/day" DEFAULT_RATELIMIT = "30/minute;200/hour;1000/day"
DEFAULT_RATELIMIT = "3/second;30/minute;200/hour;1000/day" CASINO_RATELIMIT = "100/minute;2000/hour;12000/day"
CASINO_RATELIMIT = "1/second;100/minute;2000/hour;12000/day"
PUSH_NOTIF_LIMIT = 1000 PUSH_NOTIF_LIMIT = 1000
@ -797,7 +796,7 @@ if SITE == 'rdrama.net':
'justcool393': JUSTCOOL_ID 'justcool393': JUSTCOOL_ID
} }
POST_RATELIMIT = '1/second;5/hour;10/day' POST_RATELIMIT = '5/hour;10/day'
elif SITE == 'watchpeopledie.tv': elif SITE == 'watchpeopledie.tv':
EMAIL = "wpd@watchpeopledie.tv" EMAIL = "wpd@watchpeopledie.tv"
TELEGRAM_ID = "wpdtv" TELEGRAM_ID = "wpdtv"

View File

@ -72,8 +72,9 @@ def edit_rules_get(v):
@app.post('/admin/edit_rules') @app.post('/admin/edit_rules')
@limiter.limit("1/second;30/minute;200/hour;1000/day") @limiter.limit('1/second', scope=path)
@limiter.limit("1/second;30/minute;200/hour;1000/day", key_func=get_ID) @limiter.limit("30/minute;200/hour;1000/day")
@limiter.limit("30/minute;200/hour;1000/day", key_func=get_ID)
@admin_level_required(PERMS['EDIT_RULES']) @admin_level_required(PERMS['EDIT_RULES'])
def edit_rules_post(v): def edit_rules_post(v):
rules = request.values.get('rules', '').strip() rules = request.values.get('rules', '').strip()
@ -90,6 +91,7 @@ def edit_rules_post(v):
return render_template('admin/edit_rules.html', v=v, rules=rules, msg='Rules edited successfully!') return render_template('admin/edit_rules.html', v=v, rules=rules, msg='Rules edited successfully!')
@app.post("/@<username>/make_admin") @app.post("/@<username>/make_admin")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['ADMIN_ADD']) @admin_level_required(PERMS['ADMIN_ADD'])
def make_admin(v:User, username): def make_admin(v:User, username):
@ -111,6 +113,7 @@ def make_admin(v:User, username):
@app.post("/@<username>/remove_admin") @app.post("/@<username>/remove_admin")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['ADMIN_REMOVE']) @admin_level_required(PERMS['ADMIN_REMOVE'])
def remove_admin(v:User, username): def remove_admin(v:User, username):
@ -138,8 +141,9 @@ def remove_admin(v:User, username):
return {"message": f"@{user.username} has been removed as admin!"} return {"message": f"@{user.username} has been removed as admin!"}
@app.post("/distribute/<int:option_id>") @app.post("/distribute/<int:option_id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['POST_BETS_DISTRIBUTE']) @admin_level_required(PERMS['POST_BETS_DISTRIBUTE'])
def distribute(v:User, option_id): def distribute(v:User, option_id):
autojanny = get_account(AUTOJANNY_ID) autojanny = get_account(AUTOJANNY_ID)
@ -196,8 +200,9 @@ def distribute(v:User, option_id):
return {"message": f"Each winner has received {coinsperperson} coins!"} return {"message": f"Each winner has received {coinsperperson} coins!"}
@app.post("/@<username>/revert_actions") @app.post("/@<username>/revert_actions")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['ADMIN_ACTIONS_REVERT']) @admin_level_required(PERMS['ADMIN_ACTIONS_REVERT'])
def revert_actions(v:User, username): def revert_actions(v:User, username):
revertee = get_user(username) revertee = get_user(username)
@ -340,6 +345,7 @@ def admin_home(v):
return render_template("admin/admin_home.html", v=v) return render_template("admin/admin_home.html", v=v)
@app.post("/admin/site_settings/<setting>") @app.post("/admin/site_settings/<setting>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['SITE_SETTINGS']) @admin_level_required(PERMS['SITE_SETTINGS'])
def change_settings(v:User, setting): def change_settings(v:User, setting):
@ -367,6 +373,7 @@ def change_settings(v:User, setting):
return {'message': f"{setting.replace('_', ' ').title()} {word}d successfully!"} return {'message': f"{setting.replace('_', ' ').title()} {word}d successfully!"}
@app.post("/admin/clear_cloudflare_cache") @app.post("/admin/clear_cloudflare_cache")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['SITE_CACHE_PURGE_CDN']) @admin_level_required(PERMS['SITE_CACHE_PURGE_CDN'])
def clear_cloudflare_cache(v): def clear_cloudflare_cache(v):
@ -401,9 +408,10 @@ def badge_grant_get(v):
badge_types=badge_types, grant=grant) badge_types=badge_types, grant=grant)
@app.post("/admin/badge_grant") @app.post("/admin/badge_grant")
@limiter.limit('1/second', scope=path)
@feature_required('BADGES') @feature_required('BADGES')
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['USER_BADGES']) @admin_level_required(PERMS['USER_BADGES'])
def badge_grant_post(v): def badge_grant_post(v):
badges = admin_badges_grantable_list(v) badges = admin_badges_grantable_list(v)
@ -462,9 +470,10 @@ def badge_grant_post(v):
return render_template("admin/badge_admin.html", v=v, badge_types=badges, grant=True, msg=f"{new_badge.name} Badge granted to @{user.username} successfully!") return render_template("admin/badge_admin.html", v=v, badge_types=badges, grant=True, msg=f"{new_badge.name} Badge granted to @{user.username} successfully!")
@app.post("/admin/badge_remove") @app.post("/admin/badge_remove")
@limiter.limit('1/second', scope=path)
@feature_required('BADGES') @feature_required('BADGES')
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['USER_BADGES']) @admin_level_required(PERMS['USER_BADGES'])
def badge_remove_post(v): def badge_remove_post(v):
badges = admin_badges_grantable_list(v) badges = admin_badges_grantable_list(v)
@ -605,16 +614,17 @@ def alt_votes_get(v):
@app.get("/admin/alts/") @app.get("/admin/alts/")
@app.get("/@<username>/alts/") @app.get("/@<username>/alts/")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['USER_LINK']) @admin_level_required(PERMS['USER_LINK'])
def admin_view_alts(v:User, username=None): def admin_view_alts(v:User, username=None):
u = get_user(username or request.values.get('username'), graceful=True) u = get_user(username or request.values.get('username'), graceful=True)
return render_template('admin/alts.html', v=v, u=u, alts=u.alts if u else None) return render_template('admin/alts.html', v=v, u=u, alts=u.alts if u else None)
@app.post('/@<username>/alts/') @app.post('/@<username>/alts/')
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['USER_LINK']) @admin_level_required(PERMS['USER_LINK'])
def admin_add_alt(v:User, username): def admin_add_alt(v:User, username):
user1 = get_user(username) user1 = get_user(username)
@ -648,8 +658,9 @@ def admin_add_alt(v:User, username):
return {"message": f"Linked @{user1.username} and @{user2.username} successfully!"} return {"message": f"Linked @{user1.username} and @{user2.username} successfully!"}
@app.post('/@<username>/alts/<int:other>/deleted') @app.post('/@<username>/alts/<int:other>/deleted')
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['USER_LINK']) @admin_level_required(PERMS['USER_LINK'])
def admin_delink_relink_alt(v:User, username, other): def admin_delink_relink_alt(v:User, username, other):
user1 = get_user(username) user1 = get_user(username)
@ -712,6 +723,7 @@ def admin_removed_comments(v):
) )
@app.post("/unagendaposter/<id>") @app.post("/unagendaposter/<id>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['USER_AGENDAPOSTER']) @admin_level_required(PERMS['USER_AGENDAPOSTER'])
def unagendaposter(id, v): def unagendaposter(id, v):
@ -751,8 +763,9 @@ def unagendaposter(id, v):
@app.post("/shadowban/<int:user_id>") @app.post("/shadowban/<int:user_id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['USER_SHADOWBAN']) @admin_level_required(PERMS['USER_SHADOWBAN'])
def shadowban(user_id, v): def shadowban(user_id, v):
user = get_account(user_id) user = get_account(user_id)
@ -786,8 +799,9 @@ def shadowban(user_id, v):
return {"message": f"@{user.username} has been shadowbanned!"} return {"message": f"@{user.username} has been shadowbanned!"}
@app.post("/unshadowban/<int:user_id>") @app.post("/unshadowban/<int:user_id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['USER_SHADOWBAN']) @admin_level_required(PERMS['USER_SHADOWBAN'])
def unshadowban(user_id, v): def unshadowban(user_id, v):
user = get_account(user_id) user = get_account(user_id)
@ -813,8 +827,9 @@ def unshadowban(user_id, v):
@app.post("/admin/title_change/<int:user_id>") @app.post("/admin/title_change/<int:user_id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['USER_TITLE_CHANGE']) @admin_level_required(PERMS['USER_TITLE_CHANGE'])
def admin_title_change(user_id, v): def admin_title_change(user_id, v):
@ -857,8 +872,9 @@ def admin_title_change(user_id, v):
return {"message": f"@{user.username}'s flair has been changed!"} return {"message": f"@{user.username}'s flair has been changed!"}
@app.post("/ban_user/<id>") @app.post("/ban_user/<id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['USER_BAN']) @admin_level_required(PERMS['USER_BAN'])
def ban_user(id, v): def ban_user(id, v):
@ -949,6 +965,7 @@ def ban_user(id, v):
@app.post("/agendaposter/<id>") @app.post("/agendaposter/<id>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['USER_AGENDAPOSTER']) @admin_level_required(PERMS['USER_AGENDAPOSTER'])
def agendaposter(id, v): def agendaposter(id, v):
@ -1043,8 +1060,9 @@ def agendaposter(id, v):
@app.post("/unban_user/<id>") @app.post("/unban_user/<id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['USER_BAN']) @admin_level_required(PERMS['USER_BAN'])
def unban_user(id, v): def unban_user(id, v):
@ -1088,8 +1106,9 @@ def unban_user(id, v):
return {"message": f"@{user.username} has been unbanned!"} return {"message": f"@{user.username} has been unbanned!"}
@app.post("/mute_user/<int:user_id>") @app.post("/mute_user/<int:user_id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['USER_BAN']) @admin_level_required(PERMS['USER_BAN'])
def mute_user(v:User, user_id): def mute_user(v:User, user_id):
user = get_account(user_id) user = get_account(user_id)
@ -1109,8 +1128,9 @@ def mute_user(v:User, user_id):
@app.post("/unmute_user/<int:user_id>") @app.post("/unmute_user/<int:user_id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['USER_BAN']) @admin_level_required(PERMS['USER_BAN'])
def unmute_user(v:User, user_id): def unmute_user(v:User, user_id):
user = get_account(user_id) user = get_account(user_id)
@ -1128,8 +1148,9 @@ def unmute_user(v:User, user_id):
return {"message": f"@{user.username} has been unmuted!"} return {"message": f"@{user.username} has been unmuted!"}
@app.post("/admin/progstack/post/<int:post_id>") @app.post("/admin/progstack/post/<int:post_id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['PROGSTACK']) @admin_level_required(PERMS['PROGSTACK'])
def progstack_post(post_id, v): def progstack_post(post_id, v):
post = get_post(post_id) post = get_post(post_id)
@ -1148,8 +1169,9 @@ def progstack_post(post_id, v):
return {"message": "Progressive stack applied on post!"} return {"message": "Progressive stack applied on post!"}
@app.post("/admin/unprogstack/post/<int:post_id>") @app.post("/admin/unprogstack/post/<int:post_id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['PROGSTACK']) @admin_level_required(PERMS['PROGSTACK'])
def unprogstack_post(post_id, v): def unprogstack_post(post_id, v):
post = get_post(post_id) post = get_post(post_id)
@ -1166,8 +1188,9 @@ def unprogstack_post(post_id, v):
return {"message": "Progressive stack removed from post!"} return {"message": "Progressive stack removed from post!"}
@app.post("/admin/progstack/comment/<int:comment_id>") @app.post("/admin/progstack/comment/<int:comment_id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['PROGSTACK']) @admin_level_required(PERMS['PROGSTACK'])
def progstack_comment(comment_id, v): def progstack_comment(comment_id, v):
comment = get_comment(comment_id) comment = get_comment(comment_id)
@ -1186,8 +1209,9 @@ def progstack_comment(comment_id, v):
return {"message": "Progressive stack applied on comment!"} return {"message": "Progressive stack applied on comment!"}
@app.post("/admin/unprogstack/comment/<int:comment_id>") @app.post("/admin/unprogstack/comment/<int:comment_id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['PROGSTACK']) @admin_level_required(PERMS['PROGSTACK'])
def unprogstack_comment(comment_id, v): def unprogstack_comment(comment_id, v):
comment = get_comment(comment_id) comment = get_comment(comment_id)
@ -1204,8 +1228,9 @@ def unprogstack_comment(comment_id, v):
return {"message": "Progressive stack removed from comment!"} return {"message": "Progressive stack removed from comment!"}
@app.post("/remove_post/<int:post_id>") @app.post("/remove_post/<int:post_id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['POST_COMMENT_MODERATION']) @admin_level_required(PERMS['POST_COMMENT_MODERATION'])
def remove_post(post_id, v): def remove_post(post_id, v):
post = get_post(post_id) post = get_post(post_id)
@ -1233,8 +1258,9 @@ def remove_post(post_id, v):
@app.post("/approve_post/<int:post_id>") @app.post("/approve_post/<int:post_id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['POST_COMMENT_MODERATION']) @admin_level_required(PERMS['POST_COMMENT_MODERATION'])
def approve_post(post_id, v): def approve_post(post_id, v):
post = get_post(post_id) post = get_post(post_id)
@ -1265,6 +1291,7 @@ def approve_post(post_id, v):
@app.post("/distinguish/<int:post_id>") @app.post("/distinguish/<int:post_id>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['POST_COMMENT_DISTINGUISH']) @admin_level_required(PERMS['POST_COMMENT_DISTINGUISH'])
def distinguish_post(post_id, v): def distinguish_post(post_id, v):
@ -1292,6 +1319,7 @@ def distinguish_post(post_id, v):
@app.post("/sticky/<int:post_id>") @app.post("/sticky/<int:post_id>")
@limiter.limit('1/second', scope=path)
@feature_required('PINS') @feature_required('PINS')
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['POST_COMMENT_MODERATION']) @admin_level_required(PERMS['POST_COMMENT_MODERATION'])
@ -1337,6 +1365,7 @@ def sticky_post(post_id, v):
@app.post("/unsticky/<int:post_id>") @app.post("/unsticky/<int:post_id>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['POST_COMMENT_MODERATION']) @admin_level_required(PERMS['POST_COMMENT_MODERATION'])
def unsticky_post(post_id, v): def unsticky_post(post_id, v):
@ -1366,6 +1395,7 @@ def unsticky_post(post_id, v):
return {"message": "Post unpinned!"} return {"message": "Post unpinned!"}
@app.post("/sticky_comment/<int:cid>") @app.post("/sticky_comment/<int:cid>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['POST_COMMENT_MODERATION']) @admin_level_required(PERMS['POST_COMMENT_MODERATION'])
def sticky_comment(cid, v): def sticky_comment(cid, v):
@ -1402,6 +1432,7 @@ def sticky_comment(cid, v):
@app.post("/unsticky_comment/<int:cid>") @app.post("/unsticky_comment/<int:cid>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['POST_COMMENT_MODERATION']) @admin_level_required(PERMS['POST_COMMENT_MODERATION'])
def unsticky_comment(cid, v): def unsticky_comment(cid, v):
@ -1434,8 +1465,9 @@ def unsticky_comment(cid, v):
@app.post("/remove_comment/<int:c_id>") @app.post("/remove_comment/<int:c_id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['POST_COMMENT_MODERATION']) @admin_level_required(PERMS['POST_COMMENT_MODERATION'])
def remove_comment(c_id, v): def remove_comment(c_id, v):
comment = get_comment(c_id) comment = get_comment(c_id)
@ -1455,8 +1487,9 @@ def remove_comment(c_id, v):
@app.post("/approve_comment/<int:c_id>") @app.post("/approve_comment/<int:c_id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['POST_COMMENT_MODERATION']) @admin_level_required(PERMS['POST_COMMENT_MODERATION'])
def approve_comment(c_id, v): def approve_comment(c_id, v):
comment = get_comment(c_id) comment = get_comment(c_id)
@ -1482,6 +1515,7 @@ def approve_comment(c_id, v):
@app.post("/distinguish_comment/<int:c_id>") @app.post("/distinguish_comment/<int:c_id>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['POST_COMMENT_DISTINGUISH']) @admin_level_required(PERMS['POST_COMMENT_DISTINGUISH'])
def admin_distinguish_comment(c_id, v): def admin_distinguish_comment(c_id, v):
@ -1517,8 +1551,9 @@ def admin_banned_domains(v):
banned_domains=banned_domains) banned_domains=banned_domains)
@app.post("/admin/ban_domain") @app.post("/admin/ban_domain")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['DOMAINS_BAN']) @admin_level_required(PERMS['DOMAINS_BAN'])
def ban_domain(v): def ban_domain(v):
@ -1549,8 +1584,9 @@ def ban_domain(v):
@app.post("/admin/unban_domain/<path:domain>") @app.post("/admin/unban_domain/<path:domain>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['DOMAINS_BAN']) @admin_level_required(PERMS['DOMAINS_BAN'])
def unban_domain(v:User, domain): def unban_domain(v:User, domain):
existing = g.db.get(BannedDomain, domain) existing = g.db.get(BannedDomain, domain)
@ -1569,8 +1605,9 @@ def unban_domain(v:User, domain):
@app.post("/admin/nuke_user") @app.post("/admin/nuke_user")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['POST_COMMENT_MODERATION']) @admin_level_required(PERMS['POST_COMMENT_MODERATION'])
def admin_nuke_user(v): def admin_nuke_user(v):
@ -1603,8 +1640,9 @@ def admin_nuke_user(v):
@app.post("/admin/unnuke_user") @app.post("/admin/unnuke_user")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['POST_COMMENT_MODERATION']) @admin_level_required(PERMS['POST_COMMENT_MODERATION'])
def admin_nunuke_user(v): def admin_nunuke_user(v):
@ -1638,8 +1676,9 @@ def admin_nunuke_user(v):
return {"message": f"@{user.username}'s content has been approved!"} return {"message": f"@{user.username}'s content has been approved!"}
@app.post("/blacklist/<int:user_id>") @app.post("/blacklist/<int:user_id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['USER_BLACKLIST']) @admin_level_required(PERMS['USER_BLACKLIST'])
def blacklist_user(user_id, v): def blacklist_user(user_id, v):
user = get_account(user_id) user = get_account(user_id)
@ -1659,8 +1698,9 @@ def blacklist_user(user_id, v):
return {"message": f"@{user.username} has been blacklisted from restricted holes!"} return {"message": f"@{user.username} has been blacklisted from restricted holes!"}
@app.post("/unblacklist/<int:user_id>") @app.post("/unblacklist/<int:user_id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['USER_BLACKLIST']) @admin_level_required(PERMS['USER_BLACKLIST'])
def unblacklist_user(user_id, v): def unblacklist_user(user_id, v):
user = get_account(user_id) user = get_account(user_id)
@ -1687,8 +1727,9 @@ def delete_media_get(v):
return render_template("admin/delete_media.html", v=v) return render_template("admin/delete_media.html", v=v)
@app.post("/admin/delete_media") @app.post("/admin/delete_media")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['DELETE_MEDIA']) @admin_level_required(PERMS['DELETE_MEDIA'])
def delete_media_post(v): def delete_media_post(v):

View File

@ -33,6 +33,7 @@ def submit_marseys(v:User):
@app.post("/submit/marseys") @app.post("/submit/marseys")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def submit_marsey(v:User): def submit_marsey(v:User):
@ -106,6 +107,7 @@ def verify_permissions_and_get_asset(cls, asset_type:str, v:User, name:str, make
return asset return asset
@app.post("/admin/approve/marsey/<name>") @app.post("/admin/approve/marsey/<name>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['MODERATE_PENDING_SUBMITTED_ASSETS']) @admin_level_required(PERMS['MODERATE_PENDING_SUBMITTED_ASSETS'])
def approve_marsey(v, name): def approve_marsey(v, name):
@ -204,6 +206,7 @@ def remove_asset(cls, type_name:str, v:User, name:str) -> dict[str, str]:
return {"message": f"'{name}' removed!"} return {"message": f"'{name}' removed!"}
@app.post("/remove/marsey/<name>") @app.post("/remove/marsey/<name>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def remove_marsey(v:User, name): def remove_marsey(v:User, name):
@ -220,6 +223,7 @@ def submit_hats(v:User):
@app.post("/submit/hats") @app.post("/submit/hats")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def submit_hat(v:User): def submit_hat(v:User):
@ -282,8 +286,9 @@ def submit_hat(v:User):
@app.post("/admin/approve/hat/<name>") @app.post("/admin/approve/hat/<name>")
@limiter.limit("3/second;120/minute;200/hour;1000/day") @limiter.limit('1/second', scope=path)
@limiter.limit("3/second;120/minute;200/hour;1000/day", key_func=get_ID) @limiter.limit("120/minute;200/hour;1000/day")
@limiter.limit("120/minute;200/hour;1000/day", key_func=get_ID)
@admin_level_required(PERMS['MODERATE_PENDING_SUBMITTED_ASSETS']) @admin_level_required(PERMS['MODERATE_PENDING_SUBMITTED_ASSETS'])
def approve_hat(v, name): def approve_hat(v, name):
hat = verify_permissions_and_get_asset(HatDef, "hat", v, name, False) hat = verify_permissions_and_get_asset(HatDef, "hat", v, name, False)
@ -353,6 +358,7 @@ def approve_hat(v, name):
return {"message": f"'{hat.name}' approved!"} return {"message": f"'{hat.name}' approved!"}
@app.post("/remove/hat/<name>") @app.post("/remove/hat/<name>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def remove_hat(v:User, name): def remove_hat(v:User, name):
@ -377,6 +383,7 @@ def update_marseys(v):
@app.post("/admin/update/marseys") @app.post("/admin/update/marseys")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['UPDATE_ASSETS']) @admin_level_required(PERMS['UPDATE_ASSETS'])
def update_marsey(v): def update_marsey(v):
@ -435,6 +442,7 @@ def update_hats(v):
@app.post("/admin/update/hats") @app.post("/admin/update/hats")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['UPDATE_ASSETS']) @admin_level_required(PERMS['UPDATE_ASSETS'])
def update_hat(v): def update_hat(v):

View File

@ -46,6 +46,7 @@ def shop(v:User):
@app.post("/buy/<award>") @app.post("/buy/<award>")
@limiter.limit('1/second', scope=path)
@limiter.limit("100/minute;200/hour;1000/day") @limiter.limit("100/minute;200/hour;1000/day")
@limiter.limit("100/minute;200/hour;1000/day", key_func=get_ID) @limiter.limit("100/minute;200/hour;1000/day", key_func=get_ID)
@auth_required @auth_required
@ -127,8 +128,9 @@ def buy(v:User, award):
return {"message": f"{award_title} award bought!"} return {"message": f"{award_title} award bought!"}
@app.post("/award/<thing_type>/<int:id>") @app.post("/award/<thing_type>/<int:id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def award_thing(v, thing_type, id): def award_thing(v, thing_type, id):
kind = request.values.get("kind", "").strip() kind = request.values.get("kind", "").strip()

View File

@ -80,6 +80,7 @@ def lottershe(v:User):
# Slots # Slots
@app.post("/casino/slots") @app.post("/casino/slots")
@limiter.limit('1/second', scope=path)
@limiter.limit(CASINO_RATELIMIT) @limiter.limit(CASINO_RATELIMIT)
@limiter.limit(CASINO_RATELIMIT, key_func=get_ID) @limiter.limit(CASINO_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
@ -112,6 +113,7 @@ def pull_slots(v:User):
# 21 # 21
@app.post("/casino/twentyone/deal") @app.post("/casino/twentyone/deal")
@limiter.limit('1/second', scope=path)
@limiter.limit(CASINO_RATELIMIT) @limiter.limit(CASINO_RATELIMIT)
@limiter.limit(CASINO_RATELIMIT, key_func=get_ID) @limiter.limit(CASINO_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
@ -132,6 +134,7 @@ def blackjack_deal_to_player(v:User):
@app.post("/casino/twentyone/hit") @app.post("/casino/twentyone/hit")
@limiter.limit('1/second', scope=path)
@limiter.limit(CASINO_RATELIMIT) @limiter.limit(CASINO_RATELIMIT)
@limiter.limit(CASINO_RATELIMIT, key_func=get_ID) @limiter.limit(CASINO_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
@ -148,6 +151,7 @@ def blackjack_player_hit(v:User):
@app.post("/casino/twentyone/stay") @app.post("/casino/twentyone/stay")
@limiter.limit('1/second', scope=path)
@limiter.limit(CASINO_RATELIMIT) @limiter.limit(CASINO_RATELIMIT)
@limiter.limit(CASINO_RATELIMIT, key_func=get_ID) @limiter.limit(CASINO_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
@ -164,6 +168,7 @@ def blackjack_player_stay(v:User):
@app.post("/casino/twentyone/double-down") @app.post("/casino/twentyone/double-down")
@limiter.limit('1/second', scope=path)
@limiter.limit(CASINO_RATELIMIT) @limiter.limit(CASINO_RATELIMIT)
@limiter.limit(CASINO_RATELIMIT, key_func=get_ID) @limiter.limit(CASINO_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
@ -180,6 +185,7 @@ def blackjack_player_doubled_down(v:User):
@app.post("/casino/twentyone/buy-insurance") @app.post("/casino/twentyone/buy-insurance")
@limiter.limit('1/second', scope=path)
@limiter.limit(CASINO_RATELIMIT) @limiter.limit(CASINO_RATELIMIT)
@limiter.limit(CASINO_RATELIMIT, key_func=get_ID) @limiter.limit(CASINO_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
@ -209,6 +215,7 @@ def roulette_get_bets(v:User):
@app.post("/casino/roulette/place-bet") @app.post("/casino/roulette/place-bet")
@limiter.limit('1/second', scope=path)
@limiter.limit(CASINO_RATELIMIT) @limiter.limit(CASINO_RATELIMIT)
@limiter.limit(CASINO_RATELIMIT, key_func=get_ID) @limiter.limit(CASINO_RATELIMIT, key_func=get_ID)
@auth_required @auth_required

View File

@ -82,8 +82,9 @@ def post_pid_comment_cid(cid, pid=None, anything=None, v=None, sub=None):
return render_template(template, v=v, p=post, sort=sort, comment_info=comment_info, render_replies=True, sub=post.subr) return render_template(template, v=v, p=post, sort=sort, comment_info=comment_info, render_replies=True, sub=post.subr)
@app.post("/comment") @app.post("/comment")
@limiter.limit("1/second;20/minute;200/hour;1000/day") @limiter.limit('1/second', scope=path)
@limiter.limit("1/second;20/minute;200/hour;1000/day", key_func=get_ID) @limiter.limit("20/minute;200/hour;1000/day")
@limiter.limit("20/minute;200/hour;1000/day", key_func=get_ID)
@auth_required @auth_required
def comment(v:User): def comment(v:User):
if v.is_suspended: abort(403, "You can't perform this action while banned!") if v.is_suspended: abort(403, "You can't perform this action while banned!")
@ -372,8 +373,9 @@ def comment(v:User):
return {"comment": render_template("comments.html", v=v, comments=[c])} return {"comment": render_template("comments.html", v=v, comments=[c])}
@app.post("/edit_comment/<int:cid>") @app.post("/edit_comment/<int:cid>")
@limiter.limit("1/second;10/minute;100/hour;200/day") @limiter.limit('1/second', scope=path)
@limiter.limit("1/second;10/minute;100/hour;200/day", key_func=get_ID) @limiter.limit("10/minute;100/hour;200/day")
@limiter.limit("10/minute;100/hour;200/day", key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def edit_comment(cid, v): def edit_comment(cid, v):
c = get_comment(cid, v=v) c = get_comment(cid, v=v)
@ -449,8 +451,9 @@ def edit_comment(cid, v):
@app.post("/delete/comment/<int:cid>") @app.post("/delete/comment/<int:cid>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def delete_comment(cid, v): def delete_comment(cid, v):
if v.id == 253: abort(403) if v.id == 253: abort(403)
@ -471,8 +474,9 @@ def delete_comment(cid, v):
return {"message": "Comment deleted!"} return {"message": "Comment deleted!"}
@app.post("/undelete/comment/<int:cid>") @app.post("/undelete/comment/<int:cid>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def undelete_comment(cid, v): def undelete_comment(cid, v):
c = get_comment(cid, v=v) c = get_comment(cid, v=v)
@ -491,6 +495,7 @@ def undelete_comment(cid, v):
return {"message": "Comment undeleted!"} return {"message": "Comment undeleted!"}
@app.post("/pin_comment/<int:cid>") @app.post("/pin_comment/<int:cid>")
@limiter.limit('1/second', scope=path)
@feature_required('PINS') @feature_required('PINS')
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
@ -515,6 +520,7 @@ def pin_comment(cid, v):
@app.post("/unpin_comment/<int:cid>") @app.post("/unpin_comment/<int:cid>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def unpin_comment(cid, v): def unpin_comment(cid, v):
@ -537,8 +543,9 @@ def unpin_comment(cid, v):
@app.post("/save_comment/<int:cid>") @app.post("/save_comment/<int:cid>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def save_comment(cid, v): def save_comment(cid, v):
@ -554,8 +561,9 @@ def save_comment(cid, v):
return {"message": "Comment saved!"} return {"message": "Comment saved!"}
@app.post("/unsave_comment/<int:cid>") @app.post("/unsave_comment/<int:cid>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def unsave_comment(cid, v): def unsave_comment(cid, v):
@ -590,8 +598,9 @@ def diff_words(answer, guess):
@app.post("/wordle/<int:cid>") @app.post("/wordle/<int:cid>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def handle_wordle_action(cid, v): def handle_wordle_action(cid, v):
comment = get_comment(cid) comment = get_comment(cid)
@ -622,6 +631,7 @@ def handle_wordle_action(cid, v):
@app.post("/toggle_comment_nsfw/<int:cid>") @app.post("/toggle_comment_nsfw/<int:cid>")
@limiter.limit('1/second', scope=path)
@feature_required('NSFW_MARKING') @feature_required('NSFW_MARKING')
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required

View File

@ -13,7 +13,7 @@ from files.__main__ import app, cache, limiter
@app.get("/") @app.get("/")
@app.get("/h/<sub>") @app.get("/h/<sub>")
@app.get("/s/<sub>") @app.get("/s/<sub>")
@limiter.limit("3/second;30/minute;5000/hour;10000/day") @limiter.limit("30/minute;5000/hour;10000/day")
@auth_desired_with_logingate @auth_desired_with_logingate
def front_all(v, sub=None, subdomain=None): def front_all(v, sub=None, subdomain=None):
if sub: if sub:

View File

@ -15,6 +15,7 @@ def ping_groups(v:User):
return render_template('groups.html', v=v, groups=groups, cost=GROUP_COST, msg=get_msg(), error=get_error()) return render_template('groups.html', v=v, groups=groups, cost=GROUP_COST, msg=get_msg(), error=get_error())
@app.post("/create_group") @app.post("/create_group")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def create_group(v): def create_group(v):
@ -52,6 +53,7 @@ def create_group(v):
return redirect(f'/ping_groups?msg=!{group} created successfully!') return redirect(f'/ping_groups?msg=!{group} created successfully!')
@app.post("/!<group_name>/apply") @app.post("/!<group_name>/apply")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def join_group(v:User, group_name): def join_group(v:User, group_name):
@ -66,6 +68,7 @@ def join_group(v:User, group_name):
return {"message": f"Application submitted to !{group}'s owner (@{group.owner.username}) successfully!"} return {"message": f"Application submitted to !{group}'s owner (@{group.owner.username}) successfully!"}
@app.post("/!<group_name>/leave") @app.post("/!<group_name>/leave")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def leave_group(v:User, group_name): def leave_group(v:User, group_name):
@ -108,6 +111,7 @@ def memberships(v:User, group_name):
return render_template('group_memberships.html', v=v, group=group, members=members, applications=applications) return render_template('group_memberships.html', v=v, group=group, members=members, applications=applications)
@app.post("/!<group_name>/<user_id>/approve") @app.post("/!<group_name>/<user_id>/approve")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def group_approve(v:User, group_name, user_id): def group_approve(v:User, group_name, user_id):
@ -129,6 +133,7 @@ def group_approve(v:User, group_name, user_id):
return {"message": f'You have approved @{application.user.username} successfully!'} return {"message": f'You have approved @{application.user.username} successfully!'}
@app.post("/!<group_name>/<user_id>/reject") @app.post("/!<group_name>/<user_id>/reject")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def group_reject(v:User, group_name, user_id): def group_reject(v:User, group_name, user_id):

View File

@ -28,6 +28,7 @@ def hats(v:User):
return render_template("hats.html", owned_hat_ids=owned_hat_ids, hats=hats, v=v, sales=sales, num_of_hats=num_of_hats) return render_template("hats.html", owned_hat_ids=owned_hat_ids, hats=hats, v=v, sales=sales, num_of_hats=num_of_hats)
@app.post("/buy_hat/<int:hat_id>") @app.post("/buy_hat/<int:hat_id>")
@limiter.limit('1/second', scope=path)
@limiter.limit('100/minute;1000/3 days') @limiter.limit('100/minute;1000/3 days')
@limiter.limit('100/minute;1000/3 days', key_func=get_ID) @limiter.limit('100/minute;1000/3 days', key_func=get_ID)
@auth_required @auth_required
@ -80,6 +81,7 @@ def buy_hat(v:User, hat_id):
@app.post("/equip_hat/<int:hat_id>") @app.post("/equip_hat/<int:hat_id>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def equip_hat(v:User, hat_id): def equip_hat(v:User, hat_id):
@ -95,6 +97,7 @@ def equip_hat(v:User, hat_id):
return {"message": f"'{hat.name}' equipped!"} return {"message": f"'{hat.name}' equipped!"}
@app.post("/unequip_hat/<int:hat_id>") @app.post("/unequip_hat/<int:hat_id>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def unequip_hat(v:User, hat_id): def unequip_hat(v:User, hat_id):

View File

@ -38,6 +38,7 @@ def login_deduct_when(resp):
return g.login_failed return g.login_failed
@app.post("/login") @app.post("/login")
@limiter.limit('1/second', scope=path)
@auth_desired @auth_desired
@limiter.limit("6/minute;10/day", deduct_when=login_deduct_when) @limiter.limit("6/minute;10/day", deduct_when=login_deduct_when)
def login_post(v:Optional[User]): def login_post(v:Optional[User]):
@ -135,8 +136,9 @@ def me(v:User):
@app.post("/logout") @app.post("/logout")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def logout(v): def logout(v):
loggedin = cache.get(f'{SITE}_loggedin') or {} loggedin = cache.get(f'{SITE}_loggedin') or {}
@ -193,7 +195,8 @@ def sign_up_get(v:Optional[User]):
@app.post("/signup") @app.post("/signup")
@limiter.limit("1/second;10/day") @limiter.limit('1/second', scope=path)
@limiter.limit("10/day")
@auth_desired @auth_desired
def sign_up_post(v:Optional[User]): def sign_up_post(v:Optional[User]):
if not get_setting('signups'): if not get_setting('signups'):
@ -365,7 +368,8 @@ def get_forgot():
@app.post("/forgot") @app.post("/forgot")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT)
def post_forgot(): def post_forgot():
username = request.values.get("username") username = request.values.get("username")
@ -429,7 +433,8 @@ def get_reset():
@app.post("/reset") @app.post("/reset")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT)
@auth_desired @auth_desired
def post_reset(v:Optional[User]): def post_reset(v:Optional[User]):
if v: return redirect('/') if v: return redirect('/')
@ -474,7 +479,8 @@ def lost_2fa(v:Optional[User]):
return render_template("login/lost_2fa.html", v=v) return render_template("login/lost_2fa.html", v=v)
@app.post("/lost_2fa") @app.post("/lost_2fa")
@limiter.limit("1/second;6/minute;200/hour;1000/day") @limiter.limit('1/second', scope=path)
@limiter.limit("6/minute;200/hour;1000/day")
def lost_2fa_post(): def lost_2fa_post():
username=request.values.get("username") username=request.values.get("username")
user=get_user(username, graceful=True) user=get_user(username, graceful=True)

View File

@ -7,6 +7,7 @@ from files.routes.wrappers import *
from files.__main__ import app, limiter from files.__main__ import app, limiter
@app.post("/lottery/end") @app.post("/lottery/end")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['LOTTERY_ADMIN']) @admin_level_required(PERMS['LOTTERY_ADMIN'])
def lottery_end(v): def lottery_end(v):
@ -15,6 +16,7 @@ def lottery_end(v):
@app.post("/lottery/start") @app.post("/lottery/start")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['LOTTERY_ADMIN']) @admin_level_required(PERMS['LOTTERY_ADMIN'])
def lottery_start(v): def lottery_start(v):
@ -23,8 +25,9 @@ def lottery_start(v):
@app.post("/lottery/buy") @app.post("/lottery/buy")
@limiter.limit("3/second;100/minute;500/hour;1000/day") @limiter.limit('1/second', scope=path)
@limiter.limit("3/second;100/minute;500/hour;1000/day", key_func=get_ID) @limiter.limit("100/minute;500/hour;1000/day")
@limiter.limit("100/minute;500/hour;1000/day", key_func=get_ID)
@auth_required @auth_required
def lottery_buy(v:User): def lottery_buy(v:User):
try: quantity = int(request.values.get("quantity")) try: quantity = int(request.values.get("quantity"))
@ -41,8 +44,8 @@ def lottery_buy(v:User):
@app.get("/lottery/active") @app.get("/lottery/active")
@limiter.limit("3/second;100/minute;500/hour;1000/day") @limiter.limit("100/minute;500/hour;1000/day")
@limiter.limit("3/second;100/minute;500/hour;1000/day", key_func=get_ID) @limiter.limit("100/minute;500/hour;1000/day", key_func=get_ID)
@auth_required @auth_required
def lottery_active(v:User): def lottery_active(v:User):
lottery, participants = get_active_lottery_stats() lottery, participants = get_active_lottery_stats()

View File

@ -10,8 +10,9 @@ from files.routes.users import claim_rewards
from files.__main__ import app, limiter from files.__main__ import app, limiter
@app.post("/verify_email") @app.post("/verify_email")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def verify_email(v): def verify_email(v):
send_verification_email(v) send_verification_email(v)

View File

@ -11,6 +11,7 @@ from files.routes.wrappers import *
from files.__main__ import app from files.__main__ import app
@app.post("/clear") @app.post("/clear")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def clear(v): def clear(v):

View File

@ -17,8 +17,9 @@ def authorize_prompt(v:User):
return render_template("oauth.html", v=v, application=application) return render_template("oauth.html", v=v, application=application)
@app.post("/authorize") @app.post("/authorize")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def authorize(v): def authorize(v):
client_id = request.values.get("client_id") client_id = request.values.get("client_id")
@ -37,8 +38,9 @@ def authorize(v):
return redirect(f"{application.redirect_uri}?token={access_token}") return redirect(f"{application.redirect_uri}?token={access_token}")
@app.post("/rescind/<int:aid>") @app.post("/rescind/<int:aid>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def rescind(v, aid): def rescind(v, aid):
@ -49,8 +51,9 @@ def rescind(v, aid):
@app.post("/api_keys") @app.post("/api_keys")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def request_api_keys(v): def request_api_keys(v):
new_app = OauthApp( new_app = OauthApp(
@ -90,8 +93,9 @@ def request_api_keys(v):
@app.post("/delete_app/<int:aid>") @app.post("/delete_app/<int:aid>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def delete_oauth_app(v, aid): def delete_oauth_app(v, aid):
try: try:
@ -113,8 +117,9 @@ def delete_oauth_app(v, aid):
@app.post("/edit_app/<int:aid>") @app.post("/edit_app/<int:aid>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def edit_oauth_app(v, aid): def edit_oauth_app(v, aid):
try: try:
@ -137,8 +142,9 @@ def edit_oauth_app(v, aid):
@app.post("/admin/app/approve/<int:aid>") @app.post("/admin/app/approve/<int:aid>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['APPS_MODERATION']) @admin_level_required(PERMS['APPS_MODERATION'])
def admin_app_approve(v, aid): def admin_app_approve(v, aid):
@ -174,8 +180,9 @@ def admin_app_approve(v, aid):
@app.post("/admin/app/revoke/<int:aid>") @app.post("/admin/app/revoke/<int:aid>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['APPS_MODERATION']) @admin_level_required(PERMS['APPS_MODERATION'])
def admin_app_revoke(v, aid): def admin_app_revoke(v, aid):
@ -200,8 +207,9 @@ def admin_app_revoke(v, aid):
@app.post("/admin/app/reject/<int:aid>") @app.post("/admin/app/reject/<int:aid>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@admin_level_required(PERMS['APPS_MODERATION']) @admin_level_required(PERMS['APPS_MODERATION'])
def admin_app_reject(v, aid): def admin_app_reject(v, aid):
@ -286,8 +294,9 @@ def admin_apps_list(v):
@app.post("/reroll/<int:aid>") @app.post("/reroll/<int:aid>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def reroll_oauth_tokens(aid, v): def reroll_oauth_tokens(aid, v):

View File

@ -6,6 +6,7 @@ from files.__main__ import app
@app.post("/vote/post/option/<int:option_id>") @app.post("/vote/post/option/<int:option_id>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def vote_option(option_id, v): def vote_option(option_id, v):
@ -85,6 +86,7 @@ def option_votes(option_id, v):
@app.post("/vote/comment/option/<int:option_id>") @app.post("/vote/comment/option/<int:option_id>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def vote_option_comment(option_id, v): def vote_option_comment(option_id, v):

View File

@ -33,8 +33,9 @@ from files.__main__ import app, limiter
titleheaders = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Safari/537.36"} titleheaders = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.72 Safari/537.36"}
@app.post("/publish/<int:pid>") @app.post("/publish/<int:pid>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def publish(pid, v): def publish(pid, v):
post = get_post(pid) post = get_post(pid)
@ -174,7 +175,7 @@ def post_id(pid, anything=None, v=None, sub=None):
fart=get_setting('fart_mode')) fart=get_setting('fart_mode'))
@app.get("/view_more/<int:pid>/<sort>/<offset>") @app.get("/view_more/<int:pid>/<sort>/<offset>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit(DEFAULT_RATELIMIT)
@auth_desired_with_logingate @auth_desired_with_logingate
def view_more(v, pid, sort, offset): def view_more(v, pid, sort, offset):
post = get_post(pid, v=v) post = get_post(pid, v=v)
@ -229,7 +230,7 @@ def view_more(v, pid, sort, offset):
@app.get("/more_comments/<int:cid>") @app.get("/more_comments/<int:cid>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit(DEFAULT_RATELIMIT)
@auth_desired_with_logingate @auth_desired_with_logingate
def more_comments(v, cid): def more_comments(v, cid):
try: cid = int(cid) try: cid = int(cid)
@ -253,8 +254,9 @@ def more_comments(v, cid):
return render_template("comments.html", v=v, comments=comments, p=p, render_replies=True) return render_template("comments.html", v=v, comments=comments, p=p, render_replies=True)
@app.post("/edit_post/<int:pid>") @app.post("/edit_post/<int:pid>")
@limiter.limit("1/second;10/minute;100/hour;200/day") @limiter.limit('1/second', scope=path)
@limiter.limit("1/second;10/minute;100/hour;200/day", key_func=get_ID) @limiter.limit("10/minute;100/hour;200/day")
@limiter.limit("10/minute;100/hour;200/day", key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def edit_post(pid, v): def edit_post(pid, v):
p = get_post(pid) p = get_post(pid)
@ -474,6 +476,7 @@ def thumbnail_thread(pid:int, vid:int):
@app.post("/is_repost") @app.post("/is_repost")
@limiter.limit('1/second', scope=path)
def is_repost(): def is_repost():
not_a_repost = {'permalink': ''} not_a_repost = {'permalink': ''}
if not FEATURES['REPOST_DETECTION']: if not FEATURES['REPOST_DETECTION']:
@ -518,6 +521,7 @@ def is_repost():
@app.post("/submit") @app.post("/submit")
@app.post("/h/<sub>/submit") @app.post("/h/<sub>/submit")
@limiter.limit('1/second', scope=path)
@limiter.limit(POST_RATELIMIT) @limiter.limit(POST_RATELIMIT)
@limiter.limit(POST_RATELIMIT, key_func=get_ID) @limiter.limit(POST_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
@ -799,8 +803,9 @@ def submit_post(v:User, sub=None):
return {"post_id": post.id} return {"post_id": post.id}
@app.post("/delete_post/<int:pid>") @app.post("/delete_post/<int:pid>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def delete_post_pid(pid, v): def delete_post_pid(pid, v):
post = get_post(pid) post = get_post(pid)
@ -826,8 +831,9 @@ def delete_post_pid(pid, v):
return {"message": "Post deleted!"} return {"message": "Post deleted!"}
@app.post("/undelete_post/<int:pid>") @app.post("/undelete_post/<int:pid>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def undelete_post_pid(pid, v): def undelete_post_pid(pid, v):
post = get_post(pid) post = get_post(pid)
@ -848,6 +854,7 @@ def undelete_post_pid(pid, v):
@app.post("/mark_post_nsfw/<int:pid>") @app.post("/mark_post_nsfw/<int:pid>")
@limiter.limit('1/second', scope=path)
@feature_required('NSFW_MARKING') @feature_required('NSFW_MARKING')
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
@ -884,6 +891,7 @@ def mark_post_nsfw(pid, v):
return {"message": "Post has been marked as +18!"} return {"message": "Post has been marked as +18!"}
@app.post("/unmark_post_nsfw/<int:pid>") @app.post("/unmark_post_nsfw/<int:pid>")
@limiter.limit('1/second', scope=path)
@feature_required('NSFW_MARKING') @feature_required('NSFW_MARKING')
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
@ -920,8 +928,9 @@ def unmark_post_nsfw(pid, v):
return {"message": "Post has been unmarked as +18!"} return {"message": "Post has been unmarked as +18!"}
@app.post("/save_post/<int:pid>") @app.post("/save_post/<int:pid>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def save_post(pid, v): def save_post(pid, v):
@ -936,8 +945,9 @@ def save_post(pid, v):
return {"message": "Post saved!"} return {"message": "Post saved!"}
@app.post("/unsave_post/<int:pid>") @app.post("/unsave_post/<int:pid>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def unsave_post(pid, v): def unsave_post(pid, v):
@ -951,6 +961,7 @@ def unsave_post(pid, v):
return {"message": "Post unsaved!"} return {"message": "Post unsaved!"}
@app.post("/pin/<int:post_id>") @app.post("/pin/<int:post_id>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def pin_post(post_id, v): def pin_post(post_id, v):
@ -965,8 +976,8 @@ def pin_post(post_id, v):
return abort(404, "Post not found!") return abort(404, "Post not found!")
@app.put("/post/<int:post_id>/new") @app.put("/post/<int:post_id>/new")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def set_new_sort(post_id:int, v:User): def set_new_sort(post_id:int, v:User):
post = get_post(post_id) post = get_post(post_id)
@ -987,8 +998,8 @@ def set_new_sort(post_id:int, v:User):
@app.delete("/post/<int:post_id>/new") @app.delete("/post/<int:post_id>/new")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def unset_new_sort(post_id:int, v:User): def unset_new_sort(post_id:int, v:User):
post = get_post(post_id) post = get_post(post_id)

View File

@ -4,6 +4,7 @@ from flask import request, g
from files.classes.push_subscriptions import PushSubscription from files.classes.push_subscriptions import PushSubscription
@app.post("/push_subscribe") @app.post("/push_subscribe")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def push_subscribe(v): def push_subscribe(v):

View File

@ -12,8 +12,9 @@ from files.routes.wrappers import *
from files.__main__ import app, limiter, cache from files.__main__ import app, limiter, cache
@app.post("/report/post/<int:pid>") @app.post("/report/post/<int:pid>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def flag_post(pid, v): def flag_post(pid, v):
post = get_post(pid) post = get_post(pid)
@ -68,8 +69,9 @@ def flag_post(pid, v):
@app.post("/report/comment/<int:cid>") @app.post("/report/comment/<int:cid>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def flag_comment(cid, v): def flag_comment(cid, v):
@ -94,8 +96,9 @@ def flag_comment(cid, v):
@app.post('/del_report/post/<int:pid>/<int:uid>') @app.post('/del_report/post/<int:pid>/<int:uid>')
@limiter.limit("4/second;100/minute;300/hour;2000/day") @limiter.limit('1/second', scope=path)
@limiter.limit("4/second;100/minute;300/hour;2000/day", key_func=get_ID) @limiter.limit("100/minute;300/hour;2000/day")
@limiter.limit("100/minute;300/hour;2000/day", key_func=get_ID)
@admin_level_required(PERMS['FLAGS_REMOVE']) @admin_level_required(PERMS['FLAGS_REMOVE'])
def remove_report_post(v, pid, uid): def remove_report_post(v, pid, uid):
try: try:
@ -118,8 +121,9 @@ def remove_report_post(v, pid, uid):
@app.post('/del_report/comment/<int:cid>/<int:uid>') @app.post('/del_report/comment/<int:cid>/<int:uid>')
@limiter.limit("4/second;100/minute;300/hour;2000/day") @limiter.limit('1/second', scope=path)
@limiter.limit("4/second;100/minute;300/hour;2000/day", key_func=get_ID) @limiter.limit("100/minute;300/hour;2000/day")
@limiter.limit("100/minute;300/hour;2000/day", key_func=get_ID)
@admin_level_required(PERMS['FLAGS_REMOVE']) @admin_level_required(PERMS['FLAGS_REMOVE'])
def remove_report_comment(v, cid, uid): def remove_report_comment(v, cid, uid):
try: try:

View File

@ -37,8 +37,8 @@ def settings_personal(v:User):
return render_template("settings/personal.html", v=v, error=get_error(), msg=get_msg()) return render_template("settings/personal.html", v=v, error=get_error(), msg=get_msg())
@app.delete('/settings/background') @app.delete('/settings/background')
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def remove_background(v): def remove_background(v):
if v.background: if v.background:
@ -49,8 +49,9 @@ def remove_background(v):
return {"message": "Background removed!"} return {"message": "Background removed!"}
@app.post('/settings/custom_background') @app.post('/settings/custom_background')
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def upload_custom_background(v): def upload_custom_background(v):
if g.is_tor: abort(403, "Image uploads are not allowed through TOR!") if g.is_tor: abort(403, "Image uploads are not allowed through TOR!")
@ -73,8 +74,9 @@ def upload_custom_background(v):
return redirect('/settings/personal') return redirect('/settings/personal')
@app.post('/settings/profile_background') @app.post('/settings/profile_background')
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def upload_profile_background(v): def upload_profile_background(v):
if g.is_tor: abort(403, "Image uploads are not allowed through TOR!") if g.is_tor: abort(403, "Image uploads are not allowed through TOR!")
@ -94,8 +96,8 @@ def upload_profile_background(v):
return redirect(f'/@{v.username}') return redirect(f'/@{v.username}')
@app.delete('/settings/profile_background') @app.delete('/settings/profile_background')
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def delete_profile_background(v): def delete_profile_background(v):
if v.profile_background: if v.profile_background:
@ -104,8 +106,9 @@ def delete_profile_background(v):
return {"message": "Profile background removed!"} return {"message": "Profile background removed!"}
@app.post("/settings/personal") @app.post("/settings/personal")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def settings_personal_post(v): def settings_personal_post(v):
if v.id == 253 and request.values.get("private"): if v.id == 253 and request.values.get("private"):
@ -361,6 +364,7 @@ def settings_personal_post(v):
@app.post("/settings/filters") @app.post("/settings/filters")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def filters(v:User): def filters(v:User):
@ -388,37 +392,42 @@ def set_color(v:User, attr:str, color:Optional[str]):
@app.post("/settings/namecolor") @app.post("/settings/namecolor")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def namecolor(v): def namecolor(v):
return set_color(v, "namecolor", request.values.get("namecolor")) return set_color(v, "namecolor", request.values.get("namecolor"))
@app.post("/settings/themecolor") @app.post("/settings/themecolor")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def themecolor(v): def themecolor(v):
return set_color(v, "themecolor", request.values.get("themecolor")) return set_color(v, "themecolor", request.values.get("themecolor"))
@app.post("/settings/titlecolor") @app.post("/settings/titlecolor")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def titlecolor(v): def titlecolor(v):
return set_color(v, "titlecolor", request.values.get("titlecolor")) return set_color(v, "titlecolor", request.values.get("titlecolor"))
@app.post("/settings/verifiedcolor") @app.post("/settings/verifiedcolor")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def verifiedcolor(v): def verifiedcolor(v):
if not v.verified: abort(403, "You don't have a checkmark") if not v.verified: abort(403, "You don't have a checkmark")
return set_color(v, "verifiedcolor", request.values.get("verifiedcolor")) return set_color(v, "verifiedcolor", request.values.get("verifiedcolor"))
@app.post("/settings/security") @app.post("/settings/security")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def settings_security_post(v): def settings_security_post(v):
if request.values.get("new_password"): if request.values.get("new_password"):
@ -491,8 +500,9 @@ def settings_security_post(v):
return render_template("settings/security.html", v=v, msg="Two-factor authentication disabled!") return render_template("settings/security.html", v=v, msg="Two-factor authentication disabled!")
@app.post("/settings/log_out_all_others") @app.post("/settings/log_out_all_others")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def settings_log_out_others(v): def settings_log_out_others(v):
submitted_password = request.values.get("password", "").strip() submitted_password = request.values.get("password", "").strip()
@ -507,8 +517,9 @@ def settings_log_out_others(v):
@app.post("/settings/images/profile") @app.post("/settings/images/profile")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def settings_images_profile(v): def settings_images_profile(v):
if g.is_tor: abort(403, "Image uploads are not allowed through TOR!") if g.is_tor: abort(403, "Image uploads are not allowed through TOR!")
@ -545,9 +556,10 @@ def settings_images_profile(v):
@app.post("/settings/images/banner") @app.post("/settings/images/banner")
@limiter.limit('1/second', scope=path)
@feature_required('USERS_PROFILE_BANNER') @feature_required('USERS_PROFILE_BANNER')
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def settings_images_banner(v): def settings_images_banner(v):
if g.is_tor: abort(403, "Image uploads are not allowed through TOR!") if g.is_tor: abort(403, "Image uploads are not allowed through TOR!")
@ -573,8 +585,9 @@ def settings_css_get(v:User):
return render_template("settings/css.html", v=v, msg=get_msg(), profilecss=v.profilecss) return render_template("settings/css.html", v=v, msg=get_msg(), profilecss=v.profilecss)
@app.post("/settings/css") @app.post("/settings/css")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def settings_css(v): def settings_css(v):
if v.agendaposter: abort(400, "Agendapostered users can't edit CSS!") if v.agendaposter: abort(400, "Agendapostered users can't edit CSS!")
@ -585,8 +598,9 @@ def settings_css(v):
return render_template("settings/css.html", v=v, msg="Custom CSS successfully updated!", profilecss=v.profilecss) return render_template("settings/css.html", v=v, msg="Custom CSS successfully updated!", profilecss=v.profilecss)
@app.post("/settings/profilecss") @app.post("/settings/profilecss")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def settings_profilecss(v): def settings_profilecss(v):
profilecss = request.values.get("profilecss", v.profilecss).strip().replace('\\', '').strip()[:CSS_LENGTH_LIMIT] profilecss = request.values.get("profilecss", v.profilecss).strip().replace('\\', '').strip()[:CSS_LENGTH_LIMIT]
@ -610,8 +624,9 @@ def settings_security(v:User):
) )
@app.post("/settings/block") @app.post("/settings/block")
@limiter.limit("1/second;20/day") @limiter.limit('1/second', scope=path)
@limiter.limit("1/second;20/day", key_func=get_ID) @limiter.limit("20/day")
@limiter.limit("20/day", key_func=get_ID)
@auth_required @auth_required
def settings_block_user(v): def settings_block_user(v):
user = get_user(request.values.get("username"), graceful=True) user = get_user(request.values.get("username"), graceful=True)
@ -637,8 +652,9 @@ def settings_block_user(v):
@app.post("/settings/unblock") @app.post("/settings/unblock")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def settings_unblock_user(v): def settings_unblock_user(v):
user = get_user(request.values.get("username")) user = get_user(request.values.get("username"))
@ -663,8 +679,9 @@ def settings_advanced_get(v:User):
return render_template("settings/advanced.html", v=v, msg=get_msg(), error=get_error()) return render_template("settings/advanced.html", v=v, msg=get_msg(), error=get_error())
@app.post("/settings/name_change") @app.post("/settings/name_change")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def settings_name_change(v): def settings_name_change(v):
new_name=request.values.get("name").strip() new_name=request.values.get("name").strip()
@ -701,9 +718,10 @@ def settings_name_change(v):
return redirect("/settings/personal?msg=Name successfully changed!") return redirect("/settings/personal?msg=Name successfully changed!")
@app.post("/settings/song_change_mp3") @app.post("/settings/song_change_mp3")
@limiter.limit('1/second', scope=path)
@feature_required('USERS_PROFILE_SONG') @feature_required('USERS_PROFILE_SONG')
@limiter.limit("1/second;10/day") @limiter.limit("10/day")
@limiter.limit("1/second;10/day", key_func=get_ID) @limiter.limit("10/day", key_func=get_ID)
@auth_required @auth_required
def settings_song_change_mp3(v): def settings_song_change_mp3(v):
file = request.files['file'] file = request.files['file']
@ -765,9 +783,10 @@ def _change_song_youtube(vid, id):
@app.post("/settings/song_change") @app.post("/settings/song_change")
@limiter.limit('1/second', scope=path)
@feature_required('USERS_PROFILE_SONG') @feature_required('USERS_PROFILE_SONG')
@limiter.limit("3/second;10/day") @limiter.limit("10/day")
@limiter.limit("3/second;10/day", key_func=get_ID) @limiter.limit("10/day", key_func=get_ID)
@auth_required @auth_required
def settings_song_change(v): def settings_song_change(v):
song=request.values.get("song").strip() song=request.values.get("song").strip()
@ -817,8 +836,9 @@ def settings_song_change(v):
return redirect("/settings/personal?msg=Profile Anthem successfully updated. Wait 5 minutes for the change to take effect.") return redirect("/settings/personal?msg=Profile Anthem successfully updated. Wait 5 minutes for the change to take effect.")
@app.post("/settings/title_change") @app.post("/settings/title_change")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def settings_title_change(v): def settings_title_change(v):
if v.flairchanged: abort(403) if v.flairchanged: abort(403)
@ -845,9 +865,10 @@ def settings_title_change(v):
@app.post("/settings/pronouns_change") @app.post("/settings/pronouns_change")
@limiter.limit('1/second', scope=path)
@feature_required('PRONOUNS') @feature_required('PRONOUNS')
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def settings_pronouns_change(v): def settings_pronouns_change(v):
pronouns = sanitize_settings_text(request.values.get("pronouns")) pronouns = sanitize_settings_text(request.values.get("pronouns"))
@ -872,8 +893,9 @@ def settings_pronouns_change(v):
@app.post("/settings/checkmark_text") @app.post("/settings/checkmark_text")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def settings_checkmark_text(v): def settings_checkmark_text(v):
if not v.verified: abort(403) if not v.verified: abort(403)
@ -886,6 +908,7 @@ def settings_checkmark_text(v):
if IS_FISTMAS(): if IS_FISTMAS():
@app.post("/events/fistmas2022/darkmode") @app.post("/events/fistmas2022/darkmode")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def event_darkmode(v): def event_darkmode(v):

View File

@ -227,8 +227,9 @@ def contact(v:Optional[User]):
return render_template("contact.html", v=v, msg=get_msg()) return render_template("contact.html", v=v, msg=get_msg())
@app.post("/contact") @app.post("/contact")
@limiter.limit("1/second;1/2 minutes;10/day") @limiter.limit('1/second', scope=path)
@limiter.limit("1/second;1/2 minutes;10/day", key_func=get_ID) @limiter.limit("1/2 minutes;10/day")
@limiter.limit("1/2 minutes;10/day", key_func=get_ID)
@auth_required @auth_required
def submit_contact(v): def submit_contact(v):
body = request.values.get("message") body = request.values.get("message")
@ -321,6 +322,7 @@ def mobile_app(v:Optional[User]):
return render_template("app.html", v=v) return render_template("app.html", v=v)
@app.post("/dismiss_mobile_tip") @app.post("/dismiss_mobile_tip")
@limiter.limit('1/second', scope=path)
def dismiss_mobile_tip(): def dismiss_mobile_tip():
session["tooltip_last_dismissed"] = int(time.time()) session["tooltip_last_dismissed"] = int(time.time())
return "", 204 return "", 204

View File

@ -8,6 +8,7 @@ from .front import frontlist
from files.__main__ import app, cache, limiter from files.__main__ import app, cache, limiter
@app.post("/exile/post/<int:pid>") @app.post("/exile/post/<int:pid>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def exile_post(v:User, pid): def exile_post(v:User, pid):
@ -40,6 +41,7 @@ def exile_post(v:User, pid):
return {"message": f"@{u.username} has been exiled from /h/{sub} successfully!"} return {"message": f"@{u.username} has been exiled from /h/{sub} successfully!"}
@app.post("/exile/comment/<int:cid>") @app.post("/exile/comment/<int:cid>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def exile_comment(v:User, cid): def exile_comment(v:User, cid):
@ -72,6 +74,7 @@ def exile_comment(v:User, cid):
return {"message": f"@{u.username} has been exiled from /h/{sub} successfully!"} return {"message": f"@{u.username} has been exiled from /h/{sub} successfully!"}
@app.post("/h/<sub>/unexile/<int:uid>") @app.post("/h/<sub>/unexile/<int:uid>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def unexile(v:User, sub, uid): def unexile(v:User, sub, uid):
@ -101,6 +104,7 @@ def unexile(v:User, sub, uid):
return redirect(f'/h/{sub}/exilees') return redirect(f'/h/{sub}/exilees')
@app.post("/h/<sub>/block") @app.post("/h/<sub>/block")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def block_sub(v:User, sub): def block_sub(v:User, sub):
@ -113,6 +117,7 @@ def block_sub(v:User, sub):
return {"message": f"/h/{sub} blocked successfully!"} return {"message": f"/h/{sub} blocked successfully!"}
@app.post("/h/<sub>/unblock") @app.post("/h/<sub>/unblock")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def unblock_sub(v:User, sub): def unblock_sub(v:User, sub):
@ -129,6 +134,7 @@ def unblock_sub(v:User, sub):
return {"message": f"/h/{sub.name} unblocked successfully!"} return {"message": f"/h/{sub.name} unblocked successfully!"}
@app.post("/h/<sub>/subscribe") @app.post("/h/<sub>/subscribe")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def subscribe_sub(v:User, sub): def subscribe_sub(v:User, sub):
@ -141,6 +147,7 @@ def subscribe_sub(v:User, sub):
return {"message": f"/h/{sub} unblocked successfully!"} return {"message": f"/h/{sub} unblocked successfully!"}
@app.post("/h/<sub>/unsubscribe") @app.post("/h/<sub>/unsubscribe")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def unsubscribe_sub(v:User, sub): def unsubscribe_sub(v:User, sub):
@ -152,6 +159,7 @@ def unsubscribe_sub(v:User, sub):
return {"message": f"/h/{sub} blocked successfully!"} return {"message": f"/h/{sub} blocked successfully!"}
@app.post("/h/<sub>/follow") @app.post("/h/<sub>/follow")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def follow_sub(v:User, sub): def follow_sub(v:User, sub):
@ -167,6 +175,7 @@ def follow_sub(v:User, sub):
return {"message": f"/h/{sub} followed successfully!"} return {"message": f"/h/{sub} followed successfully!"}
@app.post("/h/<sub>/unfollow") @app.post("/h/<sub>/unfollow")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def unfollow_sub(v:User, sub): def unfollow_sub(v:User, sub):
@ -235,8 +244,9 @@ def sub_followers(v:User, sub):
@app.post("/h/<sub>/add_mod") @app.post("/h/<sub>/add_mod")
@limiter.limit("1/second;30/day") @limiter.limit('1/second', scope=path)
@limiter.limit("1/second;30/day", key_func=get_ID) @limiter.limit("30/day")
@limiter.limit("30/day", key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def add_mod(v:User, sub): def add_mod(v:User, sub):
if SITE_NAME == 'WPD': abort(403) if SITE_NAME == 'WPD': abort(403)
@ -273,6 +283,7 @@ def add_mod(v:User, sub):
return redirect(f'/h/{sub}/mods') return redirect(f'/h/{sub}/mods')
@app.post("/h/<sub>/remove_mod") @app.post("/h/<sub>/remove_mod")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def remove_mod(v:User, sub): def remove_mod(v:User, sub):
@ -322,6 +333,7 @@ def create_sub(v):
return render_template("sub/create_hole.html", v=v, cost=HOLE_COST, error=get_error()) return render_template("sub/create_hole.html", v=v, cost=HOLE_COST, error=get_error())
@app.post("/create_hole") @app.post("/create_hole")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def create_sub2(v): def create_sub2(v):
@ -356,6 +368,7 @@ def create_sub2(v):
return redirect(f'/h/{sub}') return redirect(f'/h/{sub}')
@app.post("/kick/<int:pid>") @app.post("/kick/<int:pid>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def kick(v:User, pid): def kick(v:User, pid):
@ -397,8 +410,9 @@ def sub_settings(v:User, sub):
@app.post('/h/<sub>/sidebar') @app.post('/h/<sub>/sidebar')
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def post_sub_sidebar(v:User, sub): def post_sub_sidebar(v:User, sub):
sub = get_sub_by_name(sub) sub = get_sub_by_name(sub)
@ -422,8 +436,9 @@ def post_sub_sidebar(v:User, sub):
@app.post('/h/<sub>/css') @app.post('/h/<sub>/css')
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def post_sub_css(v:User, sub): def post_sub_css(v:User, sub):
sub = get_sub_by_name(sub) sub = get_sub_by_name(sub)
@ -462,8 +477,9 @@ def get_sub_css(sub):
return resp return resp
@app.post("/h/<sub>/settings/banners/") @app.post("/h/<sub>/settings/banners/")
@limiter.limit("1/second;50/day") @limiter.limit('1/second', scope=path)
@limiter.limit("1/second;50/day", key_func=get_ID) @limiter.limit("50/day")
@limiter.limit("50/day", key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def upload_sub_banner(v:User, sub:str): def upload_sub_banner(v:User, sub:str):
if g.is_tor: abort(403, "Image uploads are not allowed through Tor") if g.is_tor: abort(403, "Image uploads are not allowed through Tor")
@ -549,8 +565,9 @@ def delete_all_sub_banners(v:User, sub:str):
return {"message": f"Deleted all banners from /h/{sub} successfully"} return {"message": f"Deleted all banners from /h/{sub} successfully"}
@app.post("/h/<sub>/sidebar_image") @app.post("/h/<sub>/sidebar_image")
@limiter.limit("1/second;10/day") @limiter.limit('1/second', scope=path)
@limiter.limit("1/second;10/day", key_func=get_ID) @limiter.limit("10/day")
@limiter.limit("10/day", key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def sub_sidebar(v:User, sub): def sub_sidebar(v:User, sub):
if g.is_tor: abort(403, "Image uploads are not allowed through TOR!") if g.is_tor: abort(403, "Image uploads are not allowed through TOR!")
@ -580,8 +597,9 @@ def sub_sidebar(v:User, sub):
return redirect(f'/h/{sub}/settings') return redirect(f'/h/{sub}/settings')
@app.post("/h/<sub>/marsey_image") @app.post("/h/<sub>/marsey_image")
@limiter.limit("1/second;10/day") @limiter.limit('1/second', scope=path)
@limiter.limit("1/second;10/day", key_func=get_ID) @limiter.limit("10/day")
@limiter.limit("10/day", key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def sub_marsey(v:User, sub): def sub_marsey(v:User, sub):
if g.is_tor: abort(403, "Image uploads are not allowed through TOR!") if g.is_tor: abort(403, "Image uploads are not allowed through TOR!")
@ -620,6 +638,7 @@ def subs(v:User):
return render_template('sub/subs.html', v=v, subs=subs, total_users=total_users) return render_template('sub/subs.html', v=v, subs=subs, total_users=total_users)
@app.post("/hole_pin/<int:pid>") @app.post("/hole_pin/<int:pid>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def hole_pin(v:User, pid): def hole_pin(v:User, pid):
@ -649,6 +668,7 @@ def hole_pin(v:User, pid):
return {"message": f"Post pinned to /h/{p.sub} successfully!"} return {"message": f"Post pinned to /h/{p.sub} successfully!"}
@app.post("/hole_unpin/<int:pid>") @app.post("/hole_unpin/<int:pid>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def hole_unpin(v:User, pid): def hole_unpin(v:User, pid):
@ -679,6 +699,7 @@ def hole_unpin(v:User, pid):
@app.post('/h/<sub>/stealth') @app.post('/h/<sub>/stealth')
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def sub_stealth(v:User, sub): def sub_stealth(v:User, sub):
@ -711,6 +732,7 @@ def sub_stealth(v:User, sub):
@app.post("/mod_pin/<int:cid>") @app.post("/mod_pin/<int:cid>")
@limiter.limit('1/second', scope=path)
@feature_required('PINS') @feature_required('PINS')
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@is_not_permabanned @is_not_permabanned
@ -740,6 +762,7 @@ def mod_pin(cid, v):
return {"message": "Comment pinned!"} return {"message": "Comment pinned!"}
@app.post("/unmod_pin/<int:cid>") @app.post("/unmod_pin/<int:cid>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def mod_unpin(cid, v): def mod_unpin(cid, v):

View File

@ -297,9 +297,10 @@ def downvoting(v:User, username:str):
return all_upvoters_downvoters(v, username, -1, True) return all_upvoters_downvoters(v, username, -1, True)
@app.post("/@<username>/suicide") @app.post("/@<username>/suicide")
@limiter.limit('1/second', scope=path)
@feature_required('USERS_SUICIDE') @feature_required('USERS_SUICIDE')
@limiter.limit("1/second;5/day") @limiter.limit("5/day")
@limiter.limit("1/second;5/day", key_func=get_ID) @limiter.limit("5/day", key_func=get_ID)
@auth_required @auth_required
def suicide(v:User, username:str): def suicide(v:User, username:str):
user = get_user(username) user = get_user(username)
@ -357,16 +358,18 @@ def transfer_currency(v:User, username:str, currency_name:Literal['coins', 'mars
return {"message": f"{amount - tax} {currency_name} have been transferred to @{receiver.username}"} return {"message": f"{amount - tax} {currency_name} have been transferred to @{receiver.username}"}
@app.post("/@<username>/transfer_coins") @app.post("/@<username>/transfer_coins")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def transfer_coins(v:User, username:str): def transfer_coins(v:User, username:str):
return transfer_currency(v, username, 'coins', True) return transfer_currency(v, username, 'coins', True)
@app.post("/@<username>/transfer_bux") @app.post("/@<username>/transfer_bux")
@limiter.limit('1/second', scope=path)
@feature_required('MARSEYBUX') @feature_required('MARSEYBUX')
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def transfer_bux(v:User, username:str): def transfer_bux(v:User, username:str):
return transfer_currency(v, username, 'marseybux', False) return transfer_currency(v, username, 'marseybux', False)
@ -452,8 +455,9 @@ def usersong(username:str):
else: abort(404) else: abort(404)
@app.post("/subscribe/<int:post_id>") @app.post("/subscribe/<int:post_id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def subscribe(v, post_id): def subscribe(v, post_id):
existing = g.db.query(Subscription).filter_by(user_id=v.id, submission_id=post_id).one_or_none() existing = g.db.query(Subscription).filter_by(user_id=v.id, submission_id=post_id).one_or_none()
@ -463,8 +467,9 @@ def subscribe(v, post_id):
return {"message": "Subscribed to post successfully!"} return {"message": "Subscribed to post successfully!"}
@app.post("/unsubscribe/<int:post_id>") @app.post("/unsubscribe/<int:post_id>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def unsubscribe(v, post_id): def unsubscribe(v, post_id):
existing = g.db.query(Subscription).filter_by(user_id=v.id, submission_id=post_id).one_or_none() existing = g.db.query(Subscription).filter_by(user_id=v.id, submission_id=post_id).one_or_none()
@ -473,8 +478,9 @@ def unsubscribe(v, post_id):
return {"message": "Unsubscribed from post successfully!"} return {"message": "Unsubscribed from post successfully!"}
@app.post("/@<username>/message") @app.post("/@<username>/message")
@limiter.limit("1/second;10/minute;20/hour;50/day") @limiter.limit('1/second', scope=path)
@limiter.limit("1/second;10/minute;20/hour;50/day", key_func=get_ID) @limiter.limit("10/minute;20/hour;50/day")
@limiter.limit("10/minute;20/hour;50/day", key_func=get_ID)
@is_not_permabanned @is_not_permabanned
def message2(v:User, username:str): def message2(v:User, username:str):
user = get_user(username, v=v, include_blocks=True, include_shadowbanned=False) user = get_user(username, v=v, include_blocks=True, include_shadowbanned=False)
@ -535,8 +541,9 @@ def message2(v:User, username:str):
@app.post("/reply") @app.post("/reply")
@limiter.limit("1/second;6/minute;50/hour;200/day") @limiter.limit('1/second', scope=path)
@limiter.limit("1/second;6/minute;50/hour;200/day", key_func=get_ID) @limiter.limit("6/minute;50/hour;200/day")
@limiter.limit("6/minute;50/hour;200/day", key_func=get_ID)
@auth_required @auth_required
def messagereply(v:User): def messagereply(v:User):
body = sanitize_raw_body(request.values.get("body"), False) body = sanitize_raw_body(request.values.get("body"), False)
@ -1045,8 +1052,9 @@ def u_user_id_info(id, v=None):
return user.json return user.json
@app.post("/follow/<username>") @app.post("/follow/<username>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def follow_user(username, v): def follow_user(username, v):
@ -1072,8 +1080,9 @@ def follow_user(username, v):
return {"message": f"@{target.username} has been followed!"} return {"message": f"@{target.username} has been followed!"}
@app.post("/unfollow/<username>") @app.post("/unfollow/<username>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def unfollow_user(username, v): def unfollow_user(username, v):
@ -1100,8 +1109,9 @@ def unfollow_user(username, v):
return {"message": f"@{target.username} has been unfollowed!"} return {"message": f"@{target.username} has been unfollowed!"}
@app.post("/remove_follow/<username>") @app.post("/remove_follow/<username>")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def remove_follow(username, v): def remove_follow(username, v):
target = get_user(username) target = get_user(username)
@ -1192,6 +1202,7 @@ def subscribed_posts(v:User, username):
return get_saves_and_subscribes(v, "userpage/submissions.html", Subscription, page, False) return get_saves_and_subscribes(v, "userpage/submissions.html", Subscription, page, False)
@app.post("/fp/<fp>") @app.post("/fp/<fp>")
@limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def fp(v:User, fp): def fp(v:User, fp):
@ -1348,6 +1359,7 @@ if KOFI_TOKEN:
return '' return ''
@app.post("/gumroad") @app.post("/gumroad")
@limiter.limit('1/second', scope=path)
def gumroad(): def gumroad():
data = request.values data = request.values
ip = request.headers.get('CF-Connecting-IP') ip = request.headers.get('CF-Connecting-IP')
@ -1379,8 +1391,9 @@ def gumroad():
@app.post("/settings/claim_rewards") @app.post("/settings/claim_rewards")
@limiter.limit(DEFAULT_RATELIMIT_SLOWER) @limiter.limit('1/second', scope=path)
@limiter.limit(DEFAULT_RATELIMIT_SLOWER, key_func=get_ID) @limiter.limit(DEFAULT_RATELIMIT)
@limiter.limit(DEFAULT_RATELIMIT, key_func=get_ID)
@auth_required @auth_required
def settings_claim_rewards(v:User): def settings_claim_rewards(v:User):
if not (v.email and v.is_activated): if not (v.email and v.is_activated):

View File

@ -194,16 +194,18 @@ def vote_post_comment(target_id, new, v, cls, vote_cls):
@app.post("/vote/post/<int:post_id>/<new>") @app.post("/vote/post/<int:post_id>/<new>")
@limiter.limit("5/second;60/minute;1000/hour;2000/day") @limiter.limit('1/second', scope=path)
@limiter.limit("5/second;60/minute;1000/hour;2000/day", key_func=get_ID) @limiter.limit("60/minute;1000/hour;2000/day")
@limiter.limit("60/minute;1000/hour;2000/day", key_func=get_ID)
@is_not_permabanned @is_not_permabanned
@limiter.limit("1/second", key_func=lambda:f'{g.v.id}-{request.full_path}') @limiter.limit("1/second", key_func=lambda:f'{g.v.id}-{request.full_path}')
def vote_post(post_id, new, v): def vote_post(post_id, new, v):
return vote_post_comment(post_id, new, v, Submission, Vote) return vote_post_comment(post_id, new, v, Submission, Vote)
@app.post("/vote/comment/<int:comment_id>/<new>") @app.post("/vote/comment/<int:comment_id>/<new>")
@limiter.limit("5/second;60/minute;1000/hour;2000/day") @limiter.limit('1/second', scope=path)
@limiter.limit("5/second;60/minute;1000/hour;2000/day", key_func=get_ID) @limiter.limit("60/minute;1000/hour;2000/day")
@limiter.limit("60/minute;1000/hour;2000/day", key_func=get_ID)
@is_not_permabanned @is_not_permabanned
@limiter.limit("1/second", key_func=lambda:f'{g.v.id}-{request.full_path}') @limiter.limit("1/second", key_func=lambda:f'{g.v.id}-{request.full_path}')
def vote_comment(comment_id, new, v): def vote_comment(comment_id, new, v):

View File

@ -10,6 +10,9 @@ from files.helpers.settings import get_setting
from files.routes.routehelpers import validate_formkey from files.routes.routehelpers import validate_formkey
from files.__main__ import app, db_session, limiter from files.__main__ import app, db_session, limiter
def path(n):
return request.path
def get_ID(): def get_ID():
if request.headers.get("Authorization"): if request.headers.get("Authorization"):
x = request.headers.get("Authorization") x = request.headers.get("Authorization")