|
10 | 10 | CreateEndpointRequest, |
11 | 11 | CreateEndpointResponse, |
12 | 12 | ) |
13 | | -from cactus_client_notifications.server.endpoint_store import NotificationException |
| 13 | +from cactus_client_notifications.server.endpoint_store import ( |
| 14 | + NotificationException, |
| 15 | + generate_collected_notification, |
| 16 | +) |
14 | 17 | from cactus_client_notifications.server.settings import ServerSettings |
15 | 18 | from cactus_client_notifications.server.shared import ( |
16 | 19 | APPKEY_NOTIFICATION_STORE, |
@@ -86,6 +89,7 @@ async def post_manage_endpoint_list(request: web.Request) -> web.Response: |
86 | 89 | try: |
87 | 90 | endpoint_id = await request.app[APPKEY_NOTIFICATION_STORE].create_endpoint() |
88 | 91 | except NotificationException as exc: |
| 92 | + logger.error("Error creating endpoint", exc_info=exc) |
89 | 93 | return web.Response(status=exc.status_code, text=str(exc)) |
90 | 94 |
|
91 | 95 | create_response = CreateEndpointResponse( |
@@ -119,6 +123,7 @@ async def get_manage_endpoint(request: web.Request) -> web.Response: |
119 | 123 | try: |
120 | 124 | collected_notifications = await request.app[APPKEY_NOTIFICATION_STORE].collect_notifications(endpoint_id) |
121 | 125 | except NotificationException as exc: |
| 126 | + logger.error(f"Error updating config for {endpoint_id}", exc_info=exc) |
122 | 127 | return web.Response(status=exc.status_code, text=str(exc)) |
123 | 128 |
|
124 | 129 | collect_response = CollectEndpointResponse( |
@@ -159,6 +164,75 @@ async def put_manage_endpoint(request: web.Request) -> web.Response: |
159 | 164 | try: |
160 | 165 | await request.app[APPKEY_NOTIFICATION_STORE].update_endpoint(endpoint_id, enabled=configure_request.enabled) |
161 | 166 | except NotificationException as exc: |
| 167 | + logger.error(f"Error configuring {endpoint_id} with {configure_request}", exc_info=exc) |
| 168 | + return web.Response(status=exc.status_code, text=str(exc)) |
| 169 | + |
| 170 | + return web.Response(status=http.HTTPStatus.NO_CONTENT) |
| 171 | + |
| 172 | + |
| 173 | +async def delete_manage_endpoint(request: web.Request) -> web.Response: |
| 174 | + """Deletes an existing endpoint based on the endpoint_id in the path. All uncollected notifications will be lost. |
| 175 | +
|
| 176 | + Args: |
| 177 | + request: An aiohttp.web.Request instance. |
| 178 | +
|
| 179 | + Returns: |
| 180 | + aiohttp.web.Response: Encodes a CreateEndpointResponse on success |
| 181 | +
|
| 182 | + a 204 (NO_CONTENT) on success. |
| 183 | + a 404 (NOT_FOUND) if the endpoint has been deleted or the endpoint_id is invalid |
| 184 | + """ |
| 185 | + |
| 186 | + endpoint_id = request.match_info.get("endpoint_id") |
| 187 | + if not endpoint_id: |
| 188 | + return web.Response(status=http.HTTPStatus.BAD_REQUEST, text="endpoint_id couldn't be extracted from the path.") |
| 189 | + |
| 190 | + logger.info(f"Deleting endpoint {endpoint_id} for {request.remote}") |
| 191 | + |
| 192 | + try: |
| 193 | + await request.app[APPKEY_NOTIFICATION_STORE].try_delete_endpoint(endpoint_id) |
| 194 | + except NotificationException as exc: |
| 195 | + logger.error(f"Error deleting {endpoint_id}", exc_info=exc) |
162 | 196 | return web.Response(status=exc.status_code, text=str(exc)) |
163 | 197 |
|
164 | 198 | return web.Response(status=http.HTTPStatus.NO_CONTENT) |
| 199 | + |
| 200 | + |
| 201 | +async def webhook_endpoint(request: web.Request) -> web.Response: |
| 202 | + """This is the endpoint that will handle ALL incoming 2030.5 notifications from the utility server. It will try |
| 203 | + to report success for everything and log the contents of the incoming request. |
| 204 | +
|
| 205 | + Args: |
| 206 | + request: An aiohttp.web.Request instance. |
| 207 | +
|
| 208 | + Returns: |
| 209 | + aiohttp.web.Response: Encodes a CreateEndpointResponse on success |
| 210 | +
|
| 211 | + a 200 (OK) on success. |
| 212 | + a 404 (NOT_FOUND) if the endpoint has been deleted or the endpoint_id is invalid |
| 213 | + a 500 (INTERNAL_SERVER_ERROR) if the endpoint has been disabled |
| 214 | + a 507 (INSUFFICIENT_STORAGE) if the endpoint has too many uncollected notifications |
| 215 | + """ |
| 216 | + |
| 217 | + endpoint_id = request.match_info.get("endpoint_id") |
| 218 | + if not endpoint_id: |
| 219 | + return web.Response(status=http.HTTPStatus.NOT_FOUND) |
| 220 | + |
| 221 | + try: |
| 222 | + collected_notification = await generate_collected_notification(request) |
| 223 | + except Exception as exc: |
| 224 | + logger.error(f"Error parsing incoming webhook request for {endpoint_id} from {request.remote}", exc_info=exc) |
| 225 | + return web.Response(status=http.HTTPStatus.BAD_REQUEST) |
| 226 | + |
| 227 | + logger.info( |
| 228 | + f"{collected_notification.method} notification ({len(collected_notification.body)}) at {endpoint_id}" |
| 229 | + + f"from {request.remote}." |
| 230 | + ) |
| 231 | + |
| 232 | + try: |
| 233 | + await request.app[APPKEY_NOTIFICATION_STORE].add_notification(endpoint_id, collected_notification) |
| 234 | + except NotificationException as exc: |
| 235 | + logger.error(f"Error adding notification to {endpoint_id}", exc_info=exc) |
| 236 | + return web.Response(status=exc.status_code, text=str(exc)) |
| 237 | + |
| 238 | + return web.Response(status=http.HTTPStatus.OK) |
0 commit comments