From c56e45aa570a1054fe53c21c9264cbbd4824b77d Mon Sep 17 00:00:00 2001 From: justcool393 Date: Thu, 13 Oct 2022 00:27:56 -0700 Subject: [PATCH] create cloudflare helper --- files/helpers/cloudflare.py | 42 +++++++++++++++++++++++ files/helpers/media.py | 5 ++- files/routes/admin.py | 55 +++++++++++-------------------- files/routes/asset_submissions.py | 13 ++------ files/routes/comments.py | 3 +- 5 files changed, 68 insertions(+), 50 deletions(-) create mode 100644 files/helpers/cloudflare.py diff --git a/files/helpers/cloudflare.py b/files/helpers/cloudflare.py new file mode 100644 index 000000000..b1f05fd6e --- /dev/null +++ b/files/helpers/cloudflare.py @@ -0,0 +1,42 @@ +import json +from typing import List, Union, Optional +from files.helpers.const import * +import requests + +CLOUDFLARE_API_URL = "https://api.cloudflare.com/client/v4" +CLOUDFLARE_REQUEST_TIMEOUT_SECS = 5 +DEFAULT_CLOUDFLARE_ZONE = 'blahblahblah' + +def _request_from_cloudflare(url:str, method:str, post_data_str) -> bool: + if CF_ZONE == DEFAULT_CLOUDFLARE_ZONE: return False + try: + res = str(requests.request(method, f"{CLOUDFLARE_API_URL}/zones/{CF_ZONE}/{url}", headers=CF_HEADERS, data=post_data_str, timeout=CLOUDFLARE_REQUEST_TIMEOUT_SECS)) + except: + return False + return res == "" + +def get_security_level() -> Optional[str]: + res = None + try: + res = requests.get(f'{CLOUDFLARE_API_URL}/zones/{CF_ZONE}/settings/security_level', headers=CF_HEADERS, timeout=5).json()['result']['value'] + except: + pass + return res + +def set_security_level(under_attack="high") -> bool: + return _request_from_cloudflare("settings/security_level", "PATCH", f'{{"value":"{under_attack}"}}') + +def purge_entire_cache() -> bool: + return _request_from_cloudflare("purge_cache", "POST", '{"purge_everything":true}') + +def purge_files_in_cache(files:Union[List[str],str]) -> bool: + if CF_ZONE == DEFAULT_CLOUDFLARE_ZONE: return False + if isinstance(files, str): + files = [files] + post_data = {"files": files} + res = None + try: + res = requests.post(f'{CLOUDFLARE_API_URL}/zones/{CF_ZONE}/purge_cache', headers=CF_HEADERS, data=json.dumps(post_data), timeout=CLOUDFLARE_REQUEST_TIMEOUT_SECS) + except: + return False + return res == "" \ No newline at end of file diff --git a/files/helpers/media.py b/files/helpers/media.py index e6071a254..14182e0ed 100644 --- a/files/helpers/media.py +++ b/files/helpers/media.py @@ -11,6 +11,7 @@ import gevent import imagehash from shutil import copyfile from files.classes.media import * +from files.helpers.cloudflare import purge_files_in_cache from files.__main__ import db_session def process_files(): @@ -66,9 +67,7 @@ def webm_to_mp4(old, new, vid): subprocess.run(["ffmpeg", "-y", "-loglevel", "warning", "-nostats", "-threads:v", "1", "-i", old, "-map_metadata", "-1", tmp], check=True, stderr=subprocess.STDOUT) os.replace(tmp, new) os.remove(old) - requests.post(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/purge_cache', headers=CF_HEADERS, - data=f'{{"files": ["{SITE_FULL}{new}"]}}', timeout=5) - + purge_files_in_cache(f"{SITE_FULL}{new}") db = db_session() media = db.query(Media).filter_by(filename=new, kind='video').one_or_none() diff --git a/files/routes/admin.py b/files/routes/admin.py index f7671134b..7eea2f270 100644 --- a/files/routes/admin.py +++ b/files/routes/admin.py @@ -11,6 +11,7 @@ from files.helpers.get import * from files.helpers.media import * from files.helpers.const import * from files.helpers.actions import * +from files.helpers.cloudflare import * from files.classes import * from flask import * from files.__main__ import app, cache, limiter @@ -426,9 +427,7 @@ def admin_home(v): under_attack = False if v.admin_level >= PERMS['SITE_SETTINGS_UNDER_ATTACK']: - if CF_ZONE == 'blahblahblah': response = 'high' - else: response = requests.get(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/settings/security_level', headers=CF_HEADERS, timeout=5).json()['result']['value'] - under_attack = response == 'under_attack' + under_attack = (get_security_level() or 'high') == 'under_attack' gitref = admin_git_head() @@ -479,44 +478,33 @@ def purge_cache(v): online = cache.get(ONLINE_STR) cache.clear() cache.set(ONLINE_STR, online) - - response = str(requests.post(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/purge_cache', headers=CF_HEADERS, data='{"purge_everything":true}', timeout=5)) - + if not purge_entire_cache(): + abort(400, 'Failed to purge cache') ma = ModAction( kind="purge_cache", user_id=v.id ) g.db.add(ma) - - if response == "": return {"message": "Cache purged!"} - abort(400, 'Failed to purge cache.') + return {"message": "Cache purged!"} @app.post("/admin/under_attack") @admin_level_required(PERMS['SITE_SETTINGS_UNDER_ATTACK']) def under_attack(v): - response = requests.get(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/settings/security_level', headers=CF_HEADERS, timeout=5).json()['result']['value'] - - if response == 'under_attack': - ma = ModAction( - kind="disable_under_attack", - user_id=v.id, - ) - g.db.add(ma) - - response = str(requests.patch(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/settings/security_level', headers=CF_HEADERS, data='{"value":"high"}', timeout=5)) - if response == "": return {"message": "Under attack mode disabled!"} - abort(400, "Failed to disable under attack mode.") - else: - ma = ModAction( - kind="enable_under_attack", - user_id=v.id, - ) - g.db.add(ma) - - response = str(requests.patch(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/settings/security_level', headers=CF_HEADERS, data='{"value":"under_attack"}', timeout=5)) - if response == "": return {"message": "Under attack mode enabled!"} - abort(400, "Failed to enable under attack mode.") + response = get_security_level() + if not response: + abort(400, 'Could not retrieve the current security level') + old_under_attack_mode = response == 'under_attack' + enable_disable_str = 'disable' if old_under_attack_mode else 'enable' + new_security_level = 'high' if old_under_attack_mode else 'under_attack' + if not set_security_level(new_security_level): + abort(400, f'Failed to {enable_disable_str} under attack mode') + ma = ModAction( + kind=f"{enable_disable_str}_under_attack", + user_id=v.id, + ) + g.db.add(ma) + return {"message": f"Under attack mode {enable_disable_str}!"} @app.get("/admin/badge_grant") @admin_level_required(PERMS['USER_BADGES']) @@ -1142,10 +1130,7 @@ def remove_post(post_id, v): v.coins += 1 g.db.add(v) - - requests.post(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/purge_cache', headers=CF_HEADERS, - data=f'{{"files": ["https://{SITE}/logged_out"]}}', timeout=5) - + purge_files_in_cache(f"https://{SITE}/logged_out") return {"message": "Post removed!"} diff --git a/files/routes/asset_submissions.py b/files/routes/asset_submissions.py index f10b8e457..194a29ae2 100644 --- a/files/routes/asset_submissions.py +++ b/files/routes/asset_submissions.py @@ -132,9 +132,7 @@ if SITE not in ('pcmemes.net', 'watchpeopledie.co'): badge_grant(badge_id=16, user=author) else: badge_grant(badge_id=17, user=author) - - requests.post(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/purge_cache', headers=CF_HEADERS, - data=f'{{"files": ["https://{SITE}/e/{marsey.name}.webp"]}}', timeout=5) + purge_files_in_cache(f"https://{SITE}/e/{marsey.name}/webp") cache.delete_memoized(marsey_list) @@ -389,9 +387,7 @@ if SITE not in ('pcmemes.net', 'watchpeopledie.co'): filename = f"files/assets/images/emojis/{name}.webp" copyfile(new_path, filename) process_image(filename, resize=200, trim=True) - - requests.post(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/purge_cache', headers=CF_HEADERS, - data=f'{{"files": ["https://{SITE}/e/{name}.webp", "https://{SITE}/assets/images/emojis/{name}.webp", "https://{SITE}/asset_submissions/marseys/original/{name}.{format}"]}}', timeout=5) + purge_files_in_cache([f"https://{SITE}/e/{name}.webp", f"https://{SITE}/assets/images/emojis/{name}.webp", f"https://{SITE}/asset_submissions/marseys/original/{name}.{format}"]) ma = ModAction( kind="update_marsey", @@ -458,10 +454,7 @@ if SITE not in ('pcmemes.net', 'watchpeopledie.co'): filename = f"files/assets/images/hats/{name}.webp" copyfile(new_path, filename) process_image(filename) - - requests.post(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/purge_cache', headers=CF_HEADERS, - data=f'{{"files": ["https://{SITE}/i/hats/{name}.webp", "https://{SITE}/assets/images/hats/{name}.webp", "https://{SITE}/asset_submissions/hats/original/{name}.{format}"]}}', timeout=5) - + purge_files_in_cache([f"https://{SITE}/i/hats/{name}.webp", f"https://{SITE}/assets/images/hats/{name}.webp", f"https://{SITE}/asset_submissions/hats/original/{name}.{format}"]) ma = ModAction( kind="update_hat", user_id=v.id, diff --git a/files/routes/comments.py b/files/routes/comments.py index cf3aae1bb..314e077fe 100644 --- a/files/routes/comments.py +++ b/files/routes/comments.py @@ -215,8 +215,7 @@ def comment(v): filename = f'files/assets/images/badges/{badge.id}.webp' copyfile(oldname, filename) process_image(filename, resize=300) - requests.post(f'https://api.cloudflare.com/client/v4/zones/{CF_ZONE}/purge_cache', headers=CF_HEADERS, - data=f'{{"files": ["https://{SITE}/assets/images/badges/{badge.id}.webp"]}}', timeout=5) + purge_files_in_cache(f"https://{SITE}/assets/images/badges/{badge.id}.webp") except Exception as e: abort(400, str(e)) body += f"\n\n![]({image})"