-
Notifications
You must be signed in to change notification settings - Fork 3
Bugfix/ab#31590 notificationsetting js sonar #1925
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Refactors the Notifications settings JS to address maintainability/complexity concerns (Sonar) while preserving existing notification settings and template-management behavior.
Changes:
- Reworks initialization to use a single
$(function(){ ... })entrypoint and organizes settings-form change tracking. - Extracts many previously-nested functions (template CRUD, editor setup, card event handlers) into standalone helpers to reduce cyclomatic complexity.
- Rebuilds template card rendering via
generateCardHtml()and centralized handler wiring (setupCardEventHandlers).
Comments suppressed due to low confidence (1)
applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Web/Views/Settings/NotificationsSettingGroup/Default.js:242
- Template fields are interpolated into attribute values (
value="${...}") without escaping. Ifname/sendFrom/subjectcontain quotes or markup from the API, this can break the attribute context and enable XSS. Use DOM APIs to set input values (e.g.,.val(...)) or escape attribute values before building the HTML string.
<label class="form-label">Template Name</label>
<input type="text" class="form-control form-input" name="templateName" value="${data?.name || ''}" ${disabled} required>
</div>
<div class="mb-3">
<label class="form-label">Send From</label>
<input type="text" class="form-control form-input" name="sendFrom" value="${data?.sendFrom || ''}" ${disabled} required>
</div>
<div class="mb-3">
<label class="form-label">Subject</label>
<input type="text" class="form-control form-input" name="subject" value="${data?.subject || ''}" ${disabled} required>
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
...otifications/src/Unity.Notifications.Web/Views/Settings/NotificationsSettingGroup/Default.js
Outdated
Show resolved
Hide resolved
...otifications/src/Unity.Notifications.Web/Views/Settings/NotificationsSettingGroup/Default.js
Outdated
Show resolved
Hide resolved
...otifications/src/Unity.Notifications.Web/Views/Settings/NotificationsSettingGroup/Default.js
Show resolved
Hide resolved
...otifications/src/Unity.Notifications.Web/Views/Settings/NotificationsSettingGroup/Default.js
Outdated
Show resolved
Hide resolved
Co-authored-by: Copilot <[email protected]>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 1 out of 1 changed files in this pull request and generated 1 comment.
Comments suppressed due to low confidence (1)
applications/Unity.GrantManager/modules/Unity.Notifications/src/Unity.Notifications.Web/Views/Settings/NotificationsSettingGroup/Default.js:243
- Template fields from the server (
data.name,data.sendFrom,data.subject, etc.) are interpolated directly into HTML (including attribute values) without escaping. If these values can be user-controlled, this enables stored XSS / HTML injection. Use an escaping helper for text/attribute contexts or build the DOM with jQuery and set values via.text()/.val()instead of string concatenation.
<div class="card mb-3 shadow-sm" id="${elementIds.wrapperId}" data-id="${cardDataId}">
<div class="card-header d-flex justify-content-between align-items-center">
<strong class="template-title">${data?.name || 'Untitled Template'}</strong>
<div class="d-flex align-items-center gap-3">
<div class="text-muted small text-end me-3">
<div>Type<br /><span class="fw-normal">${displayInfo.type}</span></div>
</div>
<div class="text-muted small text-end me-3">
<div>Last Edited<br /><span class="fw-normal">${displayInfo.lastEdited}</span></div>
</div>
<button class="btn btn-sm btn-link text-decoration-none" type="button"
data-bs-toggle="collapse" data-bs-target="#${elementIds.cardId}" aria-expanded="false"
aria-controls="${elementIds.cardId}">
<i class="unt-icon-sm fa-solid fa-chevron-down"></i>
</button>
</div>
</div>
<div class="collapse" id="${elementIds.cardId}">
<div class="card-body">
<form id="${elementIds.formId}">
<div class="mb-3">
<label class="form-label">Template Name</label>
<input type="text" class="form-control form-input" name="templateName" value="${data?.name || ''}" ${disabled} required>
</div>
<div class="mb-3">
<label class="form-label">Send From</label>
<input type="text" class="form-control form-input" name="sendFrom" value="${data?.sendFrom || ''}" ${disabled} required>
</div>
<div class="mb-3">
<label class="form-label">Subject</label>
<input type="text" class="form-control form-input" name="subject" value="${data?.subject || ''}" ${disabled} required>
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| $(`#${formId} input[name="templateName"]`).on('input', function () { | ||
| const templateInput = $(this); | ||
| const newTitle = templateInput.val().trim() || 'Untitled Template'; | ||
| $(`#${wrapperId} .template-title`).text(newTitle); | ||
|
|
||
| checkTemplateNameUnique(newTitle, id, function (isUnique) { | ||
| toggleTemplateNameValidation(templateInput, formId, isUnique); | ||
| }); |
Copilot
AI
Jan 20, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
setupTemplateNameValidation triggers an AJAX uniqueness check on every input event (each keystroke). This can generate a large number of requests and cause UI flicker/out-of-order results. Consider debouncing the call (e.g., 300–500ms) and/or aborting the previous pending request before issuing a new one.
| $(`#${formId} input[name="templateName"]`).on('input', function () { | |
| const templateInput = $(this); | |
| const newTitle = templateInput.val().trim() || 'Untitled Template'; | |
| $(`#${wrapperId} .template-title`).text(newTitle); | |
| checkTemplateNameUnique(newTitle, id, function (isUnique) { | |
| toggleTemplateNameValidation(templateInput, formId, isUnique); | |
| }); | |
| const $templateInput = $(`#${formId} input[name="templateName"]`); | |
| let debounceTimer = null; | |
| let lastRequestedName = null; | |
| $templateInput.on('input', function () { | |
| const templateInput = $(this); | |
| const newTitle = templateInput.val().trim() || 'Untitled Template'; | |
| $(`#${wrapperId} .template-title`).text(newTitle); | |
| // Debounce the uniqueness check to avoid excessive AJAX calls. | |
| if (debounceTimer) { | |
| clearTimeout(debounceTimer); | |
| } | |
| debounceTimer = setTimeout(function () { | |
| const nameForRequest = templateInput.val().trim() || 'Untitled Template'; | |
| lastRequestedName = nameForRequest; | |
| checkTemplateNameUnique(nameForRequest, id, function (isUnique) { | |
| // Ignore responses for stale values to prevent out-of-order UI updates. | |
| if (nameForRequest !== lastRequestedName) { | |
| return; | |
| } | |
| toggleTemplateNameValidation(templateInput, formId, isUnique); | |
| }); | |
| }, 300); |
No description provided.