From 7a84d87507438a9fe8b9a5d47ed2749d71fa2c4c Mon Sep 17 00:00:00 2001 From: MarkLark86 Date: Thu, 29 Feb 2024 19:55:07 +1100 Subject: [PATCH 1/9] [SDESK-7163] fix: Purge assignment lock fails (#1924) Due to incomplete `system_update` signature in Assignments service (missing `kwargs`) --- server/planning/assignments/assignments.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/planning/assignments/assignments.py b/server/planning/assignments/assignments.py index dcc902f20..00b3a481c 100644 --- a/server/planning/assignments/assignments.py +++ b/server/planning/assignments/assignments.py @@ -278,8 +278,8 @@ def on_updated(self, updates, original): self.notify("assignments:updated", updates, original) self.send_assignment_notification(updates, original) - def system_update(self, id, updates, original): - super().system_update(id, updates, original) + def system_update(self, id, updates, original, **kwargs): + super().system_update(id, updates, original, **kwargs) if self.is_assignment_being_activated(updates, original): doc = deepcopy(original) doc.update(updates) From 875f1cb0c39b04fc164590c3289336780efdead9 Mon Sep 17 00:00:00 2001 From: MarkLark86 Date: Mon, 4 Mar 2024 09:51:43 +1100 Subject: [PATCH 2/9] [CPCN-651] improve: Publish Planning on Assignment re-assign (#1925) * [CPCN-651] improve: Publish Planning on Assignment re-assign * Update assignment actions, due to multiple planning publish per action --- .../assignments_planning_publish.feature | 96 +++++++++++-------- server/features/content_rewrite.feature | 85 ++++++++++++---- server/planning/assignments/assignments.py | 58 +++++++---- .../assignments/assignments_content.py | 1 - .../planning/assignments/assignments_link.py | 14 ++- .../assignments/assignments_unlink.py | 2 - 6 files changed, 170 insertions(+), 86 deletions(-) diff --git a/server/features/assignments_planning_publish.feature b/server/features/assignments_planning_publish.feature index 034dd0b67..bee86b6af 100644 --- a/server/features/assignments_planning_publish.feature +++ b/server/features/assignments_planning_publish.feature @@ -100,21 +100,8 @@ Feature: For posted planning item changes in assignment state post a planning it Then we get OK response Then we store coverage id in "firstcoverage" from coverage 0 - @auth @vocabularies + @auth @vocabularies @planning_cvs Scenario: Publish Planning item on changes to assignment state. - Given "vocabularies" - """ - [{ - "_id": "g2_content_type", - "display_name": "Coverage content types", - "type": "manageable", - "unique_field": "qcode", - "selection_type": "do not show", - "items": [ - {"is_active": true, "name": "Text", "qcode": "text", "content item type": "text"} - ] - }] - """ When we post to "/planning/post" """ { @@ -184,7 +171,9 @@ Feature: For posted planning item changes in assignment state post a planning it "qcode": "ncostat:int" }, "deliveries": [], - "coverage_provider": null + "coverage_provider": null, + "assigned_desk": "__no_value__", + "assigned_user": "__no_value__" } ] } @@ -243,7 +232,9 @@ Feature: For posted planning item changes in assignment state post a planning it "qcode": "ncostat:int" }, "deliveries": [], - "coverage_provider": null + "coverage_provider": null, + "assigned_desk": {"name": "Sports"}, + "assigned_user": {"display_name": "test_user"} } ] } @@ -308,7 +299,9 @@ Feature: For posted planning item changes in assignment state post a planning it "news_coverage_status": { "qcode": "ncostat:int" }, - "coverage_provider": null + "coverage_provider": null, + "assigned_desk": {"name": "Sports"}, + "assigned_user": {"display_name": "test_user"} } ] } @@ -377,8 +370,26 @@ Feature: For posted planning item changes in assignment state post a planning it "coverage_item": "#firstcoverage#" } """ + When we transmit items When we get "published_planning?sort=item_id,version" - Then we get list with 3 items + Then we get list with 4 items + Then we store "PLANNING" with 4 item + When we get "published_planning?where={\"item_id\": \"#PLANNING.item_id#\", \"version\": #PLANNING.version#}" + Then we get list with 1 items + Then we get transmitted item "/tmp/#PLANNING.item_id#-#PLANNING.version#-4.txt" + """ + { + "state": "scheduled", + "pubstatus": "usable", + "coverages": [{ + "coverage_id": "#firstcoverage#", + "workflow_status": "active", + "assigned_desk": {"name": "Politics"}, + "assigned_user": "__no_value__" + }] + } + """ + When we publish "#ARCHIVE_ID#" with "publish" type and "published" state Then we get OK response When we get "/archive/#ARCHIVE_ID#" @@ -394,11 +405,11 @@ Feature: For posted planning item changes in assignment state post a planning it """ When we transmit items When we get "published_planning?sort=item_id,version" - Then we get list with 4 items - Then we store "PLANNING" with 4 item + Then we get list with 5 items + Then we store "PLANNING" with 5 item When we get "published_planning?where={\"item_id\": \"#PLANNING.item_id#\", \"version\": #PLANNING.version#}" Then we get list with 1 items - Then we get transmitted item "/tmp/#PLANNING.item_id#-#PLANNING.version#-4.txt" + Then we get transmitted item "/tmp/#PLANNING.item_id#-#PLANNING.version#-5.txt" """ { "state": "scheduled", @@ -419,7 +430,9 @@ Feature: For posted planning item changes in assignment state post a planning it "qcode": "ncostat:int" }, "deliveries": [{"item_id": "#ARCHIVE_ID#"}], - "coverage_provider": null + "coverage_provider": null, + "assigned_desk": {"name": "Politics"}, + "assigned_user": "__no_value__" } ] } @@ -607,21 +620,8 @@ Feature: For posted planning item changes in assignment state post a planning it } """ - @auth @vocabularies + @auth @vocabularies @planning_cvs Scenario: Publish Planning item on linking and unlinking - Given "vocabularies" - """ - [{ - "_id": "g2_content_type", - "display_name": "Coverage content types", - "type": "manageable", - "unique_field": "qcode", - "selection_type": "do not show", - "items": [ - {"is_active": true, "name": "Text", "qcode": "text", "content item type": "text"} - ] - }] - """ When we post to "/planning/post" """ { @@ -691,7 +691,9 @@ Feature: For posted planning item changes in assignment state post a planning it "qcode": "ncostat:int" }, "deliveries": [], - "coverage_provider": null + "coverage_provider": null, + "assigned_desk": "__no_value__", + "assigned_user": "__no_value__" } ] } @@ -750,7 +752,9 @@ Feature: For posted planning item changes in assignment state post a planning it "qcode": "ncostat:int" }, "deliveries": [], - "coverage_provider": null + "coverage_provider": null, + "assigned_desk": {"name": "Sports"}, + "assigned_user": {"display_name": "test_user"} } ] } @@ -825,7 +829,9 @@ Feature: For posted planning item changes in assignment state post a planning it "qcode": "ncostat:int" }, "deliveries": [], - "coverage_provider": null + "coverage_provider": null, + "assigned_desk": {"name": "Sports"}, + "assigned_user": {"display_name": "test_user"} } ] } @@ -859,7 +865,9 @@ Feature: For posted planning item changes in assignment state post a planning it "qcode": "ncostat:int" }, "deliveries": [{"item_id": "123"}], - "coverage_provider": null + "coverage_provider": null, + "assigned_desk": {"name": "Sports"}, + "assigned_user": {"display_name": "test_user"} } ] } @@ -916,7 +924,9 @@ Feature: For posted planning item changes in assignment state post a planning it "qcode": "ncostat:int" }, "deliveries": [], - "coverage_provider": null + "coverage_provider": null, + "assigned_desk": {"name": "Sports"}, + "assigned_user": {"display_name": "test_user"} } ] } @@ -974,7 +984,9 @@ Feature: For posted planning item changes in assignment state post a planning it "qcode": "ncostat:int" }, "deliveries": [{"item_id": "123"}], - "coverage_provider": null + "coverage_provider": null, + "assigned_desk": {"name": "Sports"}, + "assigned_user": {"display_name": "test_user"} } ] } diff --git a/server/features/content_rewrite.feature b/server/features/content_rewrite.feature index 4b53d44a2..80ddb46cb 100644 --- a/server/features/content_rewrite.feature +++ b/server/features/content_rewrite.feature @@ -230,7 +230,9 @@ Feature: Rewrite content "scheduled": "2029-10-12T14:00:00+0000" }, "news_coverage_status": {"qcode": "ncostat:int"}, - "workflow_status": "assigned" + "workflow_status": "assigned", + "assigned_desk": {"name": "Sports"}, + "assigned_user": {"display_name": "test_user"} }] } """ @@ -276,7 +278,9 @@ Feature: Rewrite content }, "news_coverage_status": {"qcode": "ncostat:int"}, "workflow_status": "completed", - "deliveries": [{"item_state": "published", "item_id": "#archive._id#"}] + "deliveries": [{"item_state": "published", "item_id": "#archive._id#"}], + "assigned_desk": {"name": "Sports"}, + "assigned_user": {"display_name": "test_user"} }] } """ @@ -296,8 +300,35 @@ Feature: Rewrite content "assignment_id": "#firstassignment#" } """ + + When we transmit items When we get "published_planning?sort=item_id,version" Then we get list with 3 items + Then we store "PLANNING" with 3 item + Then we get transmitted item "/tmp/#PLANNING.item_id#-#PLANNING.version#-3.txt" + """ + { + "state": "scheduled", + "pubstatus": "usable", + "guid": "#PLANNING.item_id#", + "coverages": [{ + "planning": { + "g2_content_type": "text", + "ednote": "test coverage, I want 250 words", + "slugline": "test slugline", + "scheduled": "2029-10-12T14:00:00+0000" + }, + "news_coverage_status": {"qcode": "ncostat:int"}, + "workflow_status": "completed", + "deliveries": [ + {"item_state": "published", "item_id": "#archive._id#", "sequence_no": 0}, + {"item_state": "in_progress", "item_id": "#REWRITE_ID#", "sequence_no": 1} + ], + "assigned_desk": {"name": "Sports"}, + "assigned_user": {"display_name": "test_user"} + }] + } + """ When we get "/published" Then we get existing resource """ @@ -334,9 +365,11 @@ Feature: Rewrite content "news_coverage_status": {"qcode": "ncostat:int"}, "workflow_status": "completed", "deliveries": [ - {"item_state": "published", "item_id": "#archive._id#"}, - {"item_state": "published", "item_id": "#REWRITE_ID#"} - ] + {"item_state": "published", "item_id": "#archive._id#", "sequence_no": 0}, + {"item_state": "published", "item_id": "#REWRITE_ID#", "sequence_no": 1} + ], + "assigned_desk": {"name": "Sports"}, + "assigned_user": {"display_name": "test_user"} }] } """ @@ -647,7 +680,9 @@ Feature: Rewrite content "scheduled": "2029-10-12T14:00:00+0000" }, "news_coverage_status": {"qcode": "ncostat:int"}, - "workflow_status": "assigned" + "workflow_status": "assigned", + "assigned_desk": {"name": "Sports"}, + "assigned_user": {"display_name": "test_user"} }] } """ @@ -685,7 +720,9 @@ Feature: Rewrite content }, "news_coverage_status": {"qcode": "ncostat:int"}, "workflow_status": "completed", - "deliveries": [{"item_state": "published", "item_id": "#archive._id#"}] + "deliveries": [{"item_state": "published", "item_id": "#archive._id#"}], + "assigned_desk": {"name": "Sports"}, + "assigned_user": {"display_name": "test_user"} }] } """ @@ -722,9 +759,11 @@ Feature: Rewrite content "news_coverage_status": {"qcode": "ncostat:int"}, "workflow_status": "completed", "deliveries": [ - {"item_state": "published", "item_id": "#archive._id#"}, - {"item_state": "in_progress", "item_id": "#REWRITE_ID#"} - ] + {"item_state": "published", "item_id": "#archive._id#", "sequence_no": 0}, + {"item_state": "in_progress", "item_id": "#REWRITE_ID#", "sequence_no": 1} + ], + "assigned_desk": {"name": "Sports"}, + "assigned_user": {"display_name": "test_user"} }] } """ @@ -764,9 +803,11 @@ Feature: Rewrite content "news_coverage_status": {"qcode": "ncostat:int"}, "workflow_status": "completed", "deliveries": [ - {"item_state": "published", "item_id": "#archive._id#"}, - {"item_state": "published", "item_id": "#REWRITE_ID#"} - ] + {"item_state": "published", "item_id": "#archive._id#", "sequence_no": 0}, + {"item_state": "published", "item_id": "#REWRITE_ID#", "sequence_no": 1} + ], + "assigned_desk": {"name": "Sports"}, + "assigned_user": {"display_name": "test_user"} }] } """ @@ -805,10 +846,12 @@ Feature: Rewrite content "news_coverage_status": {"qcode": "ncostat:int"}, "workflow_status": "completed", "deliveries": [ - {"item_state": "published", "item_id": "#archive._id#"}, - {"item_state": "published", "item_id": "#rewrite1#"}, - {"item_state": "in_progress", "item_id": "#REWRITE_ID#"} - ] + {"item_state": "published", "item_id": "#archive._id#", "sequence_no": 0}, + {"item_state": "published", "item_id": "#rewrite1#", "sequence_no": 1}, + {"item_state": "in_progress", "item_id": "#REWRITE_ID#", "sequence_no": 2} + ], + "assigned_desk": {"name": "Sports"}, + "assigned_user": {"display_name": "test_user"} }] } """ @@ -851,9 +894,11 @@ Feature: Rewrite content "news_coverage_status": {"qcode": "ncostat:int"}, "workflow_status": "completed", "deliveries": [ - {"item_state": "published", "item_id": "#archive._id#"}, - {"item_state": "published", "item_id": "#rewrite1#"} - ] + {"item_state": "published", "item_id": "#archive._id#", "sequence_no": 0}, + {"item_state": "published", "item_id": "#rewrite1#", "sequence_no": 1} + ], + "assigned_desk": {"name": "Sports"}, + "assigned_user": {"display_name": "test_user"} }] } """ diff --git a/server/planning/assignments/assignments.py b/server/planning/assignments/assignments.py index 00b3a481c..42cb17ee7 100644 --- a/server/planning/assignments/assignments.py +++ b/server/planning/assignments/assignments.py @@ -10,6 +10,7 @@ """Superdesk Assignments""" +from typing import Dict, Any import superdesk import logging from copy import deepcopy @@ -278,6 +279,24 @@ def on_updated(self, updates, original): self.notify("assignments:updated", updates, original) self.send_assignment_notification(updates, original) + # If Desk, User and/or State was changed, then re-publish the Planning item + # So that the newly appointed assignee's/state will be pushed to subscribers + if self.assignee_details_changed(updates, original): + self.publish_planning(original.get("planning_item")) + + def assignee_details_changed(self, updates: Dict[str, Any], original: Dict[str, Any]) -> bool: + if "assigned_to" not in updates: + return False + + original_assigned_to = original.get("assigned_to") or {} + updated_assigned_to = updates["assigned_to"] or {} + + for field in ["user", "desk", "state"]: + if original_assigned_to.get(field) != updated_assigned_to.get(field): + return True + + return False + def system_update(self, id, updates, original, **kwargs): super().system_update(id, updates, original, **kwargs) if self.is_assignment_being_activated(updates, original): @@ -867,18 +886,6 @@ def update_assignment_on_archive_operation(self, updates, original, operation=No elif operation == ITEM_PUBLISH: updated_assignment = self._get_empty_updates_for_assignment(assignment) if updates.get(ITEM_STATE, original.get(ITEM_STATE, "")) != CONTENT_STATE.SCHEDULED: - if updated_assignment.get("assigned_to")["state"] != ASSIGNMENT_WORKFLOW_STATE.COMPLETED: - updated_assignment.get("assigned_to")["state"] = get_next_assignment_status( - updated_assignment, ASSIGNMENT_WORKFLOW_STATE.COMPLETED - ) - - # Remove lock information as the archive item is unlocked when publishing - remove_lock_information(updated_assignment) - - # Update the Assignment and send websocket notification - self._update_assignment_and_notify(updated_assignment, assignment) - get_resource_service("assignments_history").on_item_complete(updated_assignment, assignment) - # Update delivery record here delivery_service = get_resource_service("delivery") delivery = delivery_service.find_one(req=None, item_id=original[config.ID_FIELD]) @@ -892,8 +899,20 @@ def update_assignment_on_archive_operation(self, updates, original, operation=No }, ) - # publish planning - self.publish_planning(assignment.get("planning_item")) + if updated_assignment.get("assigned_to")["state"] != ASSIGNMENT_WORKFLOW_STATE.COMPLETED: + updated_assignment.get("assigned_to")["state"] = get_next_assignment_status( + updated_assignment, ASSIGNMENT_WORKFLOW_STATE.COMPLETED + ) + + # Remove lock information as the archive item is unlocked when publishing + remove_lock_information(updated_assignment) + + # Update the Assignment and send websocket notification + self._update_assignment_and_notify(updated_assignment, assignment) + get_resource_service("assignments_history").on_item_complete(updated_assignment, assignment) + else: + # publish planning + self.publish_planning(assignment.get("planning_item")) assigned_to_user = get_resource_service("users").find_one( req=None, _id=get_user().get(config.ID_FIELD, "") @@ -1039,9 +1058,14 @@ def unlink_assignment_on_delete_archive_rewrite(self): if not doc.get("assignment_id"): return - get_resource_service("assignments_unlink").post( - [{"assignment_id": doc["assignment_id"], "item_id": doc[config.ID_FIELD]}] - ) + assignment_id = doc["assignment_id"] + assignment = self.find_one(req=None, _id=assignment_id) + if not assignment: + logger.error(f"Failed to find assignment '{assignment_id}' for archive item '{item_id}'") + return + + get_resource_service("assignments_unlink").post([{"assignment_id": assignment_id, "item_id": item_id}]) + self.publish_planning(assignment["planning_item"]) def _update_assignment_and_notify(self, updates, original): self.system_update(original.get(config.ID_FIELD), updates, original) diff --git a/server/planning/assignments/assignments_content.py b/server/planning/assignments/assignments_content.py index 45a204425..f7a3e5d3b 100644 --- a/server/planning/assignments/assignments_content.py +++ b/server/planning/assignments/assignments_content.py @@ -201,7 +201,6 @@ def create(self, docs, **kwargs): if not assignment.get("scheduled_update_id"): # set the assignment to in progress assignments_service.patch(assignment[config.ID_FIELD], updates) - assignments_service.publish_planning(assignment["planning_item"]) doc.update(item) ids.append(doc["_id"]) diff --git a/server/planning/assignments/assignments_link.py b/server/planning/assignments/assignments_link.py index 29c9d071e..d93b4812d 100644 --- a/server/planning/assignments/assignments_link.py +++ b/server/planning/assignments/assignments_link.py @@ -104,7 +104,7 @@ def link_archive_items_to_assignments(self, assignment, related_items, actioned_ if len(deliveries) > 0: delivery_service.post(deliveries) - self.update_assignment( + assignment_was_updated = self.update_assignment( updates, assignment, actioned_item, @@ -124,9 +124,13 @@ def link_archive_items_to_assignments(self, assignment, related_items, actioned_ assignment_history_service.on_item_content_link(updates, assignment) if ( - actioned_item.get(ITEM_STATE) not in [CONTENT_STATE.PUBLISHED, CONTENT_STATE.CORRECTED] - or already_completed - ) and not need_complete: + not assignment_was_updated + and ( + actioned_item.get(ITEM_STATE) not in [CONTENT_STATE.PUBLISHED, CONTENT_STATE.CORRECTED] + or already_completed + ) + and not need_complete + ): # publishing planning item assignments_service.publish_planning(assignment["planning_item"]) @@ -245,6 +249,8 @@ def update_assignment( if updated: get_resource_service("assignments").patch(assignment[config.ID_FIELD], updates) + return updated + class AssignmentsLinkResource(Resource): endpoint_name = resource_title = "assignments_link" diff --git a/server/planning/assignments/assignments_unlink.py b/server/planning/assignments/assignments_unlink.py index d0c776215..268c886f0 100644 --- a/server/planning/assignments/assignments_unlink.py +++ b/server/planning/assignments/assignments_unlink.py @@ -112,8 +112,6 @@ def create(self, docs): push_content_notification(updated_items) # Update assignment history with all items affected updates["item_ids"] = ids - # publishing planning item - assignments_service.publish_planning(assignment["planning_item"]) return ids From 3f640b162b1298aaf0f8ba905838124542aea5e4 Mon Sep 17 00:00:00 2001 From: MarkLark86 Date: Thu, 7 Mar 2024 19:20:17 +1100 Subject: [PATCH 3/9] [SDESK-7163] improve: Use expiry datetime for purge_expired_locks command (#1929) --- server/planning/assignments/assignments.py | 10 +- .../planning/commands/purge_expired_locks.py | 63 +++--- .../commands/purge_expired_locks_test.py | 182 ++++++++++++++++++ server/planning/utils.py | 3 +- 4 files changed, 222 insertions(+), 36 deletions(-) create mode 100644 server/planning/commands/purge_expired_locks_test.py diff --git a/server/planning/assignments/assignments.py b/server/planning/assignments/assignments.py index 42cb17ee7..e57387c4d 100644 --- a/server/planning/assignments/assignments.py +++ b/server/planning/assignments/assignments.py @@ -298,7 +298,7 @@ def assignee_details_changed(self, updates: Dict[str, Any], original: Dict[str, return False def system_update(self, id, updates, original, **kwargs): - super().system_update(id, updates, original, **kwargs) + rtn = super().system_update(id, updates, original, **kwargs) if self.is_assignment_being_activated(updates, original): doc = deepcopy(original) doc.update(updates) @@ -310,6 +310,7 @@ def system_update(self, id, updates, original, **kwargs): and updates.get("assigned_to").get("state") != ASSIGNMENT_WORKFLOW_STATE.CANCELLED ): app.on_updated_assignments(updates, original) + return rtn def is_assignment_modified(self, updates, original): """Checks whether the assignment is modified or not""" @@ -1247,10 +1248,9 @@ def is_assignment_draft(self, updates, original): return updates.get("assigned_to", original.get("assigned_to")).get("state") == ASSIGNMENT_WORKFLOW_STATE.DRAFT def is_assignment_being_activated(self, updates, original): - return ( - original.get("assigned_to").get("state") == ASSIGNMENT_WORKFLOW_STATE.DRAFT - and updates.get("assigned_to", {}).get("state") == ASSIGNMENT_WORKFLOW_STATE.ASSIGNED - ) + return (original.get("assigned_to") or {}).get("state") == ASSIGNMENT_WORKFLOW_STATE.DRAFT and ( + updates.get("assigned_to") or {} + ).get("state") == ASSIGNMENT_WORKFLOW_STATE.ASSIGNED def is_text_assignment(self, assignment): # scheduled_update is always for text coverages diff --git a/server/planning/commands/purge_expired_locks.py b/server/planning/commands/purge_expired_locks.py index f9fa090ae..cdf7375bb 100644 --- a/server/planning/commands/purge_expired_locks.py +++ b/server/planning/commands/purge_expired_locks.py @@ -9,6 +9,7 @@ # at https://www.sourcefabric.org/superdesk/license import logging +from datetime import timedelta from flask import current_app as app from eve.utils import date_to_str @@ -18,6 +19,7 @@ from superdesk.lock import lock, unlock from superdesk.celery_task_utils import get_lock_id from planning.item_lock import LOCK_ACTION, LOCK_SESSION, LOCK_TIME, LOCK_USER +from planning.utils import try_cast_object_id logger = logging.getLogger(__name__) @@ -26,7 +28,8 @@ class PurgeExpiredLocks(Command): """ Purge item locks that are linked to a non-existing session - resource: The name of the resource to purge item locks for + --resource, -r: The name of the resource to purge item locks for + --expire-hours, -e: Purges locks that are older than this many hours Example: :: @@ -34,28 +37,42 @@ class PurgeExpiredLocks(Command): $ python manage.py planning:purge_expired_locks -r events $ python manage.py planning:purge_expired_locks -r planning $ python manage.py planning:purge_expired_locks -r assignments + $ python manage.py planning:purge_expired_locks -r all + $ python manage.py planning:purge_expired_locks -r all -e 48 """ - option_list = [Option("--resource", "-r", required=True)] + option_list = [ + Option("--resource", "-r", required=True), + Option("--expire-hours", "-e", dest="expire_hours", required=False, type=int, default=24), + ] - def run(self, resource: str): + def run(self, resource: str, expire_hours: int = 24) -> None: logger.info("Starting to purge expired item locks") + if resource == "all": + resources = ["events", "planning", "assignments"] + elif resource not in ["events", "planning", "assignments"]: + raise ValueError(f"Invalid resource: {resource}") + else: + resources = [resource] + lock_name = get_lock_id("purge_expired_locks", resource) if not lock(lock_name, expire=600): logger.info("purge expired locks task is already running") return - try: - self._purge_item_locks(resource) - except Exception as err: - logger.exception(f"Failed to purge item locks ({err})") - finally: - unlock(lock_name) + expiry_datetime = date_to_str(utcnow() - timedelta(hours=expire_hours)) + for resource_name in resources: + try: + self._purge_item_locks(resource_name, expiry_datetime) + except Exception as err: + logger.exception(f"Failed to purge item locks ({err})") + unlock(lock_name) logger.info("Completed purging expired item locks") - def _purge_item_locks(self, resource: str): + def _purge_item_locks(self, resource: str, expiry_datetime: str): + logger.info(f"Purging expired locks for {resource}") resource_service = get_resource_service(resource) try: autosave_service = get_resource_service( @@ -64,11 +81,11 @@ def _purge_item_locks(self, resource: str): except KeyError: autosave_service = None - for items in self.get_locked_items(resource): + for items in self.get_locked_items(resource, expiry_datetime): failed_ids = [] for item in items: try: - item_id = item["_id"] + item_id = try_cast_object_id(item["_id"]) except KeyError: logger.exception("Item ID not found, unable to purge its lock") continue @@ -103,29 +120,15 @@ def _purge_item_locks(self, resource: str): num_items = len(items) num_success = num_items - len(failed_ids) if num_success != num_items: - logger.warning(f"{num_success}/{num_items} item locks purged. Failed IDs: {failed_ids}") + logger.warning(f"{num_success}/{num_items} {resource} locks purged. Failed IDs: {failed_ids}") else: - logger.info(f"{num_items} item locks purged") + logger.info(f"{num_items} {resource} locks purged") - def get_locked_items(self, resource: str): - now = utcnow() - active_sessions = [str(session["_id"]) for session in get_resource_service("auth").get(req=None, lookup={})] + def get_locked_items(self, resource: str, expiry_datetime: str): service = get_resource_service(resource) total_received = 0 query = { - "query": { - "bool": { - "filter": [ - {"exists": {"field": LOCK_SESSION}}, - # Use a range filter for lock time, so if this task takes a while - # it will exclude any newer item locks and/or sessions - {"range": {LOCK_TIME: {"lt": date_to_str(now)}}}, - ], - "must_not": [ - {"terms": {LOCK_SESSION: active_sessions}}, - ], - }, - }, + "query": {"bool": {"filter": [{"range": {LOCK_TIME: {"lt": expiry_datetime}}}]}}, "size": app.config["MAX_EXPIRY_QUERY_LIMIT"], "sort": [{LOCK_TIME: "asc"}], } diff --git a/server/planning/commands/purge_expired_locks_test.py b/server/planning/commands/purge_expired_locks_test.py new file mode 100644 index 000000000..a601c6bce --- /dev/null +++ b/server/planning/commands/purge_expired_locks_test.py @@ -0,0 +1,182 @@ +# -*- coding: utf-8; -*- +# +# This file is part of Superdesk. +# +# Copyright 2024 Sourcefabric z.u. and contributors. +# +# For the full copyright and license information, please see the +# AUTHORS and LICENSE files distributed with this source code, or +# at https://www.sourcefabric.org/superdesk/license + +from typing import List, Tuple, Union +from datetime import timedelta +from bson import ObjectId + +from superdesk.utc import utcnow +from planning.tests import TestCase + +from .purge_expired_locks import PurgeExpiredLocks + +now = utcnow() +assignment_1_id = ObjectId() +assignment_2_id = ObjectId() + + +# TODO: Add Assignments +class PurgeExpiredLocksTest(TestCase): + def setUp(self) -> None: + super().setUp() + self.app.data.insert( + "events", + [ + { + "_id": "active_event_1", + "dates": {"start": now, "end": now + timedelta(days=1)}, + "lock_user": "user1", + "lock_session": "session1", + "lock_time": now - timedelta(hours=23), + "lock_action": "edit", + }, + { + "_id": "expired_event_1", + "dates": {"start": now, "end": now + timedelta(days=1)}, + "lock_user": "user2", + "lock_session": "session2", + "lock_time": now - timedelta(hours=25), + "lock_action": "edit", + }, + ], + ) + self.app.data.insert( + "planning", + [ + { + "_id": "active_plan_1", + "planning_date": now, + "lock_user": "user3", + "lock_session": "session3", + "lock_time": now - timedelta(hours=23), + "lock_action": "edit", + }, + { + "_id": "expired_plan_1", + "planning_date": now, + "lock_user": "user4", + "lock_session": "session4", + "lock_time": now - timedelta(hours=25), + "lock_action": "edit", + }, + ], + ) + self.app.data.insert( + "assignments", + [ + { + "_id": assignment_1_id, + "lock_user": "user5", + "lock_session": "session5", + "lock_time": now - timedelta(hours=23), + "lock_action": "edit", + }, + { + "_id": assignment_2_id, + "lock_user": "user6", + "lock_session": "session6", + "lock_time": now - timedelta(hours=25), + "lock_action": "edit", + }, + ], + ) + self.assertLockState( + [ + ("events", "active_event_1", True), + ("events", "expired_event_1", True), + ("planning", "active_plan_1", True), + ("planning", "expired_plan_1", True), + ("assignments", assignment_1_id, True), + ("assignments", assignment_2_id, True), + ] + ) + + def test_invalid_resource(self): + with self.assertRaises(ValueError): + PurgeExpiredLocks().run("blah") + + def assertLockState(self, item_tests: List[Tuple[str, Union[str, ObjectId], bool]]): + for resource, item_id, is_locked in item_tests: + item = self.app.data.find_one(resource, req=None, _id=item_id) + if is_locked: + self.assertIsNotNone(item["lock_user"], f"{resource} item {item_id} is NOT locked, item={item}") + self.assertIsNotNone(item["lock_session"], f"{resource} item {item_id} is NOT locked, item={item}") + self.assertIsNotNone(item["lock_time"], f"{resource} item {item_id} is NOT locked, item={item}") + self.assertIsNotNone(item["lock_action"], f"{resource} item {item_id} is NOT locked, item={item}") + else: + self.assertIsNone(item.get("lock_user"), f"{resource} item {item_id} is locked, item={item}") + self.assertIsNone(item.get("lock_session"), f"{resource} item {item_id} is locked, item={item}") + self.assertIsNone(item.get("lock_time"), f"{resource} item {item_id} is locked, item={item}") + self.assertIsNone(item.get("lock_action"), f"{resource} item {item_id} is locked, item={item}") + + def test_purge_event_locks(self): + PurgeExpiredLocks().run("events") + self.assertLockState( + [ + ("events", "active_event_1", True), + ("events", "expired_event_1", False), + ("planning", "active_plan_1", True), + ("planning", "expired_plan_1", True), + ("assignments", assignment_1_id, True), + ("assignments", assignment_2_id, True), + ] + ) + + def test_purge_planning_locks(self): + PurgeExpiredLocks().run("planning") + self.assertLockState( + [ + ("events", "active_event_1", True), + ("events", "expired_event_1", True), + ("planning", "active_plan_1", True), + ("planning", "expired_plan_1", False), + ("assignments", assignment_1_id, True), + ("assignments", assignment_2_id, True), + ] + ) + + def test_purge_assignment_locks(self): + PurgeExpiredLocks().run("assignments") + self.assertLockState( + [ + ("events", "active_event_1", True), + ("events", "expired_event_1", True), + ("planning", "active_plan_1", True), + ("planning", "expired_plan_1", True), + ("assignments", assignment_1_id, True), + ("assignments", assignment_2_id, False), + ] + ) + + def test_purge_all_locks(self): + PurgeExpiredLocks().run("all") + self.assertLockState( + [ + ("events", "active_event_1", True), + ("events", "expired_event_1", False), + ("planning", "active_plan_1", True), + ("planning", "expired_plan_1", False), + ("assignments", assignment_1_id, True), + ("assignments", assignment_2_id, False), + ] + ) + + def test_purge_all_locks_with_custom_expiry(self): + PurgeExpiredLocks().run("all", 2) + self.assertLockState( + [ + ("events", "active_event_1", False), + ("events", "expired_event_1", False), + ("planning", "active_plan_1", False), + ("planning", "expired_plan_1", False), + ("assignments", assignment_1_id, False), + ("assignments", assignment_2_id, False), + ] + ) diff --git a/server/planning/utils.py b/server/planning/utils.py index 3597ab0a0..d5f4e92ce 100644 --- a/server/planning/utils.py +++ b/server/planning/utils.py @@ -1,8 +1,9 @@ +from typing import Union from bson.objectid import ObjectId from bson.errors import InvalidId -def try_cast_object_id(value): +def try_cast_object_id(value: str) -> Union[ObjectId, str]: try: return ObjectId(value) except InvalidId: From 0f6cda11ca75392d6eac2d64fcf53a5ed47d3261 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Ja=C5=A1ek?= Date: Mon, 25 Mar 2024 09:54:54 +0100 Subject: [PATCH 4/9] set recurrence_id based on event _id (#1936) * set event recurrence_id to match first event id so we can detect in NH which event is the first one in the series CPCN-695 --- e2e/package.json | 2 +- package-lock.json | 1106 ++++++++++++++++------ package.json | 2 +- server/features/events_recurring.feature | 29 +- server/planning/events/events.py | 13 +- 5 files changed, 826 insertions(+), 326 deletions(-) diff --git a/e2e/package.json b/e2e/package.json index eedf2e192..ff29099b7 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -2,7 +2,7 @@ "name": "superdesk", "license": "GPL-3.0", "dependencies": { - "superdesk-core": "github:superdesk/superdesk-client-core#v2.6.2", + "superdesk-core": "github:superdesk/superdesk-client-core#hotfix/2.6.3", "superdesk-planning": "file:../" }, "devDependencies": { diff --git a/package-lock.json b/package-lock.json index 106d2f9c5..56c065f3f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -31,9 +31,9 @@ } }, "@babel/parser": { - "version": "7.21.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.21.4.tgz", - "integrity": "sha512-alVJj7k7zIxqBZ7BTRhz0IqJFxW1VJbm6N8JbcYhQ186df9ZBPbZBmWSqAMXwHGsCJdYks7z/voa3ibiS5bCIw==", + "version": "7.24.1", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.1.tgz", + "integrity": "sha512-Zo9c7N3xdOIQrNip7Lc9wvRPzlRtovHVE4lkz8WEDr7uYh/GMQhSiIgFxGIArRHYdJE5kxtZjAf8rT0xhdLCzg==", "dev": true }, "@babel/runtime": { @@ -1348,11 +1348,6 @@ } } }, - "angular-history": { - "version": "github:decipherinc/angular-history#ee798413fba074e3d8f2d35fc951a83cb73e923e", - "from": "github:decipherinc/angular-history#v0.8.0", - "dev": true - }, "angular-i18n": { "version": "1.6.9", "resolved": "https://registry.npmjs.org/angular-i18n/-/angular-i18n-1.6.9.tgz", @@ -1503,6 +1498,50 @@ "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", "integrity": "sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==" }, + "array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, + "requires": { + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "dependencies": { + "call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + } + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + }, + "get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + } + } + } + }, "array-differ": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz", @@ -1637,15 +1676,14 @@ } }, "asn1.js": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", - "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz", + "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==", "dev": true, "requires": { "bn.js": "^4.0.0", "inherits": "^2.0.1", - "minimalistic-assert": "^1.0.0", - "safer-buffer": "^2.1.0" + "minimalistic-assert": "^1.0.0" }, "dependencies": { "bn.js": { @@ -1657,28 +1695,28 @@ } }, "assert": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz", - "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==", + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.1.tgz", + "integrity": "sha512-zzw1uCAgLbsKwBfFc8CX78DDg+xZeBksSO3vwVIDDN5i94eOrPsSSyiVhmsSABFDM/OcpE2aagCat9dnWQLG1A==", "dev": true, "requires": { - "object-assign": "^4.1.1", - "util": "0.10.3" + "object.assign": "^4.1.4", + "util": "^0.10.4" }, "dependencies": { "inherits": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz", - "integrity": "sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==", "dev": true }, "util": { - "version": "0.10.3", - "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz", - "integrity": "sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ==", + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", "dev": true, "requires": { - "inherits": "2.0.1" + "inherits": "2.0.3" } } } @@ -1772,10 +1810,13 @@ } }, "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", - "dev": true + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "requires": { + "possible-typed-array-names": "^1.0.0" + } }, "aws-sign2": { "version": "0.7.0", @@ -2144,18 +2185,73 @@ "multicast-dns-service-types": "^1.1.0" }, "dependencies": { + "call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + } + }, "deep-equal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz", + "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==", "dev": true, "requires": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", + "is-arguments": "^1.1.1", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "object-is": "^1.1.5", "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" + "regexp.prototype.flags": "^1.5.1" + } + }, + "define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "requires": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + }, + "get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + } + }, + "regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "requires": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" } } } @@ -2273,31 +2369,54 @@ } }, "browserify-sign": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.1.tgz", - "integrity": "sha512-/vrA5fguVAKKAVTNJjgSm1tRQDHUU6DbwO9IROu/0WAzC8PKhucDSh18J0RMvVeHAn5puMd+QHC2erPRNf8lmg==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.3.tgz", + "integrity": "sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==", "dev": true, "requires": { - "bn.js": "^5.1.1", - "browserify-rsa": "^4.0.1", + "bn.js": "^5.2.1", + "browserify-rsa": "^4.1.0", "create-hash": "^1.2.0", "create-hmac": "^1.1.7", - "elliptic": "^6.5.3", + "elliptic": "^6.5.5", + "hash-base": "~3.0", "inherits": "^2.0.4", - "parse-asn1": "^5.1.5", - "readable-stream": "^3.6.0", - "safe-buffer": "^5.2.0" + "parse-asn1": "^5.1.7", + "readable-stream": "^2.3.8", + "safe-buffer": "^5.2.1" }, "dependencies": { + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha512-EeeoJKjTyt868liAlVmcv2ZsUfGHlE3Q+BICOXcZiwN3osr5Q/zFGYmTJpoIzuaSTAwndFy+GqhEwlU4L3j4Ow==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, "readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", + "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==", "dev": true, "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + } } }, "safe-buffer": { @@ -2528,9 +2647,9 @@ } }, "caniuse-db": { - "version": "1.0.30001478", - "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30001478.tgz", - "integrity": "sha512-t80eKm8nWCTTWVzfScEB0e8ltCXx1d0nFwyCrFAwQW2gh/vRrZ4BtOaWirzBNDTvK/YuDtlKtJA2O19izdQAQQ==", + "version": "1.0.30001599", + "resolved": "https://registry.npmjs.org/caniuse-db/-/caniuse-db-1.0.30001599.tgz", + "integrity": "sha512-hf+Cz6b+u6k66JYkb1Rx/2vwZRk1Tplqart197ohxjRsQsvF2LkXJZ/VlHFjyqp3njXuFlVBf8fSkfd7VjsK2g==", "dev": true }, "caseless": { @@ -2961,7 +3080,7 @@ "color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" }, "color-string": { "version": "0.3.0", @@ -3611,13 +3730,13 @@ "dev": true }, "d": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", - "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", + "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", "dev": true, "requires": { - "es5-ext": "^0.10.50", - "type": "^1.0.1" + "es5-ext": "^0.10.64", + "type": "^2.7.2" } }, "d3": { @@ -3685,16 +3804,17 @@ "integrity": "sha512-yVn6RZmHiGnxRKR9sJb3iVV2XTF1Ghh2DiWRZ3dMnGc43yUdWWF/kX6lQyk3+P84iprfWKU/8zFTrlkvtFm1ug==" }, "deep-equal": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.0.tgz", - "integrity": "sha512-RdpzE0Hv4lhowpIUKKMJfeH6C1pXdtT1/it80ubgWqwI3qpuxUBpC1S4hnHg+zjnuOoDkzUtUCEEkG+XG5l3Mw==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", + "integrity": "sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "es-get-iterator": "^1.1.2", - "get-intrinsic": "^1.1.3", + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.5", + "es-get-iterator": "^1.1.3", + "get-intrinsic": "^1.2.2", "is-arguments": "^1.1.1", - "is-array-buffer": "^3.0.1", + "is-array-buffer": "^3.0.2", "is-date-object": "^1.0.5", "is-regex": "^1.1.4", "is-shared-array-buffer": "^1.0.2", @@ -3702,18 +3822,73 @@ "object-is": "^1.1.5", "object-keys": "^1.1.1", "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.4.3", + "regexp.prototype.flags": "^1.5.1", "side-channel": "^1.0.4", "which-boxed-primitive": "^1.0.2", "which-collection": "^1.0.1", - "which-typed-array": "^1.1.9" + "which-typed-array": "^1.1.13" }, "dependencies": { + "call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + } + }, + "define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "requires": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + }, + "get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + } + }, "isarray": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true + }, + "regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "requires": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" + } } } }, @@ -3747,6 +3922,17 @@ "clone": "^1.0.2" } }, + "define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + } + }, "define-properties": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.4.tgz", @@ -3868,9 +4054,9 @@ "dev": true }, "des.js": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz", - "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.1.0.tgz", + "integrity": "sha512-r17GxjhUCjSRy8aiJpr8/UadFIzMzJGexI3Nmz4ADi9LYSFx4gTBp80+NaX/YsXWWLhpZ7v/v/ubEc/bCNfKwg==", "dev": true, "requires": { "inherits": "^2.0.1", @@ -3964,7 +4150,7 @@ } }, "docs-soap": { - "version": "github:tomaskikutis/docs-soap#95dbd7e7d245f4c0329422640cad068e4bcbf9c5", + "version": "github:tomaskikutis/docs-soap#cca5d748d3bdce3537ef512ec1ce1492d0f3983b", "from": "github:tomaskikutis/docs-soap#convert-tables", "dev": true }, @@ -4182,9 +4368,9 @@ }, "dependencies": { "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true } } @@ -4196,15 +4382,15 @@ "dev": true }, "electron-to-chromium": { - "version": "1.4.361", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.361.tgz", - "integrity": "sha512-VocVwjPp05HUXzf3xmL0boRn5b0iyqC7amtDww84Jb1QJNPBc7F69gJyEeXRoriLBC4a5pSyckdllrXAg4mmRA==", + "version": "1.4.713", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.713.tgz", + "integrity": "sha512-vDarADhwntXiULEdmWd77g2dV6FrNGa8ecAC29MZ4TwPut2fvosD0/5sJd1qWNNe8HcJFAC+F5Lf9jW1NPtWmw==", "dev": true }, "elliptic": { - "version": "6.5.4", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", - "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", + "version": "6.5.5", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.5.tgz", + "integrity": "sha512-7EjbcmUm17NQFu4Pmgmq2olYMj8nwMnpcddByChSUjArp8F5DQWcIcpriwO4ZToLNAJig0yiyjswfyGNje/ixw==", "dev": true, "requires": { "bn.js": "^4.11.9", @@ -4523,6 +4709,42 @@ "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==", "dev": true }, + "es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "dev": true, + "requires": { + "get-intrinsic": "^1.2.4" + }, + "dependencies": { + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + }, + "get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + } + } + } + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true + }, "es-get-iterator": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", @@ -4569,13 +4791,14 @@ } }, "es5-ext": { - "version": "0.10.62", - "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.62.tgz", - "integrity": "sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==", + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", "dev": true, "requires": { "es6-iterator": "^2.0.3", "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", "next-tick": "^1.1.0" } }, @@ -4633,24 +4856,16 @@ "es6-symbol": "^3.1.3", "event-emitter": "^0.3.5", "type": "^2.7.2" - }, - "dependencies": { - "type": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", - "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", - "dev": true - } } }, "es6-symbol": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", - "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", + "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", "dev": true, "requires": { - "d": "^1.0.1", - "ext": "^1.1.2" + "d": "^1.0.2", + "ext": "^1.7.0" } }, "es6-templates": { @@ -4854,6 +5069,18 @@ "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==", "dev": true }, + "esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "dev": true, + "requires": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + } + }, "espree": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz", @@ -5098,17 +5325,17 @@ } }, "express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.1.tgz", + "integrity": "sha512-K4w1/Bp7y8iSiVObmCrtq8Cs79XjJc/RU2YYkZQ7wpUu5ZyZ7MtPHkqoMz4pf+mgXfNvo2qft8D9OnrH2ABk9w==", "dev": true, "requires": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -5142,10 +5369,38 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "dev": true }, + "body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dev": true, + "requires": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "dependencies": { + "content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true + } + } + }, "cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", "dev": true }, "etag": { @@ -5175,6 +5430,15 @@ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "dev": true }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, "ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -5187,6 +5451,18 @@ "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", "dev": true }, + "raw-body": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "dev": true, + "requires": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -5302,14 +5578,6 @@ "dev": true, "requires": { "type": "^2.7.2" - }, - "dependencies": { - "type": { - "version": "2.7.2", - "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", - "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", - "dev": true - } } }, "extend": { @@ -7401,6 +7669,12 @@ "get-intrinsic": "^1.1.1" } }, + "has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "dev": true + }, "has-symbols": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", @@ -7491,6 +7765,23 @@ "minimalistic-assert": "^1.0.1" } }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "requires": { + "function-bind": "^1.1.2" + }, + "dependencies": { + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + } + } + }, "hawk": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/hawk/-/hawk-3.1.3.tgz", @@ -8389,25 +8680,32 @@ } }, "is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, "requires": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" }, "dependencies": { + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + }, "get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" } } } @@ -8576,9 +8874,9 @@ } }, "is-map": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", - "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", "dev": true }, "is-my-ip-valid": { @@ -8718,9 +9016,9 @@ "dev": true }, "is-set": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", - "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", "dev": true }, "is-shared-array-buffer": { @@ -8771,19 +9069,6 @@ "has-symbols": "^1.0.2" } }, - "is-typed-array": { - "version": "1.1.10", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", - "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", - "dev": true, - "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" - } - }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -8815,9 +9100,9 @@ "dev": true }, "is-weakmap": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", - "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", "dev": true }, "is-weakref": { @@ -8830,13 +9115,47 @@ } }, "is-weakset": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", - "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.3.tgz", + "integrity": "sha512-LvIm3/KWzS9oRFHugab7d+M/GcBXuXX5xZkzPmN+NxihdQlZUQ4dWuSV1xR/sq6upL1TJEDrfBgRepHFdBtSNQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4" + }, + "dependencies": { + "call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + } + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + }, + "get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + } + } } }, "is-windows": { @@ -8997,18 +9316,73 @@ "deep-equal": "^1.0.0" }, "dependencies": { + "call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + } + }, "deep-equal": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", - "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.2.tgz", + "integrity": "sha512-5tdhKF6DbU7iIzrIOa1AOUt39ZRm13cmL1cGEh//aqR8x9+tNfbywRf0n5FD/18OKMdo7DNEtrX2t22ZAkI+eg==", "dev": true, "requires": { - "is-arguments": "^1.0.4", - "is-date-object": "^1.0.1", - "is-regex": "^1.0.4", - "object-is": "^1.0.1", + "is-arguments": "^1.1.1", + "is-date-object": "^1.0.5", + "is-regex": "^1.1.4", + "object-is": "^1.1.5", "object-keys": "^1.1.1", - "regexp.prototype.flags": "^1.2.0" + "regexp.prototype.flags": "^1.5.1" + } + }, + "define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "requires": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + } + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + }, + "get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + } + }, + "regexp.prototype.flags": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", + "dev": true, + "requires": { + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" } } } @@ -10062,9 +10436,9 @@ } }, "loglevel": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.1.tgz", - "integrity": "sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.1.tgz", + "integrity": "sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==", "dev": true }, "lolex": { @@ -11668,16 +12042,35 @@ } }, "parse-asn1": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.6.tgz", - "integrity": "sha512-RnZRo1EPU6JBnra2vGHj0yhp6ebyjBZpmUCLHWiFhxlzvBCCpAuZ7elsBp1PVAbQN0/04VD/19rfzlBSwLstMw==", + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.7.tgz", + "integrity": "sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==", "dev": true, "requires": { - "asn1.js": "^5.2.0", - "browserify-aes": "^1.0.0", - "evp_bytestokey": "^1.0.0", - "pbkdf2": "^3.0.3", - "safe-buffer": "^5.1.1" + "asn1.js": "^4.10.1", + "browserify-aes": "^1.2.0", + "evp_bytestokey": "^1.0.3", + "hash-base": "~3.0", + "pbkdf2": "^3.1.2", + "safe-buffer": "^5.2.1" + }, + "dependencies": { + "hash-base": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz", + "integrity": "sha512-EeeoJKjTyt868liAlVmcv2ZsUfGHlE3Q+BICOXcZiwN3osr5Q/zFGYmTJpoIzuaSTAwndFy+GqhEwlU4L3j4Ow==", + "dev": true, + "requires": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + } } }, "parse-filepath": { @@ -12092,6 +12485,12 @@ "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", "integrity": "sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==" }, + "possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true + }, "postcss": { "version": "5.2.18", "resolved": "https://registry.npmjs.org/postcss/-/postcss-5.2.18.tgz", @@ -12817,12 +13216,6 @@ "strict-uri-encode": "^1.0.0" } }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==", - "dev": true - }, "querystring-es3": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz", @@ -14214,6 +14607,73 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, + "set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "dependencies": { + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + }, + "get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + } + }, + "has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "requires": { + "es-define-property": "^1.0.0" + } + } + } + }, + "set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "dependencies": { + "has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "requires": { + "es-define-property": "^1.0.0" + } + } + } + }, "set-value": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", @@ -14772,9 +15232,9 @@ } }, "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", "dev": true }, "spdx-expression-parse": { @@ -14788,9 +15248,9 @@ } }, "spdx-license-ids": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.13.tgz", - "integrity": "sha512-XkD+zwiqXHikFZm4AX/7JSCXA98U5Db4AFd5XUg/+9UNtnH75+Z9KxtpYiJZx36mUDVOwH83pl7yvCer6ewM3w==", + "version": "3.0.17", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.17.tgz", + "integrity": "sha512-sh8PWc/ftMqAAdFiBu6Fy6JUOYjqDJBJvIhpfDMyHrr0Rbp5liZqd4TjtQ/RgfLjKFZb+LMx5hpml5qOWy0qvg==", "dev": true }, "spdy": { @@ -14896,25 +15356,14 @@ "internal-slot": "^1.0.4" }, "dependencies": { - "get-intrinsic": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", - "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", - "dev": true, - "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.3" - } - }, "internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, "requires": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "hasown": "^2.0.0", "side-channel": "^1.0.4" } } @@ -15569,8 +16018,8 @@ } }, "superdesk-core": { - "version": "github:superdesk/superdesk-client-core#7b2fbe1b1d714cb7a6207e21faf9a408ae88b24a", - "from": "github:superdesk/superdesk-client-core#v2.6.2", + "version": "github:superdesk/superdesk-client-core#c32bc2d97b396cee16a33d6d0f583560e7d50e99", + "from": "github:superdesk/superdesk-client-core#hotfix/2.6.3", "dev": true, "requires": { "@metadata/exif": "github:superdesk/exif#431066d", @@ -15590,7 +16039,6 @@ "angular-embed": "github:superdesk/angular-embed#d75968e", "angular-embedly": "github:Urigo/angular-embedly#0.0.8", "angular-gettext": "github:tomaskikutis/angular-gettext#master", - "angular-history": "github:decipherinc/angular-history#v0.8.0", "angular-i18n": "1.6.9", "angular-mocks": "1.6.9", "angular-moment": "1.2.0", @@ -15664,7 +16112,7 @@ "sass-loader": "6.0.6", "shortid": "2.2.8", "style-loader": "0.20.2", - "superdesk-ui-framework": "3.0.9", + "superdesk-ui-framework": "^3.0.71", "ts-loader": "3.5.0", "tslint": "5.11.0", "typescript": "3.9.7", @@ -15680,19 +16128,10 @@ "integrity": "sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ==", "dev": true }, - "@superdesk/primereact": { - "version": "5.0.2-11", - "resolved": "https://registry.npmjs.org/@superdesk/primereact/-/primereact-5.0.2-11.tgz", - "integrity": "sha512-Dbya04bogmc+BZTAunTLYsV6AghvEbUiJ7yehqz6pwLvJ5j6N+V0PdafoYcu7zSwmWt3FYTaXsEMMImJqJd1Jw==", - "dev": true, - "requires": { - "react-transition-group": "^4.4.1" - } - }, "@types/node": { - "version": "14.18.42", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.42.tgz", - "integrity": "sha512-xefu+RBie4xWlK8hwAzGh3npDz/4VhF6icY/shU+zv/1fNn+ZVG7T7CRwe9LId9sAYRPxI+59QBPuKL3WpyGRg==", + "version": "14.18.63", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz", + "integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==", "dev": true }, "@typescript-eslint/experimental-utils": { @@ -15739,12 +16178,6 @@ "integrity": "sha512-DTt3GhOUDKhh4ONwIJW4lmhyotQmV2LjNlGK/J2hkwUcqcbKkCLAdJPtxQnxnlc7SR3f1CEXCyMmc7WLUsWbNA==", "dev": true }, - "csstype": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.2.tgz", - "integrity": "sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==", - "dev": true - }, "debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -15754,16 +16187,6 @@ "ms": "2.1.2" } }, - "dom-helpers": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz", - "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==", - "dev": true, - "requires": { - "@babel/runtime": "^7.8.7", - "csstype": "^3.0.2" - } - }, "json5": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", @@ -15837,31 +16260,6 @@ } } }, - "react-transition-group": { - "version": "4.4.5", - "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz", - "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==", - "dev": true, - "requires": { - "@babel/runtime": "^7.5.5", - "dom-helpers": "^5.0.1", - "loose-envify": "^1.4.0", - "prop-types": "^15.6.2" - }, - "dependencies": { - "prop-types": { - "version": "15.8.1", - "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", - "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", - "dev": true, - "requires": { - "loose-envify": "^1.4.0", - "object-assign": "^4.1.1", - "react-is": "^16.13.1" - } - } - } - }, "redux": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/redux/-/redux-4.0.5.tgz", @@ -15873,24 +16271,29 @@ } }, "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true }, "superdesk-ui-framework": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/superdesk-ui-framework/-/superdesk-ui-framework-3.0.9.tgz", - "integrity": "sha512-6b3seE2uA2JRTSV/pkREGbS/+67BIt6Gu8ILKqUFmsBrCZSluJ6DH1wSbvP8pDrFwN9IUOyEJqwMco8Q+L2R4A==", + "version": "3.0.75", + "resolved": "https://registry.npmjs.org/superdesk-ui-framework/-/superdesk-ui-framework-3.0.75.tgz", + "integrity": "sha512-kXoBOAMRPrR7CMfK/MdR+fYeK2b+lQrJpTXT0N5eVsrwhSK6nUYkJlPQaHnfmLDD6JqhFev0RnmWABD3OGz7sw==", "dev": true, "requires": { "@material-ui/lab": "^4.0.0-alpha.56", "@popperjs/core": "^2.4.0", - "@superdesk/primereact": "^5.0.2-10", + "@superdesk/primereact": "^5.0.2-12", + "@superdesk/react-resizable-panels": "0.0.39", + "@types/enzyme-adapter-react-16": "^1.0.6", "@types/node": "^14.10.2", "chart.js": "^2.9.3", "date-fns": "2.7.0", + "enzyme": "^3.11.0", + "enzyme-adapter-react-16": "^1.15.7", "moment": "^2.29.3", + "popper-max-size-modifier": "^0.2.0", "popper.js": "1.14.4", "primeicons": "2.0.0", "react-beautiful-dnd": "^13.0.0", @@ -16350,9 +16753,9 @@ "dev": true }, "type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", - "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==", + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.2.tgz", + "integrity": "sha512-dzlvlNlt6AXU7EBSfpAscydQ7gXB+pPGsPnfJnZpiNJBDj7IaJzQlBZYGdEi4R9HmPdBv2XmWJ6YUtoTa7lmCw==", "dev": true }, "type-check": { @@ -16665,20 +17068,79 @@ "integrity": "sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==" }, "url": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz", - "integrity": "sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==", + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/url/-/url-0.11.3.tgz", + "integrity": "sha512-6hxOLGfZASQK/cijlZnZJTq8OXAkt/3YGfQX45vvMYXpZoo8NdWZcY73K108Jf759lS1Bv/8wXnHDTSz17dSRw==", "dev": true, "requires": { - "punycode": "1.3.2", - "querystring": "0.2.0" + "punycode": "^1.4.1", + "qs": "^6.11.2" }, "dependencies": { + "call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + } + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + }, + "get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + } + }, + "object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "dev": true + }, "punycode": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz", - "integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", "dev": true + }, + "qs": { + "version": "6.12.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.0.tgz", + "integrity": "sha512-trVZiI6RMOkO476zLGaBIzszOdFPnCCXHPG9kn0yuS1uz6xdVxPfZdB3vUig9pxPFDM9BRAgz/YUIVQ1/vuiUg==", + "dev": true, + "requires": { + "side-channel": "^1.0.6" + } + }, + "side-channel": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "dev": true, + "requires": { + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + } } } }, @@ -16990,9 +17452,9 @@ } }, "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, "optional": true }, @@ -17007,9 +17469,9 @@ } }, "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, "optional": true, "requires": { @@ -17034,9 +17496,9 @@ } }, "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "optional": true }, @@ -17329,9 +17791,9 @@ } }, "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", "dev": true }, "yargs": { @@ -17589,15 +18051,15 @@ } }, "which-collection": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", - "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, "requires": { - "is-map": "^2.0.1", - "is-set": "^2.0.1", - "is-weakmap": "^2.0.1", - "is-weakset": "^2.0.1" + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" } }, "which-module": { @@ -17607,17 +18069,59 @@ "dev": true }, "which-typed-array": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", - "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dev": true, "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0", - "is-typed-array": "^1.1.10" + "has-tostringtag": "^1.0.2" + }, + "dependencies": { + "call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "dev": true, + "requires": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + } + }, + "function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true + }, + "get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + } + }, + "has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "requires": { + "has-symbols": "^1.0.3" + } + } } }, "wide-align": { diff --git a/package.json b/package.json index c40eaadda..353e000e8 100644 --- a/package.json +++ b/package.json @@ -66,7 +66,7 @@ "simulant": "^0.2.2", "sinon": "^4.5.0", "superdesk-code-style": "1.5.0", - "superdesk-core": "github:superdesk/superdesk-client-core#v2.6.2", + "superdesk-core": "github:superdesk/superdesk-client-core#hotfix/2.6.3", "superdesk-ui-framework": "^3.0.58", "ts-node": "~7.0.1", "tslint": "5.11.0", diff --git a/server/features/events_recurring.feature b/server/features/events_recurring.feature index b1a38b687..04163191e 100644 --- a/server/features/events_recurring.feature +++ b/server/features/events_recurring.feature @@ -260,12 +260,11 @@ Feature: Events Recurring "event": "events:updated:recurring", "extra": { "item": "#EVENT_ID#", - "recurrence_id": "__any_value__", + "recurrence_id": "#EVENT_ID#", "user": "#CONTEXT_USER_ID#" } }] """ - Then we store "NEW_RECURRING" from patch When we get "/events" Then we get list with 3 items """ @@ -276,21 +275,21 @@ Feature: Events Recurring "start": "2019-11-22T12:00:00+0000", "end": "2019-11-22T14:00:00+0000" }, - "recurrence_id": "#NEW_RECURRING.recurrence_id#" + "recurrence_id": "#EVENT_ID#" }, { "name": "Weekly Friday Club", "dates": { "start": "2019-11-29T12:00:00+0000", "end": "2019-11-29T14:00:00+0000" }, - "recurrence_id": "#NEW_RECURRING.recurrence_id#" + "recurrence_id": "#EVENT_ID#" }, { "name": "Weekly Friday Club", "dates": { "start": "2019-12-06T12:00:00+0000", "end": "2019-12-06T14:00:00+0000" }, - "recurrence_id": "#NEW_RECURRING.recurrence_id#" + "recurrence_id": "#EVENT_ID#" } ]} """ @@ -406,7 +405,6 @@ Feature: Events Recurring } """ Then we get OK response - Then we store "NEW_RECURRING" from patch When we get "/events" Then we get list with 4 items """ @@ -419,7 +417,7 @@ Feature: Events Recurring "end": "2019-11-21T14:00:00+0000" }, "state": "rescheduled", - "recurrence_id": "#NEW_RECURRING.recurrence_id#" + "recurrence_id": "event1" }, { "name": "Weekly Friday Club", @@ -427,21 +425,21 @@ Feature: Events Recurring "start": "2019-11-22T12:00:00+0000", "end": "2019-11-22T14:00:00+0000" }, - "recurrence_id": "#NEW_RECURRING.recurrence_id#" + "recurrence_id": "event1" }, { "name": "Weekly Friday Club", "dates": { "start": "2019-11-29T12:00:00+0000", "end": "2019-11-29T14:00:00+0000" }, - "recurrence_id": "#NEW_RECURRING.recurrence_id#" + "recurrence_id": "event1" }, { "name": "Weekly Friday Club", "dates": { "start": "2019-12-06T12:00:00+0000", "end": "2019-12-06T14:00:00+0000" }, - "recurrence_id": "#NEW_RECURRING.recurrence_id#" + "recurrence_id": "event1" } ]} """ @@ -451,7 +449,7 @@ Feature: Events Recurring { "_id": "event1", "state": "rescheduled", - "recurrence_id": "#NEW_RECURRING.recurrence_id#" + "recurrence_id": "event1" } """ When we get "/planning/plan1" @@ -461,7 +459,7 @@ Feature: Events Recurring "slugline": "TestPlan", "state": "rescheduled", "event_item": "event1", - "recurrence_id": "#NEW_RECURRING.recurrence_id#" + "recurrence_id": "event1" } """ When we get "/events_history" @@ -513,7 +511,6 @@ Feature: Events Recurring } """ Then we get OK response - And we store "NEW_RECURRING" from patch When we get "/events" Then we get list with 3 items """ @@ -524,21 +521,21 @@ Feature: Events Recurring "start": "2019-11-22T12:00:00+0000", "end": "2019-11-22T14:00:00+0000" }, - "recurrence_id": "#NEW_RECURRING.recurrence_id#" + "recurrence_id": "#EVENT_ID#" }, { "name": "Friday Club", "dates": { "start": "2019-11-29T12:00:00+0000", "end": "2019-11-29T14:00:00+0000" }, - "recurrence_id": "#NEW_RECURRING.recurrence_id#" + "recurrence_id": "#EVENT_ID#" }, { "name": "Friday Club", "dates": { "start": "2019-12-06T12:00:00+0000", "end": "2019-12-06T14:00:00+0000" }, - "recurrence_id": "#NEW_RECURRING.recurrence_id#" + "recurrence_id": "#EVENT_ID#" } ]} """ diff --git a/server/planning/events/events.py b/server/planning/events/events.py index 59bfc53b4..ac4d5454d 100644 --- a/server/planning/events/events.py +++ b/server/planning/events/events.py @@ -223,7 +223,7 @@ def on_create(self, docs): recurring_events = generate_recurring_events(event) generated_events.extend(recurring_events) # remove the event that contains the recurring rule. We don't need it anymore - docs.remove(event) + docs.remove(event) # todo: why we remove that event and not update it? # Set the current Event to the first Event in the new series # This will make sure the ID of the Event can be used when @@ -623,7 +623,7 @@ def mark_event_complete(self, original, updates, event, mark_complete_validated) def _convert_to_recurring_event(self, updates, original): """Convert a single event to a series of recurring events""" self._validate_convert_to_recurring(updates, original) - updates["recurrence_id"] = generate_guid(type=GUID_NEWSML) + updates["recurrence_id"] = original["_id"] merged = copy.deepcopy(original) merged.update(updates) @@ -631,7 +631,7 @@ def _convert_to_recurring_event(self, updates, original): # Generated new events will be "draft" merged[ITEM_STATE] = WORKFLOW_STATE.DRAFT - generated_events = generate_recurring_events(merged) + generated_events = generate_recurring_events(merged, updates["recurrence_id"]) updated_event = generated_events.pop(0) # Check to see if the first generated event is different from original @@ -867,13 +867,10 @@ def overwrite_event_expiry_date(event): event["expiry"] = event["dates"]["end"] + timedelta(minutes=expiry_minutes or 0) -def generate_recurring_events(event): +def generate_recurring_events(event, recurrence_id=None): generated_events = [] setRecurringMode(event) - # Get the recurrence_id, or generate one if it doesn't exist - recurrence_id = event.get("recurrence_id", generate_guid(type=GUID_NEWSML)) - # compute the difference between start and end in the original event time_delta = event["dates"]["end"] - event["dates"]["start"] # for all the dates based on the recurring rules: @@ -904,6 +901,8 @@ def generate_recurring_events(event): new_event["guid"] = generate_guid(type=GUID_NEWSML) new_event["_id"] = new_event["guid"] # set the recurrence id + if not recurrence_id: + recurrence_id = new_event["guid"] new_event["recurrence_id"] = recurrence_id # set expiry date From 938f1533fa6d6dba092be08b4443f6af70fdb33b Mon Sep 17 00:00:00 2001 From: Ketan <73937490+devketanpro@users.noreply.github.com> Date: Tue, 2 Apr 2024 16:20:44 +0530 Subject: [PATCH 5/9] Fix : Some coverage items are not displaying in Newspro [SDCP-755] (#1940) * FIX : if planning item is locked when working on coverage assignment[CPCN-726] * remove all functionality related to check planning is locked * remove unwanted code --- server/planning/assignments/assignments.py | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/server/planning/assignments/assignments.py b/server/planning/assignments/assignments.py index 978b8869d..ca7534518 100644 --- a/server/planning/assignments/assignments.py +++ b/server/planning/assignments/assignments.py @@ -1296,22 +1296,7 @@ def _publish_planning(item): else: logger.error("Failed to save planning version for planning item id {}".format(item["_id"])) - try: - # check if the planning item is locked - lock_service.validate_relationship_locks(planning_item, "planning") - use_published_planning = False - except SuperdeskApiError as ex: - # planning item is already locked. - use_published_planning = True - logger.exception(str(ex)) - - if use_published_planning: - # use the published planning and enqueue again - plan = published_planning_item.get("published_item") - else: - plan = planning_item - - _publish_planning(plan) + _publish_planning(planning_item) except Exception: logger.exception("Failed to publish assignment for planning.") From cdac148f09d55e0b6616bfdc12a6e9306fa30af2 Mon Sep 17 00:00:00 2001 From: Ketan <73937490+devketanpro@users.noreply.github.com> Date: Tue, 2 Apr 2024 16:20:44 +0530 Subject: [PATCH 6/9] Fix : Some coverage items are not displaying in Newspro [SDCP-755] (#1940) * FIX : if planning item is locked when working on coverage assignment[CPCN-726] * remove all functionality related to check planning is locked * remove unwanted code --- server/planning/assignments/assignments.py | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/server/planning/assignments/assignments.py b/server/planning/assignments/assignments.py index e57387c4d..6da9a69d0 100644 --- a/server/planning/assignments/assignments.py +++ b/server/planning/assignments/assignments.py @@ -1317,22 +1317,7 @@ def _publish_planning(item): else: logger.error("Failed to save planning version for planning item id {}".format(item["_id"])) - try: - # check if the planning item is locked - lock_service.validate_relationship_locks(planning_item, "planning") - use_published_planning = False - except SuperdeskApiError as ex: - # planning item is already locked. - use_published_planning = True - logger.exception(str(ex)) - - if use_published_planning: - # use the published planning and enqueue again - plan = published_planning_item.get("published_item") - else: - plan = planning_item - - _publish_planning(plan) + _publish_planning(planning_item) except Exception: logger.exception("Failed to publish assignment for planning.") From 9191ab936253abb2c2fb72cbbd6a046809b214c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Ja=C5=A1ek?= Date: Thu, 4 Apr 2024 09:10:45 +0200 Subject: [PATCH 7/9] Create dependabot.yml (#1944) --- .github/dependabot.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..3d9999646 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,15 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + - package-ecosystem: "npm" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" + - package-ecosystem: "pip" # See documentation for possible values + directory: "/" # Location of package manifests + schedule: + interval: "weekly" From 5219dafe570915254b431cc846ad0ec248dbe4b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Ja=C5=A1ek?= Date: Thu, 4 Apr 2024 09:45:16 +0200 Subject: [PATCH 8/9] fix deprecated docker-compose on github actions (#1945) --- .travis.yml | 94 ------------------------------------ scripts/ci-start-services.sh | 2 +- 2 files changed, 1 insertion(+), 95 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 85968c945..000000000 --- a/.travis.yml +++ /dev/null @@ -1,94 +0,0 @@ -language: python - -python: 3.6 - -dist: bionic - -services: - - docker - -addons: - chrome: stable - -cache: - pip: true - npm: true - directories: - - ~/.npm - - ~/.cache - -before_install: - - | - if [ "$INSTALL_NODEJS" == "true" ]; then - nvm install lts/* - fi - - | - if [ "$INSTALL_NODE_MODULES" == "true" ]; then - npm install - fi - - | - if [ "$INSTALL_PY_MODULES" == "true" ]; then - cd server - pip install -r requirements.txt - cd .. - fi - - | - if [ "$RUN_SERVICES" == "true" ]; then - docker-compose -f .travis-docker-compose.yml up -d - sleep 30 - fi - - | - if [ "$E2E" == "true" ]; then - cd e2e/server - pip install -r requirements.txt - cd .. - fi - - | - if [ "$E2E" == "true" ]; then - npm install - fi - - | - if [ "$E2E" == "true" ]; then - npm run build - fi - - | - if [ "$E2E" == "true" ]; then - cd server - honcho start & - cd .. - fi - -jobs: - include: - - name: "server" - env: - - INSTALL_NODEJS=false - - INSTALL_NODE_MODULES=false - - INSTALL_PY_MODULES=true - - RUN_SERVICES=true - script: cd server && flake8 && nosetests --logging-level=ERROR && behave --format progress2 --logging-level=ERROR - - name: "client" - env: - - INSTALL_NODEJS=true - - INSTALL_NODE_MODULES=true - - INSTALL_PY_MODULES=false - - RUN_SERVICES=false - script: npm run test - - name: "e2e vol. 1 (events)" - env: - - INSTALL_NODEJS=true - - INSTALL_NODE_MODULES=true - - INSTALL_PY_MODULES=false - - RUN_SERVICES=true - - E2E=true - - TZ=Australia/Sydney - script: npm run cypress-ci -- --spec "cypress/integration/events/*.spec.js" - - name: "e2e vol. 2 (non-events)" - env: - - INSTALL_NODEJS=true - - INSTALL_NODE_MODULES=true - - INSTALL_PY_MODULES=false - - RUN_SERVICES=true - - E2E=true - - TZ=Australia/Sydney - script: npm run cypress-ci -- --spec "cypress/integration/!(events)/*.spec.js" diff --git a/scripts/ci-start-services.sh b/scripts/ci-start-services.sh index 913120d1d..4cf286dec 100755 --- a/scripts/ci-start-services.sh +++ b/scripts/ci-start-services.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash if [ "$RUN_SERVICES" == "true" ]; then - docker-compose -f .travis-docker-compose.yml up -d + docker compose -f .travis-docker-compose.yml up -d while ! curl -sfo /dev/null 'http://localhost:9200/'; do echo -n '.' && sleep .5; done fi From 9b9869eb1eba5aaa41626102b39d1206c35e7540 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 5 Apr 2024 08:37:48 +0200 Subject: [PATCH 9/9] Bump coverage from 4.3.4 to 7.4.4 (#1946) Bumps [coverage](https://github.com/nedbat/coveragepy) from 4.3.4 to 7.4.4. - [Release notes](https://github.com/nedbat/coveragepy/releases) - [Changelog](https://github.com/nedbat/coveragepy/blob/master/CHANGES.rst) - [Commits](https://github.com/nedbat/coveragepy/compare/coverage-4.3.4...7.4.4) --- updated-dependencies: - dependency-name: coverage dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- server/requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/requirements.txt b/server/requirements.txt index a798d6518..b95b4d23e 100644 --- a/server/requirements.txt +++ b/server/requirements.txt @@ -8,7 +8,7 @@ wooper==0.4.4 requests requests-mock==1.8.0 icalendar>=4.0.3,<4.1 -coverage==4.3.4 +coverage==7.4.4 deepdiff coveralls mock