mirror of
https://github.com/microsoft/onefuzz.git
synced 2025-06-18 04:38:09 +00:00
Replace notifications by default (#1084)
This commit is contained in:
@ -7,16 +7,29 @@ import logging
|
|||||||
|
|
||||||
import azure.functions as func
|
import azure.functions as func
|
||||||
from onefuzztypes.models import Error
|
from onefuzztypes.models import Error
|
||||||
from onefuzztypes.requests import NotificationCreate, NotificationGet
|
from onefuzztypes.requests import (
|
||||||
|
NotificationCreate,
|
||||||
|
NotificationGet,
|
||||||
|
NotificationSearch,
|
||||||
|
)
|
||||||
|
|
||||||
from ..onefuzzlib.endpoint_authorization import call_if_user
|
from ..onefuzzlib.endpoint_authorization import call_if_user
|
||||||
from ..onefuzzlib.events import get_events
|
from ..onefuzzlib.events import get_events
|
||||||
from ..onefuzzlib.notifications.main import Notification
|
from ..onefuzzlib.notifications.main import Notification
|
||||||
from ..onefuzzlib.request import not_ok, ok, parse_request
|
from ..onefuzzlib.request import not_ok, ok, parse_request, parse_uri
|
||||||
|
|
||||||
|
|
||||||
def get(req: func.HttpRequest) -> func.HttpResponse:
|
def get(req: func.HttpRequest) -> func.HttpResponse:
|
||||||
|
logging.info("notification search")
|
||||||
|
request = parse_uri(NotificationSearch, req)
|
||||||
|
if isinstance(request, Error):
|
||||||
|
return not_ok(request, context="notification search")
|
||||||
|
|
||||||
|
if request.container:
|
||||||
|
entries = Notification.search(query={"container": request.container})
|
||||||
|
else:
|
||||||
entries = Notification.search()
|
entries = Notification.search()
|
||||||
|
|
||||||
return ok(entries)
|
return ok(entries)
|
||||||
|
|
||||||
|
|
||||||
@ -26,7 +39,11 @@ def post(req: func.HttpRequest) -> func.HttpResponse:
|
|||||||
if isinstance(request, Error):
|
if isinstance(request, Error):
|
||||||
return not_ok(request, context="notification create")
|
return not_ok(request, context="notification create")
|
||||||
|
|
||||||
entry = Notification.create(container=request.container, config=request.config)
|
entry = Notification.create(
|
||||||
|
container=request.container,
|
||||||
|
config=request.config,
|
||||||
|
replace_existing=request.replace_existing,
|
||||||
|
)
|
||||||
if isinstance(entry, Error):
|
if isinstance(entry, Error):
|
||||||
return not_ok(entry, context="notification create")
|
return not_ok(entry, context="notification create")
|
||||||
|
|
||||||
|
@ -87,7 +87,9 @@ class JobTemplateIndex(BASE_INDEX, ORMMixin):
|
|||||||
for task_container in request.containers:
|
for task_container in request.containers:
|
||||||
if task_container.type == notification_config.container_type:
|
if task_container.type == notification_config.container_type:
|
||||||
notification = Notification.create(
|
notification = Notification.create(
|
||||||
task_container.name, notification_config.notification.config
|
task_container.name,
|
||||||
|
notification_config.notification.config,
|
||||||
|
True,
|
||||||
)
|
)
|
||||||
if isinstance(notification, Error):
|
if isinstance(notification, Error):
|
||||||
return notification
|
return notification
|
||||||
|
@ -57,30 +57,26 @@ class Notification(models.Notification, ORMMixin):
|
|||||||
notification = notifications[0]
|
notification = notifications[0]
|
||||||
return notification
|
return notification
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def get_existing(
|
|
||||||
cls, container: Container, config: NotificationTemplate
|
|
||||||
) -> Optional["Notification"]:
|
|
||||||
notifications = Notification.search(query={"container": [container]})
|
|
||||||
for notification in notifications:
|
|
||||||
if notification.config == config:
|
|
||||||
return notification
|
|
||||||
return None
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def key_fields(cls) -> Tuple[str, str]:
|
def key_fields(cls) -> Tuple[str, str]:
|
||||||
return ("notification_id", "container")
|
return ("notification_id", "container")
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def create(
|
def create(
|
||||||
cls, container: Container, config: NotificationTemplate
|
cls, container: Container, config: NotificationTemplate, replace_existing: bool
|
||||||
) -> Result["Notification"]:
|
) -> Result["Notification"]:
|
||||||
if not container_exists(container, StorageType.corpus):
|
if not container_exists(container, StorageType.corpus):
|
||||||
return Error(code=ErrorCode.INVALID_REQUEST, errors=["invalid container"])
|
return Error(code=ErrorCode.INVALID_REQUEST, errors=["invalid container"])
|
||||||
|
|
||||||
existing = cls.get_existing(container, config)
|
if replace_existing:
|
||||||
if existing is not None:
|
existing = cls.search(query={"container": [container]})
|
||||||
return existing
|
for entry in existing:
|
||||||
|
logging.info(
|
||||||
|
"replacing existing notification: %s",
|
||||||
|
entry.notification_id,
|
||||||
|
container,
|
||||||
|
)
|
||||||
|
entry.delete()
|
||||||
|
|
||||||
entry = cls(container=container, config=config)
|
entry = cls(container=container, config=config)
|
||||||
entry.save()
|
entry.save()
|
||||||
|
@ -692,11 +692,17 @@ class Notifications(Endpoint):
|
|||||||
endpoint = "notifications"
|
endpoint = "notifications"
|
||||||
|
|
||||||
def create(
|
def create(
|
||||||
self, container: primitives.Container, config: models.NotificationConfig
|
self,
|
||||||
|
container: primitives.Container,
|
||||||
|
config: models.NotificationConfig,
|
||||||
|
*,
|
||||||
|
replace_existing: bool = False,
|
||||||
) -> models.Notification:
|
) -> models.Notification:
|
||||||
"""Create a notification based on a config file"""
|
"""Create a notification based on a config file"""
|
||||||
|
|
||||||
config = requests.NotificationCreate(container=container, config=config.config)
|
config = requests.NotificationCreate(
|
||||||
|
container=container, config=config.config, replace_existing=replace_existing
|
||||||
|
)
|
||||||
return self._req_model("POST", models.Notification, data=config)
|
return self._req_model("POST", models.Notification, data=config)
|
||||||
|
|
||||||
def create_teams(
|
def create_teams(
|
||||||
@ -766,11 +772,17 @@ class Notifications(Endpoint):
|
|||||||
data=requests.NotificationGet(notification_id=notification_id_expanded),
|
data=requests.NotificationGet(notification_id=notification_id_expanded),
|
||||||
)
|
)
|
||||||
|
|
||||||
def list(self) -> List[models.Notification]:
|
def list(
|
||||||
|
self, *, container: Optional[List[primitives.Container]] = None
|
||||||
|
) -> List[models.Notification]:
|
||||||
"""List notification integrations"""
|
"""List notification integrations"""
|
||||||
|
|
||||||
self.logger.debug("listing notification integrations")
|
self.logger.debug("listing notification integrations")
|
||||||
return self._req_model_list("GET", models.Notification)
|
return self._req_model_list(
|
||||||
|
"GET",
|
||||||
|
models.Notification,
|
||||||
|
data=requests.NotificationSearch(container=container),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Tasks(Endpoint):
|
class Tasks(Endpoint):
|
||||||
|
@ -63,17 +63,16 @@ class Template(Command):
|
|||||||
self.onefuzz.tasks.delete(task.task_id)
|
self.onefuzz.tasks.delete(task.task_id)
|
||||||
|
|
||||||
if stop_notifications:
|
if stop_notifications:
|
||||||
notifications = self.onefuzz.notifications.list()
|
container_names = [x.name for x in task.config.containers]
|
||||||
for container in task.config.containers:
|
notifications = self.onefuzz.notifications.list(
|
||||||
|
container=container_names
|
||||||
|
)
|
||||||
for notification in notifications:
|
for notification in notifications:
|
||||||
if container.name == notification.container:
|
|
||||||
self.logger.info(
|
self.logger.info(
|
||||||
"removing notification: %s",
|
"removing notification: %s",
|
||||||
notification.notification_id,
|
notification.notification_id,
|
||||||
)
|
)
|
||||||
self.onefuzz.notifications.delete(
|
self.onefuzz.notifications.delete(notification.notification_id)
|
||||||
notification.notification_id
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
Template.stop.__doc__ = "stop a template job"
|
Template.stop.__doc__ = "stop a template job"
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
# Copyright (c) Microsoft Corporation.
|
# Copyright (c) Microsoft Corporation.
|
||||||
# Licensed under the MIT License.
|
# Licensed under the MIT License.
|
||||||
|
|
||||||
import json
|
|
||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
import zipfile
|
import zipfile
|
||||||
@ -119,19 +118,8 @@ class JobHelper:
|
|||||||
else:
|
else:
|
||||||
container = self.containers[ContainerType.reports]
|
container = self.containers[ContainerType.reports]
|
||||||
|
|
||||||
if not container:
|
|
||||||
return
|
|
||||||
|
|
||||||
config_dict = json.loads(config.json())
|
|
||||||
for entry in self.onefuzz.notifications.list():
|
|
||||||
if entry.container == container and entry.config == config_dict:
|
|
||||||
self.logger.debug(
|
|
||||||
"notification already exists: %s", entry.notification_id
|
|
||||||
)
|
|
||||||
return
|
|
||||||
|
|
||||||
self.logger.info("creating notification config for %s", container)
|
self.logger.info("creating notification config for %s", container)
|
||||||
self.onefuzz.notifications.create(container, config)
|
self.onefuzz.notifications.create(container, config, replace_existing=True)
|
||||||
|
|
||||||
def upload_setup(
|
def upload_setup(
|
||||||
self,
|
self,
|
||||||
|
@ -41,6 +41,11 @@ class JobSearch(BaseRequest):
|
|||||||
|
|
||||||
class NotificationCreate(BaseRequest, NotificationConfig):
|
class NotificationCreate(BaseRequest, NotificationConfig):
|
||||||
container: Container
|
container: Container
|
||||||
|
replace_existing: bool = Field(default=False)
|
||||||
|
|
||||||
|
|
||||||
|
class NotificationSearch(BaseRequest):
|
||||||
|
container: Optional[List[Container]]
|
||||||
|
|
||||||
|
|
||||||
class NotificationGet(BaseRequest):
|
class NotificationGet(BaseRequest):
|
||||||
|
Reference in New Issue
Block a user