Skip to content

Commit

Permalink
Add message endpoint
Browse files Browse the repository at this point in the history
Signed-off-by: Mehmet Baran Geylani <[email protected]>
  • Loading branch information
brngylni committed Jul 24, 2024
1 parent f1b44aa commit ea07749
Show file tree
Hide file tree
Showing 10 changed files with 1,452 additions and 111 deletions.
1 change: 1 addition & 0 deletions devel/ansible/roles/dev/files/config.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[flaskapp]
DEBUG = true
SECRET_KEY = "vagrant-env"
FASJSON_URL = "https://fasjson.tinystage.test/fasjson"
SQLALCHEMY_DATABASE_URI = "sqlite:////home/vagrant/w2fm.db"

[flaskapp.logsconf]
Expand Down
1,450 changes: 1,341 additions & 109 deletions poetry.lock

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,13 @@ classifiers = [
python = "^3.11"
sqlalchemy-helpers = ">=0.12.1"
flask = "^3.0.3"

gunicorn = {version = "^22.0.0", optional = true}

webhook-to-fedora-messaging-messages = "^1.0.0"
fasjson-client = "^1.0.8"


[tool.poetry.group.dev.dependencies]
pytest = ">=7.0.0"
pytest-cov = ">=4.0.0"
Expand Down
2 changes: 1 addition & 1 deletion webhook_to_fedora_messaging/config/defaults.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class Defaults:
PERMANENT_SESSION_LIFETIME = 604800
SESSION_COOKIE_NAME = "user"


FASJSON_URL = "https://fasjson.fedoraproject.org"
LOGGER_CONFIG = {
"version": 1,
"disable_existing_loggers": False,
Expand Down
40 changes: 40 additions & 0 deletions webhook_to_fedora_messaging/endpoints/message.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
from flask import Blueprint, abort
from ..database import db
from ..models.service import Service
from .parser.parser import msg_parser
from fedora_messaging import api
from webhook_to_fedora_messaging.exceptions import SignatureMatchError
from sqlalchemy import select
from sqlalchemy.exc import NoResultFound


message_endpoint = Blueprint("message_endpoint", __name__)


@message_endpoint.route("/message/<service_uuid>", methods=["POST"])
def create_msg(service_uuid):
"""
Used for creating a new message by sending a post request to /message path
Request Body:
service_uuid: Service related to message.
"""

try:
service = db.session.scalar(select(Service).where(Service.uuid == service_uuid)).one()
except NoResultFound:
return {'message': 'Service UUID Not Found'}, 404

try:
msg = msg_parser(service.type, service.token)
except SignatureMatchError as e:
return abort(400, {'message': str(e)})
except ValueError as e:
return abort(400, {'message': str(e)})

if msg is not None:
api.publish(msg)
return {'message': 'Success'}
else:
return abort(400, {'message': "Bad Request"})
Empty file.
39 changes: 39 additions & 0 deletions webhook_to_fedora_messaging/endpoints/parser/github.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from flask import request
import hashlib
import hmac
from webhook_to_fedora_messaging_messages.github.github import GithubMessageV1
from ..util import fas_by_github
from webhook_to_fedora_messaging.exceptions import SignatureMatchError

def github_parser(secret: str) -> GithubMessageV1:
"""Convert Flask request objects into desired FedMsg format.
Args:
secret: Specifies whether the webhook has secret key feature on or not
"""

headers = dict(request.headers)

if secret and not verify_signature(secret, headers['X-Hub-Signature-256']):
raise SignatureMatchError("Message Signature Couldn't be Matched.")

topic = f"github.{headers['X-Github-Event']}"
agent = fas_by_github(request.json['sender']['login']) # FASJSON
return GithubMessageV1(topic=topic, body={'body': request.json, 'headers': headers, 'agent': agent})


def verify_signature(secret_token: str, signature_header: str) -> bool:
"""Verify that the payload was sent from GitHub by validating SHA256.
Return false if not authorized.
Args:
secret_token: GitHub app webhook token (WEBHOOK_SECRET)
signature_header: header received from GitHub (x-hub-signature-256)
"""
if not signature_header:
return False
hash_object = hmac.new(secret_token.encode('utf-8'), msg=request.data, digestmod=hashlib.sha256)
expected_signature = "sha256=" + hash_object.hexdigest()

return hmac.compare_digest(expected_signature, signature_header)
7 changes: 7 additions & 0 deletions webhook_to_fedora_messaging/endpoints/parser/parser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from .github import github_parser

def msg_parser(service_type: str, secret: str):
if service_type.lower() == "github":
return github_parser(secret)
else:
raise ValueError(f"Unsupported Service: {service_type}")
15 changes: 14 additions & 1 deletion webhook_to_fedora_messaging/endpoints/util.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from flask import Response, request, abort
from functools import wraps

import fasjson_client

def validate_request(fields=None):
fields = fields or ['username']
Expand All @@ -27,3 +27,16 @@ def wrapper(*args, **kwargs):
return decorator(func)

return decorator


def fas_by_github(username: str) -> str:
"""Get the Fedora Account System Username of the given github username
Args:
username: Github Username"""

fasjson = fasjson_client.Client(FASJSON_URL)
response = fasjson.search(github_username=username)
if response.result and len(response.result) == 1:
return response.result[0]["username"]
return None
4 changes: 4 additions & 0 deletions webhook_to_fedora_messaging/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,7 @@ def __init__(self, text):

def __str__(self):
return self.text

class SignatureMatchError(Exception):
pass

0 comments on commit ea07749

Please sign in to comment.