Add Github webhook support
This commit is contained in:
parent
beb9c0e959
commit
d4936e18ee
@ -18,19 +18,21 @@ from flask import Blueprint
|
|||||||
|
|
||||||
bp = Blueprint("github", __name__)
|
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 flask_user import current_user
|
||||||
from sqlalchemy import func
|
from sqlalchemy import func
|
||||||
from flask_github import GitHub
|
from flask_github import GitHub
|
||||||
from app import github
|
from app import github, csrf
|
||||||
from app.models import db, User
|
from app.models import db, User, APIToken, Package
|
||||||
from app.utils import loginUser
|
from app.utils import loginUser
|
||||||
|
from app.blueprints.api.support import error, handleCreateRelease
|
||||||
|
import hmac
|
||||||
|
|
||||||
@bp.route("/github/start/")
|
@bp.route("/github/start/")
|
||||||
def start():
|
def start():
|
||||||
return github.authorize("")
|
return github.authorize("")
|
||||||
|
|
||||||
@bp.route("/user/github/callback/")
|
@bp.route("/github/callback/")
|
||||||
@github.authorized_handler
|
@github.authorized_handler
|
||||||
def callback(oauth_token):
|
def callback(oauth_token):
|
||||||
next_url = request.args.get("next")
|
next_url = request.args.get("next")
|
||||||
@ -72,3 +74,58 @@ def callback(oauth_token):
|
|||||||
else:
|
else:
|
||||||
flash("Authorization failed [err=gh-login-failed]", "danger")
|
flash("Authorization failed [err=gh-login-failed]", "danger")
|
||||||
return redirect(url_for("user.login"))
|
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)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user