1
0
mirror of https://github.com/quay/quay.git synced 2026-01-26 06:21:37 +03:00
Files
quay/endpoints/api/repositorynotification.py
Brandon Caton cad8326d4a api: adding permissions for global readonly superuser (PROJQUAY-7177) (#2993)
The global readonly superuser is missing read only permissions on certain GET api's. This adds those permissions.
2024-07-09 13:17:26 -04:00

225 lines
7.5 KiB
Python

"""
List, create and manage repository events/notifications.
"""
import logging
from flask import request
from endpoints.api import (
InvalidRequest,
RepositoryParamResource,
disallow_for_app_repositories,
log_action,
nickname,
path_param,
request_error,
require_repo_admin,
resource,
validate_json_request,
)
from endpoints.api.repositorynotification_models_pre_oci import pre_oci_model as model
from endpoints.exception import NotFound
from notifications.models_interface import Repository
from notifications.notificationevent import NotificationEvent
from notifications.notificationmethod import (
CannotValidateNotificationMethodException,
NotificationMethod,
)
logger = logging.getLogger(__name__)
@resource("/v1/repository/<apirepopath:repository>/notification/")
@path_param("repository", "The full path of the repository. e.g. namespace/name")
class RepositoryNotificationList(RepositoryParamResource):
"""
Resource for dealing with listing and creating notifications on a repository.
"""
schemas = {
"NotificationCreateRequest": {
"type": "object",
"description": "Information for creating a notification on a repository",
"required": [
"event",
"method",
"config",
"eventConfig",
],
"properties": {
"event": {
"type": "string",
"description": "The event on which the notification will respond",
},
"method": {
"type": "string",
"description": "The method of notification (such as email or web callback)",
},
"config": {
"type": "object",
"description": "JSON config information for the specific method of notification",
},
"eventConfig": {
"type": "object",
"description": "JSON config information for the specific event of notification",
},
"title": {
"type": "string",
"description": "The human-readable title of the notification",
},
},
},
}
@require_repo_admin(allow_for_superuser=True)
@nickname("createRepoNotification")
@disallow_for_app_repositories
@validate_json_request("NotificationCreateRequest")
def post(self, namespace_name, repository_name):
parsed = request.get_json()
method_handler = NotificationMethod.get_method(parsed["method"])
try:
method_handler.validate(namespace_name, repository_name, parsed["config"])
except CannotValidateNotificationMethodException as ex:
raise request_error(message=str(ex))
new_notification = model.create_repo_notification(
namespace_name,
repository_name,
parsed["event"],
parsed["method"],
parsed["config"],
parsed["eventConfig"],
parsed.get("title"),
)
log_action(
"add_repo_notification",
namespace_name,
{
"repo": repository_name,
"namespace": namespace_name,
"notification_id": new_notification.uuid,
"event": new_notification.event_name,
"method": new_notification.method_name,
},
repo_name=repository_name,
)
return new_notification.to_dict(), 201
@require_repo_admin(allow_for_global_readonly_superuser=True, allow_for_superuser=True)
@nickname("listRepoNotifications")
@disallow_for_app_repositories
def get(self, namespace_name, repository_name):
"""
List the notifications for the specified repository.
"""
notifications = model.list_repo_notifications(namespace_name, repository_name)
return {"notifications": [n.to_dict() for n in notifications]}
@resource("/v1/repository/<apirepopath:repository>/notification/<uuid>")
@path_param("repository", "The full path of the repository. e.g. namespace/name")
@path_param("uuid", "The UUID of the notification")
class RepositoryNotification(RepositoryParamResource):
"""
Resource for dealing with specific notifications.
"""
@require_repo_admin(allow_for_global_readonly_superuser=True, allow_for_superuser=True)
@nickname("getRepoNotification")
@disallow_for_app_repositories
def get(self, namespace_name, repository_name, uuid):
"""
Get information for the specified notification.
"""
found = model.get_repo_notification(uuid)
if not found:
raise NotFound()
return found.to_dict()
@require_repo_admin(allow_for_superuser=True)
@nickname("deleteRepoNotification")
@disallow_for_app_repositories
def delete(self, namespace_name, repository_name, uuid):
"""
Deletes the specified notification.
"""
deleted = model.delete_repo_notification(namespace_name, repository_name, uuid)
if not deleted:
raise InvalidRequest(
"No repository notification found for: %s, %s, %s"
% (namespace_name, repository_name, uuid)
)
log_action(
"delete_repo_notification",
namespace_name,
{
"repo": repository_name,
"namespace": namespace_name,
"notification_id": uuid,
"event": deleted.event_name,
"method": deleted.method_name,
},
repo_name=repository_name,
)
return "No Content", 204
@require_repo_admin(allow_for_superuser=True)
@nickname("resetRepositoryNotificationFailures")
@disallow_for_app_repositories
def post(self, namespace_name, repository_name, uuid):
"""
Resets repository notification to 0 failures.
"""
reset = model.reset_notification_number_of_failures(namespace_name, repository_name, uuid)
if not reset:
raise InvalidRequest(
"No repository notification found for: %s, %s, %s"
% (namespace_name, repository_name, uuid)
)
log_action(
"reset_repo_notification",
namespace_name,
{
"repo": repository_name,
"namespace": namespace_name,
"notification_id": uuid,
"event": reset.event_name,
"method": reset.method_name,
},
repo_name=repository_name,
)
return "No Content", 204
@resource("/v1/repository/<apirepopath:repository>/notification/<uuid>/test")
@path_param("repository", "The full path of the repository. e.g. namespace/name")
@path_param("uuid", "The UUID of the notification")
class TestRepositoryNotification(RepositoryParamResource):
"""
Resource for queuing a test of a notification.
"""
@require_repo_admin(allow_for_superuser=True)
@nickname("testRepoNotification")
@disallow_for_app_repositories
def post(self, namespace_name, repository_name, uuid):
"""
Queues a test notification for this repository.
"""
test_note = model.queue_test_notification(uuid)
if not test_note:
raise InvalidRequest(
"No repository notification found for: %s, %s, %s"
% (namespace_name, repository_name, uuid)
)
return {}, 200