Skip to content

NMS-19711: POC for combining Password Gateway, User static and user info modals#8462

Open
mershad-manesh wants to merge 6 commits into
developfrom
mem/ui_tweak
Open

NMS-19711: POC for combining Password Gateway, User static and user info modals#8462
mershad-manesh wants to merge 6 commits into
developfrom
mem/ui_tweak

Conversation

@mershad-manesh
Copy link
Copy Markdown
Contributor

Side note, if you want to reset the notice or the product update steps use the following commands.

> curl -s -u admin:admin -X POST 'http://localhost:8980/opennms/rest/datachoices/status' \
  -H 'Content-Type: application/json' \
  -d '{"initialNoticeAcknowledged": false}'
> curl -s -u admin:admin -X POST 'http://localhost:8980/opennms/rest/datachoices/productupdate/status' \
  -H 'Content-Type: application/json' \
  -d '{"optedIn": false, "noticeAcknowledged": false}'

All Contributors

External References

Copy link
Copy Markdown
Contributor

@synqotik synqotik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added some comments. I still need to look at the Rest API and Vue part more in depth, but things are initial things to fix. Also could be some differences if you target foundation-2025.

</service-properties>
</service>

<bean id="modalInjector" class="org.opennms.features.datachoices.web.internal.ModalInjector">
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we remove this, then we may also want to remove that datachoices ModalInjector, and also features/datachoices/src/main/resources/web/product-update-enrollment.ftl.html as well.

Though see below, we need some of the logic that's in ModalInjector, may need to move it to OpenNMSAuthSuccessHandler.

<intercept-url pattern="/api/v2/geocoding/**" method="POST" access="ROLE_REST,ROLE_ADMIN" />
<intercept-url pattern="/api/v2/geocoding/**" method="DELETE" access="ROLE_REST,ROLE_ADMIN" />
<intercept-url pattern="/api/v2/geocoding/**" method="PUT" access="ROLE_REST,ROLE_ADMIN" />

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These for snmp-config should not be removed!

Also may need similar for the new AccountRestService with ROLE_ADMIN.

<intercept-url pattern="/rest/scv/**" method="PUT" access="ROLE_ADMIN" />

<!-- Allow certain actions for the ROLE_USER role -->

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably leave previous spacing.


// check for admin/admin
boolean defaultAdminLogin = isDefaultAdminLogin(request.getParameter("j_username"), request.getParameter("j_password"));
boolean requiresWizard = false;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need to handle opennms.productUpdateEnrollment.show and opennms.userDataCollection.show properties, which user can set to false if they do not want to see those.

Or else if we decide not to allow user to disable, then remove those properties and also may need to update some documentation.

More importantly, we need some of the logic from ModalInjector. This uses datachoices StateManager to see if user already opted in/out, already saw the Usage Stats and Product Enrollment notices. We need to show the Wizard if those need to be shown, even if user didn't use the admin/admin password.

If we determine here that none of the 3 things need to be shown, then we don't redirect to the Vue wizard.

<intercept-url pattern="/rest/foreignSources/**" access="ROLE_PROVISION,ROLE_REST,ROLE_ADMIN"/>
<intercept-url pattern="/rest/requisitions/**" access="ROLE_PROVISION,ROLE_REST,ROLE_ADMIN"/>

<!--
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't remove this comment, at least not in develop.

@@ -1,14 +1,6 @@
<template>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leave this file as it was, it's a fallback to display wording if user navigates to a URL that doesn't exist.

@@ -1,25 +1,3 @@
///
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't remove the license comment.

@synqotik
Copy link
Copy Markdown
Contributor

Should also discuss re the password gate functionality, which checks for admin/admin password on every login, not just the initial one. Do we want to keep that or not, or keep it and move it to this wizard, etc.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

POC to consolidate first-sign-in UX (default password change, usage statistics notice, and product update/community signup) into a single Vue-based WelcomeModal wizard, and to start shifting legacy JSP modal behavior into the Vue UI.

Changes:

  • Add a new Vue WelcomeModal wizard and App-level logic to decide which steps to show based on session/account and /rest/datachoices state.
  • Add UI service methods/types for product update enrollment + usage notice acknowledgment, and a new accountService for password-change operations.
  • Add v2 REST endpoints for account/password operations and update Spring Security login success handling to route default admin/admin logins into the Vue wizard; remove the legacy DataChoices ModalInjector.

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
ui/src/types/usageStatistics.d.ts Adds types for product-update enrollment status and submission form data.
ui/src/services/usageStatisticsService.ts Adds REST calls to acknowledge usage notice and manage product-update enrollment.
ui/src/services/index.ts Re-exports new usage-statistics and account service methods via the central API facade.
ui/src/services/accountService.ts New v2 client wrapper for password-change flow and “dismiss prompt” behavior.
ui/src/main/App.vue Adds WelcomeModal mount and first-sign-in step discovery + dashboard redirect behavior.
ui/src/components/WelcomeModal/WelcomeModal.vue New multi-step wizard UI for change-password, usage notice, and community signup.
opennms-webapp/src/main/webapp/WEB-INF/applicationContext-spring-security.xml Configures wizardUrl for the authentication success handler.
opennms-webapp-rest/src/main/java/org/opennms/web/rest/v2/api/AccountRestService.java Defines new v2 Account REST API contract (requires-password-change + change password).
opennms-webapp-rest/src/main/java/org/opennms/web/rest/v2/AccountRestServiceImpl.java Implements server-side session flag read/clear and password change logic.
features/springframework-security/src/main/java/org/opennms/web/springframework/security/OpenNMSAuthSuccessHandler.java Sets a session flag for default admin/admin logins and redirects to the Vue wizard URL.
features/datachoices/src/main/resources/OSGI-INF/blueprint/blueprint.xml Removes the legacy DataChoices ModalInjector HTML injection registration.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread ui/src/main/App.vue Outdated
@@ -121,15 +121,6 @@
</service-properties>
</service>

protected final Logger logger = LoggerFactory.getLogger(OpenNMSAuthSuccessHandler.class);
private final RequestCache requestCache = new HttpSessionRequestCache();

// URL of the Vue wizard app — used when any first-sign-in wizard step needs to be shown.
Comment on lines +49 to +53
@Component("accountRestService")
@SuppressWarnings("java:S2068")
public class AccountRestServiceImpl implements AccountRestService {

// Must match OpenNMSAuthSuccessHandler.REQUIRES_PASSWORD_CHANGE_SESSION_ATTR
Comment thread ui/src/components/WelcomeModal/WelcomeModal.vue Outdated
mershad-manesh and others added 3 commits April 17, 2026 16:33
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

POC that consolidates first-sign-in flows (default admin password change, usage statistics notice, and product update enrollment notice) into a single Vue “Welcome” wizard and updates the login success redirect logic to route users into that wizard when any step is pending.

Changes:

  • Adds a new Vue WelcomeModal wizard and wires it into App.vue to run after whoAmI.
  • Introduces new UI service endpoints + types for acknowledging notices and submitting product update enrollment data, plus a new account/password service.
  • Adds backend support for wizard gating (OSGi WizardGateService) and a new v2 account REST API, and updates the auth success handler to redirect to the Vue wizard when needed.

Reviewed changes

Copilot reviewed 14 out of 15 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
ui/src/types/usageStatistics.d.ts Adds Product Update Enrollment types used by the wizard + services.
ui/src/services/usageStatisticsService.ts Adds API calls for acknowledging usage notice and product update enrollment status/submit.
ui/src/services/index.ts Exposes new usage statistics + account service methods on the API facade.
ui/src/services/accountService.ts New UI service for password-change wizard step (v2 /account/*).
ui/src/main/App.vue Displays WelcomeModal and redirects to classic dashboard when no wizard steps apply.
ui/src/components/WelcomeModal/WelcomeModal.vue New multi-step wizard UI for password change, usage notice, and community sign-up.
opennms-webapp/src/main/webapp/WEB-INF/applicationContext-spring-security.xml Configures wizardUrl on the auth success handler.
opennms-webapp-rest/src/main/java/org/opennms/web/rest/v2/api/AccountRestService.java Defines new v2 account endpoints for wizard integration.
opennms-webapp-rest/src/main/java/org/opennms/web/rest/v2/AccountRestServiceImpl.java Implements password change + session flag read/clear logic.
opennms-web-api/src/main/java/org/opennms/web/api/WizardGateService.java New API for determining whether wizard redirect is needed.
features/springframework-security/.../OpenNMSAuthSuccessHandler.java Redirects to Vue wizard when password gate or datachoices notices are pending.
features/datachoices/.../OSGI-INF/blueprint/blueprint.xml Registers WizardGateService provider from datachoices.
features/datachoices/.../WizardGateServiceImpl.java Implements gating logic based on StateManager + roles + feature flags.
features/datachoices/.../DataChoiceRestServiceImpl.java Adds featureEnabled to product enrollment status response.
features/datachoices/.../ProductUpdateEnrollmentStatusDTO.java Adds featureEnabled field to DTO.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +420 to +423
await API.setProductUpdateEnrollmentStatus(false, true)
} finally {
isBusy.value = false
closeModal()
Comment on lines +372 to +382
await API.acknowledgeUsageStatisticsNotice()
} finally {
isBusy.value = false
advanceOrClose()
}
}

const onLearnMore = async () => {
isBusy.value = true
try {
await API.acknowledgeUsageStatisticsNotice()
Comment on lines +126 to +130
private static boolean isProductEnrollmentEnabled() {
return java.util.stream.Stream.of("opennms.productUpdateEnrollment.show", "opennms.userDataCollection.show")
.map(key -> System.getProperty(key, "true"))
.noneMatch(val -> val.equalsIgnoreCase("false"));
}
Comment on lines +372 to +387
await API.acknowledgeUsageStatisticsNotice()
} finally {
isBusy.value = false
advanceOrClose()
}
}

const onLearnMore = async () => {
isBusy.value = true
try {
await API.acknowledgeUsageStatisticsNotice()
} finally {
isBusy.value = false
}
router.push('/usage-statistics')
closeModal()
Comment on lines +45 to +49
@Override
public boolean hasUnacknowledgedNotices(boolean isAdmin, boolean isAdminOrRest) {
try {
if (isAdmin && needsUsageStatisticsNotice()) {
return true;
Comment on lines +81 to +85
@Override
public Response changePassword(HttpServletRequest request, SecurityContext securityContext, String body) {
final String username = securityContext.getUserPrincipal().getName();

final JSONObject json;
Comment on lines +253 to +257
const steps = computed<WizardStep[]>(() => {
const result: WizardStep[] = []
if (props.showChangePassword) result.push({ id: 'change-password', title: 'Change Password' })
if (props.showUsageStatistics) result.push({ id: 'usage-statistics', title: 'Usage Statistics' })
if (props.showCommunitySignup) result.push({ id: 'community-signup', title: 'Stay Connected' })
throw new Error('Submit failed')
}

await API.setProductUpdateEnrollmentStatus(true, true)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants