diff --git a/docs/package-lock.json b/docs/package-lock.json index 466ddce74610..50ba48160941 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -4382,11 +4382,11 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -6450,9 +6450,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dependencies": { "to-regex-range": "^5.0.1" }, diff --git a/requirements-base.txt b/requirements-base.txt index d0c4b4883a70..158e22bb6851 100644 --- a/requirements-base.txt +++ b/requirements-base.txt @@ -124,7 +124,7 @@ frozenlist==1.4.1 # aiosignal google-api-core==2.15.0 # via google-api-python-client -google-api-python-client==2.132.0 +google-api-python-client==2.133.0 # via -r requirements-base.in google-auth==2.26.1 # via @@ -214,7 +214,7 @@ markupsafe==2.1.3 # jinja2 # mako # werkzeug -msal==1.28.0 +msal==1.28.1 # via -r requirements-base.in multidict==6.0.4 # via @@ -242,7 +242,7 @@ oauthlib[signedtoken]==3.2.2 # atlassian-python-api # jira # requests-oauthlib -openai==1.32.0 +openai==1.34.0 # via -r requirements-base.in packaging==23.2 # via @@ -396,7 +396,7 @@ six==1.16.0 # validators slack-bolt==1.18.1 # via -r requirements-base.in -slack-sdk==3.27.2 +slack-sdk==3.29.0 # via # -r requirements-base.in # slack-bolt diff --git a/requirements-dev.txt b/requirements-dev.txt index a72885509a65..01be3e7aa287 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -32,7 +32,7 @@ executing==2.0.1 # stack-data factory-boy==3.3.0 # via -r requirements-dev.in -faker==25.6.0 +faker==25.8.0 # via # -r requirements-dev.in # factory-boy diff --git a/src/dispatch/incident/messaging.py b/src/dispatch/incident/messaging.py index 3281b38119e4..ab19cd4f3497 100644 --- a/src/dispatch/incident/messaging.py +++ b/src/dispatch/incident/messaging.py @@ -658,7 +658,7 @@ def send_participant_announcement_message( f"*Name:* {participant_name_mrkdwn}\n" f"*Team*: {participant_team}, {participant_department}\n" f"*Location*: {participant_location}\n" - f"*Incident Role(s)*: {(', ').join(participant_roles)}\n" + f"*{subject_type} Role(s)*: {(', ').join(participant_roles)}\n" ), }, }, diff --git a/src/dispatch/plugins/dispatch_duo/plugin.py b/src/dispatch/plugins/dispatch_duo/plugin.py index 8c184b98fd17..39fdf7bebc6c 100644 --- a/src/dispatch/plugins/dispatch_duo/plugin.py +++ b/src/dispatch/plugins/dispatch_duo/plugin.py @@ -76,22 +76,33 @@ def send_push_notification( For more information, see https://duo.com/docs/authapi#/auth """ duo_client = duo_service.create_duo_auth_client(self.configuration) - try: - response = duo_client.auth(factor="push", username=username, device=device, type=type) - except RuntimeError as e: - if "Invalid request parameters (username)" in str(e): - username, _ = username.split("@") - - try: - response = duo_client.auth( - factor="push", username=username, device=device, type=type - ) - except RuntimeError as e: - if "Invalid request parameters (username)" in str(e): - log.warning( - f"Sending push notification failed. Unable to find {username} in Duo" - ) - return PushResponseResult.user_not_found + userstatus = duo_client.preauth(username=username) + response = {} + + if userstatus["result"] == "enroll" and "@" in username: + username, domain = username.split("@") + userstatus = duo_client.preauth(username=username) + + if userstatus["result"] == "enroll": + log.warning(f"Sending push notification failed. Unable to find {username} in Duo") + return PushResponseResult.user_not_found + elif userstatus["result"] == "deny": + return PushResponseResult.deny + elif userstatus["result"] == "allow": + return PushResponseResult.allow + elif userstatus["result"] == "auth": + push_devs = [row.get("device") for row in userstatus.get("devices") if "push" in row.get("capabilities")] + if len(push_devs) < 1: + log.error(f"ERROR: Duo account found for {username}, but no devices support Push") + return PushResponseResult.deny + try: + response = duo_client.auth(factor="push", username=username, device=device, type=type) + except RuntimeError as e: + log.error(f"ERROR: Runtime Error during Duo Push: {e}") + return PushResponseResult.deny + else: + log.error(f"ERROR: Unexpected user status from Duo during push: {userstatus}") + return PushResponseResult.deny if response.get("result") == PushResponseResult.allow: return PushResponseResult.allow diff --git a/src/dispatch/plugins/dispatch_google/groups/plugin.py b/src/dispatch/plugins/dispatch_google/groups/plugin.py index 29a04473fb89..e67e3298df80 100644 --- a/src/dispatch/plugins/dispatch_google/groups/plugin.py +++ b/src/dispatch/plugins/dispatch_google/groups/plugin.py @@ -84,7 +84,12 @@ def add_member(client: Any, group_key: str, email: str, role: str): def remove_member(client: Any, group_key: str, email: str): """Removes member from google group.""" - return make_call(client.members(), "delete", groupKey=group_key, memberKey=email) + try: + return make_call(client.members(), "delete", groupKey=group_key, memberKey=email) + except HttpError as e: + if e.resp.status in [409]: + log.debug(f"Member does not exist in google group. GroupKey={group_key} MemberKey={email}") + return def list_members(client: Any, group_key: str, **kwargs): diff --git a/src/dispatch/plugins/dispatch_slack/service.py b/src/dispatch/plugins/dispatch_slack/service.py index 3aaababc611d..3c8e9089815e 100644 --- a/src/dispatch/plugins/dispatch_slack/service.py +++ b/src/dispatch/plugins/dispatch_slack/service.py @@ -275,7 +275,7 @@ def unarchive_conversation(client: WebClient, conversation_id: str) -> SlackResp def rename_conversation(client: WebClient, conversation_id: str, name: str) -> SlackResponse: """Renames an existing conversation.""" return make_call( - client, SlackAPIPostEndpoints.conversations_rename, channel=conversation_id, name=name + client, SlackAPIPostEndpoints.conversations_rename, channel=conversation_id, name=name.lower() ) diff --git a/src/dispatch/static/dispatch/package-lock.json b/src/dispatch/static/dispatch/package-lock.json index e8349b6c2600..ddd3f26d990e 100644 --- a/src/dispatch/static/dispatch/package-lock.json +++ b/src/dispatch/static/dispatch/package-lock.json @@ -1304,21 +1304,21 @@ } }, "node_modules/@tanstack/query-core": { - "version": "5.40.0", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.40.0.tgz", - "integrity": "sha512-eD8K8jsOIq0Z5u/QbvOmfvKKE/XC39jA7yv4hgpl/1SRiU+J8QCIwgM/mEHuunQsL87dcvnHqSVLmf9pD4CiaA==", + "version": "5.45.0", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.45.0.tgz", + "integrity": "sha512-RVfIZQmFUTdjhSAAblvueimfngYyfN6HlwaJUPK71PKd7yi43Vs1S/rdimmZedPWX/WGppcq/U1HOj7O7FwYxw==", "funding": { "type": "github", "url": "https://github.com/sponsors/tannerlinsley" } }, "node_modules/@tanstack/vue-query": { - "version": "5.40.1", - "resolved": "https://registry.npmjs.org/@tanstack/vue-query/-/vue-query-5.40.1.tgz", - "integrity": "sha512-S6zUwFPcLyfwpJO3llD2iTZtQp0Na8cTh+LggdRulIcHMxgjVAKRkjPETFE5fnQiVvtXDkz3pCmTl1Yf5/xxFQ==", + "version": "5.45.0", + "resolved": "https://registry.npmjs.org/@tanstack/vue-query/-/vue-query-5.45.0.tgz", + "integrity": "sha512-WogAH4+xDPWbiK9CUXAE4cQiCyvWeYZI3g3/onKbkb3tVnoEPRhbGHANgxpfAEFY165Vj4afKnI3hkVQvr7aHA==", "dependencies": { "@tanstack/match-sorter-utils": "^8.15.1", - "@tanstack/query-core": "5.40.0", + "@tanstack/query-core": "5.45.0", "@vue/devtools-api": "^6.5.1", "vue-demi": "^0.14.7" }, @@ -2670,11 +2670,11 @@ } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" @@ -3844,9 +3844,9 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -6065,9 +6065,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sass": { - "version": "1.77.4", - "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.4.tgz", - "integrity": "sha512-vcF3Ckow6g939GMA4PeU7b2K/9FALXk2KF9J87txdHzXbUF9XRQRwSxcAs/fGaTnJeBFd7UoV22j3lzMLdM0Pw==", + "version": "1.77.5", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.5.tgz", + "integrity": "sha512-oDfX1mukIlxacPdQqNb6mV2tVCrnE+P3nVYioy72V5tlk56CPNcO4TCuFcaCRKKfJ1M3lH95CleRS+dVKL2qMg==", "dev": true, "dependencies": { "chokidar": ">=3.0.0 <4.0.0", @@ -7324,9 +7324,9 @@ } }, "node_modules/vue-router": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.3.2.tgz", - "integrity": "sha512-hKQJ1vDAZ5LVkKEnHhmm1f9pMiWIBNGF5AwU67PdH7TyXCj/a4hTccuUuYCAMgJK6rO/NVYtQIEN3yL8CECa7Q==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.3.3.tgz", + "integrity": "sha512-8Q+u+WP4N2SXY38FDcF2H1dUEbYVHVPtPCPZj/GTZx8RCbiB8AtJP9+YIxn4Vs0svMTNQcLIzka4GH7Utkx9xQ==", "dependencies": { "@vue/devtools-api": "^6.5.1" }, @@ -7408,9 +7408,9 @@ "integrity": "sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==" }, "node_modules/vuetify": { - "version": "3.6.8", - "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.6.8.tgz", - "integrity": "sha512-j0v0iTeSVRj2ZEM9Q8HxejHxmxrQLYQSalhH82hfcraORaiDoqf1XV05N3P5ERXkKiJjJc/LfxFAUUvYSldxeg==", + "version": "3.6.9", + "resolved": "https://registry.npmjs.org/vuetify/-/vuetify-3.6.9.tgz", + "integrity": "sha512-LVIZL0OCwzg3Aw2F8nT1rK/renpTPOcDEPe5E002Vj+VjXwsCNqwwxNteGfrcNlp0vgIJ8WusMvaxp69UJ3NJg==", "engines": { "node": "^12.20 || >=14.13" }, diff --git a/src/dispatch/static/dispatch/src/case/Table.vue b/src/dispatch/static/dispatch/src/case/Table.vue index 970745ce7068..9a022e67dbf0 100644 --- a/src/dispatch/static/dispatch/src/case/Table.vue +++ b/src/dispatch/static/dispatch/src/case/Table.vue @@ -182,7 +182,7 @@ const headers = [ { title: "Severity", value: "case_severity.name", sortable: true }, { title: "Priority", value: "case_priority.name", sortable: true }, { title: "Project", value: "project.name", sortable: true }, - { title: "Assignee", value: "assignee", sortable: true }, + { title: "Assignee", value: "assignee.email", sortable: false }, { title: "Reported At", value: "reported_at", sortable: true }, { title: "Closed At", value: "closed_at", sortable: true }, { title: "", key: "data-table-actions", sortable: false, align: "end" },