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 authored and abompard committed Jul 24, 2024
1 parent f1b44aa commit c5d101f
Show file tree
Hide file tree
Showing 10 changed files with 1,449 additions and 110 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.

3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,11 @@ classifiers = [
python = "^3.11"
sqlalchemy-helpers = ">=0.12.1"
flask = "^3.0.3"
webhook-to-fedora-messaging-messages = "^1.0.0"
fasjson-client = "^1.0.8"
gunicorn = {version = "^22.0.0", optional = true}


[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
37 changes: 37 additions & 0 deletions webhook_to_fedora_messaging/endpoints/message.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
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("/<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.execute(select(Service).where(Service.uuid == service_uuid)).scalar_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)})

api.publish(msg)
return {'status': 'OK', 'message_id': msg.id}
Empty file.
53 changes: 53 additions & 0 deletions webhook_to_fedora_messaging/endpoints/parser/github.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from flask import request, current_app
import hashlib
import hmac
from webhook_to_fedora_messaging_messages.github.github import GithubMessageV1
from webhook_to_fedora_messaging.exceptions import SignatureMatchError
import fasjson_client


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)


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(current_app.config["FASJSON_URL"])
response = fasjson.search(github_username=username)
if response.result and len(response.result) == 1:
return response.result[0]["username"]
return None
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}")
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

2 changes: 2 additions & 0 deletions webhook_to_fedora_messaging/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from .config.defaults import LOGGER_CONFIG
from logging.config import dictConfig
from .endpoints.user import user_endpoint
from .endpoints.message import message_endpoint
from .endpoints.service import service_endpoint
from webhook_to_fedora_messaging.exceptions import ConfigError
import logging
Expand All @@ -32,6 +33,7 @@ def create_app():

app.register_blueprint(user_endpoint, url_prefix="/user")
app.register_blueprint(service_endpoint, url_prefix="/service")
app.register_blueprint(message_endpoint, url_prefix="/message")

# Then load the variables up from the custom configuration file
try:
Expand Down

0 comments on commit c5d101f

Please sign in to comment.