]> git.lizzy.rs Git - cheatdb.git/commitdiff
Fix download forgery
authorrubenwardy <rw@rubenwardy.com>
Mon, 18 Nov 2019 21:42:56 +0000 (21:42 +0000)
committerrubenwardy <rw@rubenwardy.com>
Mon, 18 Nov 2019 21:42:56 +0000 (21:42 +0000)
app/__init__.py
app/blueprints/packages/releases.py
app/rediscache.py [new file with mode: 0644]
config.example.cfg
requirements.txt

index a0b4ba5c5574978769ca4006504c94080a431958..4c1512aae028f1061d095d6cca02b0678b658b2d 100644 (file)
@@ -25,13 +25,15 @@ from flask_github import GitHub
 from flask_wtf.csrf import CsrfProtect
 from flask_flatpages import FlatPages
 from flask_babel import Babel
-import os
+import os, redis
 
 app = Flask(__name__, static_folder="public/static")
 app.config["FLATPAGES_ROOT"] = "flatpages"
 app.config["FLATPAGES_EXTENSION"] = ".md"
 app.config.from_pyfile(os.environ["FLASK_CONFIG"])
 
+r = redis.Redis.from_url(app.config["REDIS_URL"])
+
 menu.Menu(app=app)
 markdown = Markdown(app, extensions=["fenced_code"], safe_mode=True, output_format="html5")
 github = GitHub(app)
index 89a9a0080dbf29336afb17a3238796274e596cf0..60a54bddf62299690ce7769717361bf1bb838538 100644 (file)
@@ -20,6 +20,7 @@ from flask_user import *
 
 from . import bp
 
+from app.rediscache import has_key, set_key, make_download_key
 from app.models import *
 from app.tasks.importtasks import makeVCSRelease
 from app.utils import *
@@ -123,20 +124,18 @@ def download_release(package, id):
        if release is None or release.package != package:
                abort(404)
 
-       if release is None:
-               if "application/zip" in request.accept_mimetypes and \
-                               not "text/html" in request.accept_mimetypes:
-                       return "", 204
-               else:
-                       flash("No download available.", "error")
-                       return redirect(package.getDetailsURL())
-       else:
-               PackageRelease.query.filter_by(id=release.id).update({
-                               "downloads": PackageRelease.downloads + 1
-                       })
-               db.session.commit()
+       ip = request.headers.get("X-Forwarded-For") or request.remote_addr
+       if ip is not None:
+               key = make_download_key(ip, release.package)
+               if not has_key(key):
+                       set_key(key, "true")
+
+                       PackageRelease.query.filter_by(id=release.id).update({
+                                       "downloads": PackageRelease.downloads + 1
+                               })
+                       db.session.commit()
 
-               return redirect(release.url, code=300)
+       return redirect(release.url, code=300)
 
 @bp.route("/packages/<author>/<name>/releases/<id>/", methods=["GET", "POST"])
 @login_required
diff --git a/app/rediscache.py b/app/rediscache.py
new file mode 100644 (file)
index 0000000..718a82e
--- /dev/null
@@ -0,0 +1,13 @@
+from . import r
+
+# This file acts as a facade between the releases code and redis,
+# and also means that the releases code avoids knowing about `app`
+
+def make_download_key(ip, package):
+       return ("{}/{}/{}").format(ip, package.author.username, package.name)
+
+def set_key(key, v):
+       r.set(key, v)
+
+def has_key(key):
+       return r.exists(key)
index 09aac7f5629ec3f4d743521903b9eb9206edc722..51e3f50584922c322f99852c8e1c3760d3768525 100644 (file)
@@ -10,8 +10,9 @@ SQLALCHEMY_DATABASE_URI = "sqlite:///../db.sqlite"
 GITHUB_CLIENT_ID = ""
 GITHUB_CLIENT_SECRET = ""
 
-CELERY_BROKER_URL='redis://localhost:6379'
-CELERY_RESULT_BACKEND='redis://localhost:6379'
+REDIS_URL='redis://redis:6379'
+CELERY_BROKER_URL='redis://redis:6379'
+CELERY_RESULT_BACKEND='redis://redis:6379'
 
 USER_ENABLE_REGISTER = False
 USER_ENABLE_CHANGE_USERNAME = False
index 4067ca084889fa702dddb42be5a15bdb73a48d31..fd73ebc1219a2bc29c35efce8593c0c18191f183 100644 (file)
@@ -16,7 +16,7 @@ celery==4.1.1
 kombu==4.2.0
 GitPython~=2.1
 lxml~=4.2
-pillow~=5.3
+pillow~=6.2
 pyScss~=1.3
 redis==2.10.6
 psycopg2~=2.7