import hmac from hashlib import sha256 from flask import current_app, Response from flask.views import MethodView from freight import hooks from freight.models import App from freight.exceptions import InvalidHook class WebhooksView(MethodView): def respond(self, body="", status_code=200): rv = Response(body) rv.status_code = status_code return rv def get(self, *args, **kwargs): rv = Response() rv.status_code = 405 return rv def post(self, hook, action, app, env, digest): expected = hmac.new( current_app.config["API_KEY"].encode("utf8"), f"{hook}/{action}/{app}/{env}".encode("utf8"), sha256, ).hexdigest() if not hmac.compare_digest(expected, digest): return self.respond(status_code=403) try: hook = hooks.get(hook) except InvalidHook: return self.respond("Invalid hook", status_code=404) if action != "deploy": return self.respond("Unknown action", status_code=404) app = App.query.filter(App.name == app).first() if app is None: return self.respond("Invalid app", status_code=404) try: return hook.deploy(app, env) except NotImplementedError: return self.respond(status_code=404)