Refactor webhooks to be more discrete

This commit is contained in:
Drew DeVault 2020-04-06 16:15:52 -04:00
parent 89a2e3ac9f
commit e0326ac0e2
5 changed files with 119 additions and 46 deletions

View file

@ -110,7 +110,7 @@ Mailing list for end-user discussion and questions related to the
event.user_id = project.owner_id
db.session.add(event)
lists.ensure_mailing_list_webhooks(owner, ml.name)
lists.ensure_mailing_list_webhooks(ml)
db.session.commit()

View file

@ -117,7 +117,7 @@ def git_new_POST(owner, project_name):
db.session.add(event)
git.ensure_user_webhooks(owner)
git.ensure_repo_webhooks(owner, repo.name)
git.ensure_repo_webhooks(repo)
db.session.commit()
@ -176,7 +176,7 @@ def hg_new_POST(owner, project_name):
db.session.add(event)
hg.ensure_user_webhooks(owner)
#hg.ensure_repo_webhooks(owner, repo.name) # TODO
#hg.ensure_repo_webhooks(repo) # TODO
db.session.commit()

View file

@ -92,7 +92,7 @@ def new_POST(owner, project_name):
db.session.add(event)
todo.ensure_user_webhooks(owner)
todo.ensure_tracker_webhooks(owner, tracker.name)
todo.ensure_tracker_webhooks(tracker)
db.session.commit()

View file

@ -1,42 +1,67 @@
import json
from flask import Blueprint, request
from hubsrht.types import MailingList, SourceRepo, RepoType
from hubsrht.types import Event, EventType, MailingList, SourceRepo, RepoType
from srht.database import db
from srht.flask import csrf_bypass
webhooks = Blueprint("webhooks", __name__)
@csrf_bypass
@webhooks.route("/webhooks/git-repo", methods=["POST"])
def git_repo():
@webhooks.route("/webhooks/git-user/<int:user_id>", methods=["POST"])
def git_user(user_id):
event = request.headers.get("X-Webhook-Event")
payload = json.loads(request.data.decode("utf-8"))
user = User.query.get(user_id)
if not user:
return "I don't recognize this user.", 404
if event == "repo:update":
repo = (SourceRepo.query
.filter(SourceRepo.remote_id == payload["id"])
.filter(SourceRepo.repo_type == RepoType.git)
.one_or_none())
.filter(SourceRepo.repo_type == RepoType.git)).one_or_none()
if not repo:
return "I don't recognize that repository.", 404
return "I don't recognize this git repo.", 404
repo.name = payload["name"]
repo.description = payload["description"]
db.session.commit()
return f"Updated local:{repo.id}/remote:{repo.remote_id}. Thanks!", 200
elif event == "repo:delete":
repo = (SourceRepo.query
.filter(SourceRepo.remote_id == payload["id"])
.filter(SourceRepo.repo_type == RepoType.git)).one_or_none()
if not repo:
return "I don't recognize this git repo.", 404
raise NotImplementedError()
elif event == "repo:post-update":
else:
raise NotImplementedError()
@csrf_bypass
@webhooks.route("/webhooks/hg-repo", methods=["POST"])
def hg_repo():
@webhooks.route("/webhooks/git-repo/<int:repo_id>", methods=["POST"])
def git_repo(repo_id):
event = request.headers.get("X-Webhook-Event")
payload = json.loads(request.data.decode("utf-8"))
repo = SourceRepo.query.get(repo_id)
if not repo:
return "I don't recognize that repository.", 404
if event == "repo:post-update":
raise NotImplementedError()
else:
raise NotImplementedError()
@csrf_bypass
@webhooks.route("/webhooks/hg-user/<int:user_id>", methods=["POST"])
def hg_user(user_id):
event = request.headers.get("X-Webhook-Event")
payload = json.loads(request.data.decode("utf-8"))
user = User.query.get(user_id)
if not user:
return "I don't recognize this user.", 404
if event == "repo:update":
repo = (SourceRepo.query
.filter(SourceRepo.remote_id == payload["id"])
.filter(SourceRepo.repo_type == RepoType.hg)
.one_or_none())
.filter(SourceRepo.id == repo_id)
.filter(SourceRepo.repo_type == RepoType.hg)).one_or_none()
if not repo:
return "I don't recognize that repository.", 404
repo.name = payload["name"]
@ -45,7 +70,7 @@ def hg_repo():
return f"Updated local:{repo.id}/remote:{repo.remote_id}. Thanks!", 200
elif event == "repo:delete":
raise NotImplementedError()
elif event == "repo:post-update":
else:
raise NotImplementedError()
@csrf_bypass
@ -69,25 +94,72 @@ def mailing_list():
raise NotImplementedError()
elif event == "patchset:received":
raise NotImplementedError()
else:
raise NotImplementedError()
@csrf_bypass
@webhooks.route("/webhooks/tracker", methods=["POST"])
def tracker():
@webhooks.route("/webhooks/todo-user/<int:user_id>", methods=["POST"])
def todo_user(user_id):
event = request.headers.get("X-Webhook-Event")
payload = json.loads(request.data.decode("utf-8"))
user = User.query.get(tracker_id)
if not user:
return "I don't recognize this tracker.", 404
if event == "tracker:update":
tracker = (Tracker.query
.filter(Tracker.remote_id == payload["id"])
.one_or_none())
.one_or_default())
if not tracker:
return "I don't recognize this tracker.", 404
tracker.name = payload["name"]
tracker.description = payload["description"]
db.session.commit()
return f"Updated local:{tracker.id}/remote:{tracker.remote_id}. Thanks!", 200
elif event == "tracker:delete":
tracker = (Tracker.query
.filter(Tracker.remote_id == payload["id"])
.one_or_default())
if not tracker:
return "I don't recognize this tracker.", 404
raise NotImplementedError()
else:
raise NotImplementedError()
@csrf_bypass
@webhooks.route("/webhooks/todo-tracker/<int:tracker_id>", methods=["POST"])
def todo_tracker(tracker_id):
event = request.headers.get("X-Webhook-Event")
payload = json.loads(request.data.decode("utf-8"))
tracker = Tracker.query.get(tracker_id)
if not tracker:
return "I don't recognize this tracker.", 404
if event == "tracker:update":
tracker.name = payload["name"]
tracker.description = payload["description"]
db.session.commit()
return f"Updated local:{tracker.id}/remote:{tracker.remote_id}. Thanks!", 200
elif event == "tracker:delete":
raise NotImplementedError()
elif event == "ticket:create":
raise NotImplementedError()
else:
raise NotImplementedError()
@csrf_bypass
@webhooks.route("/webhooks/todo-ticket/<int:tracker_id>/ticket", methods=["POST"])
def todo_ticket(tracker_id):
event = request.headers.get("X-Webhook-Event")
payload = json.loads(request.data.decode("utf-8"))
tracker = Tracker.query.get(tracker_id)
if not tracker:
return "I don't recognize this tracker.", 404
if event == "event:create":
raise NotImplementedError()
else:
raise NotImplementedError()

View file

@ -70,17 +70,19 @@ class GitService(SrhtService):
def ensure_user_webhooks(self, user):
config = {
origin + url_for("webhooks.git_repo"):
origin + url_for("webhooks.git_user", user_id=user.id):
["repo:update", "repo:delete"],
}
ensure_webhooks(user, f"{_gitsrht}/api/user/webhooks", config)
def ensure_repo_webhooks(self, user, repo_name):
def ensure_repo_webhooks(self, repo):
config = {
origin + url_for("webhooks.git_repo"): ["repo:post-update"],
origin + url_for("webhooks.git_repo", repo_id=repo.id):
["repo:post-update"],
}
url = f"{_gitsrht}/api/{user.canonical_name}/repos/{repo_name}/webhooks"
ensure_webhooks(user, url, config)
owner = repo.owner
url = f"{_gitsrht}/api/{owner.canonical_name}/repos/{repo.name}/webhooks"
ensure_webhooks(owner, url, config)
class HgService(SrhtService):
def __init__(self):
@ -125,18 +127,11 @@ class HgService(SrhtService):
def ensure_user_webhooks(self, user):
config = {
origin + url_for("webhooks.hg_repo"):
origin + url_for("webhooks.hg_repo", user_id=user.id):
["repo:update", "repo:delete"],
}
ensure_webhooks(user, f"{_hgsrht}/api/user/webhooks", config)
def ensure_repo_webhooks(self, user, repo_name):
config = {
origin + url_for("webhooks.hg_repo"): ["repo:post-update"],
}
url = f"{_hgsrht}/api/{user.canonical_name}/repos/{repo_name}/webhooks"
ensure_webhooks(user, url, config)
class ListService(SrhtService):
def get_lists(self, user):
return get_results(f"{_listsrht}/api/lists", user)
@ -148,13 +143,14 @@ class ListService(SrhtService):
raise Exception(r.json())
return r.json()
def ensure_mailing_list_webhooks(self, user, list_name):
def ensure_mailing_list_webhooks(self, mailing_list):
config = {
origin + url_for("webhooks.mailing_list"):
origin + url_for("webhooks.mailing_list", list_id=mailing_list.id):
["list:update", "list:delete", "post:received", "patchset:received"],
}
url = f"{_listsrht}/api/user/{user.canonical_name}/lists/{list_name}/webhooks"
ensure_webhooks(user, url, config)
owner = mailing_list.owner
url = f"{_listsrht}/api/user/{owner.canonical_name}/lists/{mailing_list.name}/webhooks"
ensure_webhooks(owner, url, config)
def create_list(self, user, valid):
name = valid.require("name")
@ -195,24 +191,29 @@ class TodoService(SrhtService):
def ensure_user_webhooks(self, user):
config = {
origin + url_for("webhooks.tracker"): ["tracker:update", "tracker:delete"]
origin + url_for("webhooks.todo_user", user_id=user.id):
["tracker:update", "tracker:delete"]
}
url = f"{_todosrht}/api/user/webhooks"
ensure_webhooks(user, url, config)
def ensure_tracker_webhooks(self, user, tracker_name):
def ensure_tracker_webhooks(self, tracker):
config = {
origin + url_for("webhooks.tracker"): ["ticket:create"]
origin + url_for("webhooks.todo_tracker", tracker_id=tracker.id):
["ticket:create"]
}
url = f"{_todosrht}/api/user/{user.canonical_name}/trackers/{tracker_name}/webhooks"
ensure_webhooks(user, url, config)
owner = tracker.owner
url = f"{_todosrht}/api/user/{owner.canonical_name}/trackers/{tracker.name}/webhooks"
ensure_webhooks(owner, url, config)
def ensure_ticket_webhooks(self, user, tracker_name, ticket_id):
def ensure_ticket_webhooks(self, tracker, ticket_id):
config = {
origin + url_for("webhooks.tracker_ticket"): ["event:create"]
origin + url_for("webhooks.todo_ticket", tracker_id=tracker.id):
["event:create"]
}
url = f"{_todosrht}/api/user/{user.canonical_name}/trackers/{tracker_name}/tickets/{ticket_id}/webhooks"
ensure_webhooks(user, url, config)
owner = tracker.owner
url = f"{_todosrht}/api/user/{owner.canonical_name}/trackers/{tracker.name}/tickets/{ticket_id}/webhooks"
ensure_webhooks(owner, url, config)
def create_tracker(self, user, valid):
name = valid.require("name")