aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--app/blueprints/github/__init__.py65
1 files changed, 61 insertions, 4 deletions
diff --git a/app/blueprints/github/__init__.py b/app/blueprints/github/__init__.py
index 8a04390..6bf63a7 100644
--- a/app/blueprints/github/__init__.py
+++ b/app/blueprints/github/__init__.py
@@ -18,19 +18,21 @@ from flask import Blueprint
bp = Blueprint("github", __name__)
-from flask import redirect, url_for, request, flash
+from flask import redirect, url_for, request, flash, abort
from flask_user import current_user
from sqlalchemy import func
from flask_github import GitHub
-from app import github
-from app.models import db, User
+from app import github, csrf
+from app.models import db, User, APIToken, Package
from app.utils import loginUser
+from app.blueprints.api.support import error, handleCreateRelease
+import hmac
@bp.route("/github/start/")
def start():
return github.authorize("")
-@bp.route("/user/github/callback/")
+@bp.route("/github/callback/")
@github.authorized_handler
def callback(oauth_token):
next_url = request.args.get("next")
@@ -72,3 +74,58 @@ def callback(oauth_token):
else:
flash("Authorization failed [err=gh-login-failed]", "danger")
return redirect(url_for("user.login"))
+
+
+@bp.route("/github/webhook/", methods=["POST"])
+@csrf.exempt
+def webhook():
+ json = request.json
+
+ # Get package
+ github_url = "github.com/" + json["repository"]["full_name"]
+ package = Package.query.filter(Package.repo.like("%{}%".format(github_url))).first()
+ if package is None:
+ return error(400, "Unknown package")
+
+ # Get all tokens for package
+ possible_tokens = APIToken.query.filter_by(package=package).all()
+ actual_token = None
+
+ #
+ # Check signature
+ #
+
+ header_signature = request.headers.get('X-Hub-Signature')
+ if header_signature is None:
+ return error(403, "Expected payload signature")
+
+ sha_name, signature = header_signature.split('=')
+ if sha_name != 'sha1':
+ return error(403, "Expected SHA1 payload signature")
+
+ for token in possible_tokens:
+ mac = hmac.new(token.access_token.encode("utf-8"), msg=request.data, digestmod='sha1')
+
+ if hmac.compare_digest(str(mac.hexdigest()), signature):
+ actual_token = token
+ break
+
+ if actual_token is None:
+ return error(403, "Invalid authentication")
+
+ #
+ # Check event
+ #
+
+ event = request.headers.get("X-GitHub-Event")
+ if event == "push":
+ title = json["head_commit"]["message"].partition("\n")[0]
+ ref = json["after"]
+ else:
+ return error(400, "Unknown event, expected 'push'")
+
+ #
+ # Perform release
+ #
+
+ return handleCreateRelease(actual_token, package, title, ref)