<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: hediyeh kianmehr</title>
    <description>The latest articles on DEV Community by hediyeh kianmehr (@hediyeh_kianmehr_45f78137).</description>
    <link>https://dev.to/hediyeh_kianmehr_45f78137</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2880892%2Fc46fa9d7-ab0f-47e1-85af-199c89f636dd.png</url>
      <title>DEV Community: hediyeh kianmehr</title>
      <link>https://dev.to/hediyeh_kianmehr_45f78137</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hediyeh_kianmehr_45f78137"/>
    <language>en</language>
    <item>
      <title>TrustedCloud User &amp; Dashboard Guide</title>
      <dc:creator>hediyeh kianmehr</dc:creator>
      <pubDate>Sun, 02 Nov 2025 07:25:57 +0000</pubDate>
      <link>https://dev.to/hediyeh_kianmehr_45f78137/trustedcloud-3dc7</link>
      <guid>https://dev.to/hediyeh_kianmehr_45f78137/trustedcloud-3dc7</guid>
      <description>&lt;p&gt;&lt;strong&gt;Table of Contents&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Introduction&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Overview&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Authentication Interface&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;1. UIBuilder Frontend Initialization&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;2. Cookie-Based Session Check&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;3. Token Validation and Routing Flow&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;4. Authentication Flow Integration&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;4.1 Sign Up Flow&lt;/li&gt;
&lt;li&gt;4.2 Sign In Flow&lt;/li&gt;
&lt;li&gt;4.3 Reset Password Flow&lt;/li&gt;
&lt;li&gt;4.4 sendResetCode Flow&lt;/li&gt;
&lt;li&gt;4.5 setNewPassword Flow&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Dashboard Interface&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;1. UIBuilder Frontend Initialization&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;2. Cookie-Based Session Check&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;3. Token Validation and Routing Flow&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;4. Authentication Flow Integration&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;4.1.1 getDashboard (Applicant) Flow&lt;/li&gt;
&lt;li&gt;4.1.2 getDashboard (Applicant and Auditor) Flow&lt;/li&gt;
&lt;li&gt;4.1.3 getDashboard (Applicant and Approver) Flow&lt;/li&gt;
&lt;li&gt;4.1.4 getDashboard (Admin) Flow&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;4.2 editCompanyDetails Flow&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;4.3 archiveRequest Flow&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;4.4 editProfile Flow&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;4.5 auditRequest Flow&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;4.7 createRequest Flow&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;

&lt;p&gt; UIBuilder Authentication Flow Overview&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;signup&lt;/li&gt;
&lt;li&gt;login&lt;/li&gt;
&lt;li&gt;sendResetCode&lt;/li&gt;
&lt;li&gt;resendResetPassword&lt;/li&gt;
&lt;li&gt;setNewPassword&lt;/li&gt;
&lt;li&gt;resetPassword&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt; UIBuilder Dashboard Flow Overview&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;getDashboard&lt;/li&gt;
&lt;li&gt;editCompanyDetails&lt;/li&gt;
&lt;li&gt;archiveRequest&lt;/li&gt;
&lt;li&gt;editProfile&lt;/li&gt;
&lt;li&gt;auditRequest&lt;/li&gt;
&lt;li&gt;approveRequest&lt;/li&gt;
&lt;li&gt;createRequest&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Collections Overview&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PasswordResets Collection&lt;/li&gt;
&lt;li&gt;Requests Collection&lt;/li&gt;
&lt;li&gt;Tokens Collection&lt;/li&gt;
&lt;li&gt;Users Collection&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Request and Response&lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;




&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;TrustedCloud&lt;/strong&gt; is a secure platform that allows users to easily &lt;strong&gt;sign up&lt;/strong&gt;, &lt;strong&gt;log in&lt;/strong&gt;, and manage their onboarding requests through personalized dashboards.&lt;/p&gt;

&lt;p&gt;When users create an account using &lt;strong&gt;Sign Up&lt;/strong&gt; or access an existing one through &lt;strong&gt;Sign In&lt;/strong&gt;, they are automatically taken to a dashboard that matches their role and responsibilities in the system.&lt;/p&gt;

&lt;p&gt;After logging in, users are directed to one of four dashboards:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Admin Dashboard&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Applicant &amp;amp; Approver Dashboard&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Applicant &amp;amp; Auditor Dashboard&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Applicant Dashboard&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Note:&lt;br&gt;
New users are given the &lt;strong&gt;Applicant&lt;/strong&gt; role by default when they first register. Later, administrators can update their roles and provide additional permissions if needed.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Applicants can submit &lt;strong&gt;onboarding requests&lt;/strong&gt; through the platform.&lt;br&gt;
&lt;strong&gt;Approvers&lt;/strong&gt; and &lt;strong&gt;Auditors&lt;/strong&gt; then review these requests — they can &lt;strong&gt;approve&lt;/strong&gt; or &lt;strong&gt;reject&lt;/strong&gt; them and add comments or feedback to help clarify their decisions.&lt;/p&gt;
&lt;h3&gt;
  
  
  Role-Based Dashboard Access
&lt;/h3&gt;
&lt;h4&gt;
  
  
  1. Admin Dashboard
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Can view requests in: &lt;code&gt;Pending, Audited, Approved, Rejected&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Can access the list of all approved requests that exist in the Service List&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  2. Approver Dashboard
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Can view requests in: &lt;code&gt;Audited, Approved&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;Can see only rejected requests that were rejected by Approvers, not those rejected by Auditors&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  3. Auditor Dashboard
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Can view requests in: &lt;code&gt;Pending, Audited, Rejected&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  4. Applicant Dashboard
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Can view requests in: Pending, Audited, Approved, Rejected&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;h1&gt;
  
  
  Overview
&lt;/h1&gt;

&lt;p&gt;The &lt;strong&gt;TrustedCloud&lt;/strong&gt; platform uses two independent &lt;strong&gt;UIBuilder&lt;/strong&gt; frontends, each connected to its own Node-RED backend. Both frontends communicate through &lt;strong&gt;WebSocket&lt;/strong&gt; channels for secure, real-time interaction between the browser and their respective Node-RED instances.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UIBuilder 1&lt;/strong&gt; – &lt;code&gt;Authentication Interface&lt;/code&gt;:&lt;br&gt;
handles user &lt;strong&gt;authentication&lt;/strong&gt; flows — including &lt;code&gt;Sign In, Sign Up, and Password Reset&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UIBuilder 2&lt;/strong&gt; – &lt;code&gt;Dashboard Interface&lt;/code&gt;:&lt;br&gt;
manages &lt;strong&gt;authenticated&lt;/strong&gt;, &lt;strong&gt;role-based operations&lt;/strong&gt; such as &lt;code&gt;getDashboard&lt;/code&gt;, &lt;code&gt;editProfile&lt;/code&gt;, &lt;code&gt;archiveRequest&lt;/code&gt;, and others.&lt;/p&gt;

&lt;p&gt;Although the backends are separate, both follow the same &lt;strong&gt;token-based authentication&lt;/strong&gt; and &lt;strong&gt;authorization&lt;/strong&gt; structure, ensuring consistent session validation and user experience across the system.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Feature&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Sign-In UIBuilder&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Dashboard UIBuilder&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Purpose&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;User authentication and registration&lt;/td&gt;
&lt;td&gt;Role-based request management and dashboards&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Token Handling&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Generates and stores JWT in MongoDB&lt;/td&gt;
&lt;td&gt;Validates and consumes JWT for session restoration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Communication&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;WebSocket (uibuilder)&lt;/td&gt;
&lt;td&gt;WebSocket (uibuilder)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Key Identifiers&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;clientId&lt;/code&gt;, &lt;code&gt;socketId&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;clientId&lt;/code&gt;, &lt;code&gt;userToken&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Backend Validation&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Token existence, expiry, email/password match&lt;/td&gt;
&lt;td&gt;Token validity, role extraction, route handling&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h1&gt;
  
  
  Authentication Interface
&lt;/h1&gt;
&lt;h1&gt;
  
  
  1. UIBuilder Frontend Initialization
&lt;/h1&gt;

&lt;p&gt;When the user opens any &lt;strong&gt;authentication page&lt;/strong&gt; — such as &lt;strong&gt;signup&lt;/strong&gt;, &lt;strong&gt;login&lt;/strong&gt;, &lt;strong&gt;sendResetCode&lt;/strong&gt;, &lt;strong&gt;resendResetPassword&lt;/strong&gt;, &lt;strong&gt;setNewPassword&lt;/strong&gt;, or &lt;strong&gt;resetPassword&lt;/strong&gt; — the Vue app starts the uibuilder connection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uibuilder.start();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This initializes a &lt;strong&gt;WebSocket&lt;/strong&gt; connection between the browser and Node-RED.&lt;br&gt;
Each client is automatically assigned a &lt;strong&gt;unique clientId&lt;/strong&gt; (stored as a uibuilder-client-id cookie), allowing Node-RED to respond directly to the same active user session.&lt;/p&gt;


&lt;h2&gt;
  
  
  2. Cookie-Based Session Check
&lt;/h2&gt;

&lt;p&gt;On page load &lt;code&gt;(mounted() hook)&lt;/code&gt;, the app checks whether a userToken cookie already exists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (this.getCookie("userToken")) {
  uibuilder.send({
    auth: {
      userToken: this.getCookie("userToken"),
      clientId: this.getCookie("uibuilder-client-id"),
    },
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Purpose:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If the &lt;strong&gt;token exists&lt;/strong&gt;, the backend verifies it and restores the user’s session automatically — enabling persistent login.&lt;/p&gt;

&lt;p&gt;If no token is found, Node-RED treats it as a &lt;strong&gt;new session&lt;/strong&gt;, and the user continues with normal authentication flow (e.g., login or signup).&lt;/p&gt;




&lt;h1&gt;
  
  
  3. Token Validation and Routing Flow
&lt;/h1&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;link in 1&lt;/td&gt;
&lt;td&gt;link in&lt;/td&gt;
&lt;td&gt;Receives incoming messages from multiple linked flows and passes them to the &lt;code&gt;uibuilder&lt;/code&gt; node.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;uibuilder&lt;/td&gt;
&lt;td&gt;uibuilder&lt;/td&gt;
&lt;td&gt;Handles WebSocket communication between the frontend and Node-RED backend on the &lt;code&gt;/signin&lt;/code&gt; URL.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ui output&lt;/td&gt;
&lt;td&gt;debug&lt;/td&gt;
&lt;td&gt;Displays the full message from the frontend in the debug sidebar for inspection.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Check Token&lt;/td&gt;
&lt;td&gt;function&lt;/td&gt;
&lt;td&gt;Checks if the incoming message contains a valid &lt;code&gt;userToken&lt;/code&gt;. Sets &lt;code&gt;msg.payload&lt;/code&gt; to &lt;code&gt;hasToken&lt;/code&gt; or &lt;code&gt;hasNotToken&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Token Route&lt;/td&gt;
&lt;td&gt;switch&lt;/td&gt;
&lt;td&gt;Routes messages based on token presence: with token → validate token in MongoDB, without token → handle authentication requests.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;check URL&lt;/td&gt;
&lt;td&gt;switch&lt;/td&gt;
&lt;td&gt;Routes authentication requests by &lt;code&gt;auth.type&lt;/code&gt; (e.g., &lt;code&gt;signup&lt;/code&gt;, &lt;code&gt;login&lt;/code&gt;, &lt;code&gt;resetPassword&lt;/code&gt;, &lt;code&gt;sendResetCode&lt;/code&gt;, &lt;code&gt;setNewPassword&lt;/code&gt;, &lt;code&gt;resendResetPassword&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Find Token&lt;/td&gt;
&lt;td&gt;function&lt;/td&gt;
&lt;td&gt;Extracts &lt;code&gt;userToken&lt;/code&gt; from the message and prepares a MongoDB query to find it in the &lt;code&gt;Tokens&lt;/code&gt; collection.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Find Token Record&lt;/td&gt;
&lt;td&gt;mongodb4&lt;/td&gt;
&lt;td&gt;Executes the MongoDB &lt;code&gt;find&lt;/code&gt; operation on the &lt;code&gt;Tokens&lt;/code&gt; collection to locate the token document.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Token Expiration&lt;/td&gt;
&lt;td&gt;function&lt;/td&gt;
&lt;td&gt;Checks if the token exists and whether it’s expired. Returns status as &lt;code&gt;empty&lt;/code&gt;, &lt;code&gt;expired&lt;/code&gt;, or &lt;code&gt;valid&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;status&lt;/td&gt;
&lt;td&gt;switch&lt;/td&gt;
&lt;td&gt;Routes based on token validation result: &lt;code&gt;expired&lt;/code&gt; and &lt;code&gt;empty&lt;/code&gt; → back to frontend; &lt;code&gt;valid&lt;/code&gt; → proceed to redirect.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Redirect&lt;/td&gt;
&lt;td&gt;function&lt;/td&gt;
&lt;td&gt;Constructs a redirect response message indicating that the user is already logged in.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;link out 12&lt;/td&gt;
&lt;td&gt;link out&lt;/td&gt;
&lt;td&gt;Sends output messages (responses) back to the &lt;code&gt;uibuilder&lt;/code&gt; node for frontend delivery.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mongodb4-client&lt;/td&gt;
&lt;td&gt;mongodb4-client&lt;/td&gt;
&lt;td&gt;Defines the MongoDB connection configuration for the &lt;code&gt;hediyehTC&lt;/code&gt; database hosted on DigitalOcean.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h1&gt;
  
  
  4. Authentication Flow Integration
&lt;/h1&gt;

&lt;p&gt;Once token validation is complete, the flow dynamically routes the request based on the &lt;code&gt;auth.type&lt;/code&gt; received from the frontend.&lt;br&gt;
Each &lt;code&gt;auth.type&lt;/code&gt; corresponds to a dedicated backend sub-flow that performs specific MongoDB operations and response handling:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Auth Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;th&gt;Target Collection&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;signup&lt;/td&gt;
&lt;td&gt;Creates a new user record with validated credentials and role.&lt;/td&gt;
&lt;td&gt;Users&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;login&lt;/td&gt;
&lt;td&gt;Authenticates credentials and generates a new &lt;code&gt;userToken&lt;/code&gt;.&lt;/td&gt;
&lt;td&gt;Users / Tokens&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sendResetCode&lt;/td&gt;
&lt;td&gt;Creates a verification code for password recovery.&lt;/td&gt;
&lt;td&gt;PasswordResets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;resendResetPassword&lt;/td&gt;
&lt;td&gt;Regenerates or resends the reset code if expired.&lt;/td&gt;
&lt;td&gt;PasswordResets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;setNewPassword&lt;/td&gt;
&lt;td&gt;Updates the password after verifying reset code.&lt;/td&gt;
&lt;td&gt;Users / PasswordResets&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;resetPassword&lt;/td&gt;
&lt;td&gt;Finalizes password change after verification.&lt;/td&gt;
&lt;td&gt;Users / PasswordResets&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h1&gt;
  
  
  4.1 Sign Up Flow
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;High-level flow:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Frontend (Vue/React)
      ↓ uibuilder.send
Node-RED Flow
      ↓ MongoDB Users Collection
      ↓ uibuilder.onChange (response)
Frontend Redirect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx15tuehwcig973o718t9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx15tuehwcig973o718t9.png" alt=" " width="512" height="522"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the user clicks &lt;code&gt;Sign Up&lt;/code&gt;, this runs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;signupButton() {
    const clientId = uibuilder.get("clientId");
    uibuilder.send({
        auth: {
            clientId: clientId,
            fullName: this.fullName,
            email: this.email,
            password: this.password,
            confirmPassword: this.confirmPassword,
            type: "signup"
        }
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Sample request payload:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "auth": {},
  "clientId": "oD6i_WpIes8pBvWjNXy81",
  "fullName": "hediyeh",
  "email": "h@gmail.com",
  "password": "111111",
  "confirmPassword": "111111",
  "type": "signup",
  "_socketId": "kmN2iMG_VAMQ7WSFAEhJ",
  "topic": "uibuilder",
  "_msgid": "96c8e068f17bef90"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Backend Flow:&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Validate Auth Payload&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Checks payload existence, validates email format, attaches &lt;code&gt;socketId&lt;/code&gt;, prepares original payload.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;User Query&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Queries &lt;code&gt;Users&lt;/code&gt; collection for existing email.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Query Users Collection&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MongoDB&lt;/td&gt;
&lt;td&gt;Executes the email query.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Check Email Availability&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Determines if email exists; sets status &lt;code&gt;failed&lt;/code&gt; or prepares data for insertion.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Evaluate Registration Status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Switch&lt;/td&gt;
&lt;td&gt;Routes flow based on &lt;code&gt;payload.status&lt;/code&gt; (&lt;code&gt;success&lt;/code&gt; or &lt;code&gt;failed&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Get Last User ID&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Fetches highest &lt;code&gt;id&lt;/code&gt; from &lt;code&gt;Users&lt;/code&gt; collection to increment.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Fetch Last User&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MongoDB&lt;/td&gt;
&lt;td&gt;Executes query for last user document.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Generate New User Data&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Hashes password, generates &lt;code&gt;roles&lt;/code&gt;, constructs &lt;code&gt;profile&lt;/code&gt;, prepares &lt;code&gt;insertOne&lt;/code&gt; payload.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Insert New User&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MongoDB&lt;/td&gt;
&lt;td&gt;Inserts new user document into the &lt;code&gt;Users&lt;/code&gt; collection.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Registration Success Response&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Returns success response with redirect URL.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;set warning&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Returns failure response when email exists.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;signin&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Debug&lt;/td&gt;
&lt;td&gt;Logs final response for monitoring.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;ul&gt;
&lt;li&gt;Node-RED receives the signup data.&lt;/li&gt;
&lt;li&gt;Validates if the email already exists.&lt;/li&gt;
&lt;li&gt;Hashes the password before saving to the Users collection.&lt;/li&gt;
&lt;li&gt;Returns a success message with:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "payload": {
    "action": "register",
    "status": "success",
    "URL": "/hediyeh/trustedcloud2"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The frontend receives it and redirects the user to the dashboard.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Sample Responses (uibuilder.onChange)&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Response&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Success&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "action": "register", "status": "success", "message": "You have registered successfully!", "URL": "https://codenxa.leanea.com/hediyeh/signin" }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Failure&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "action": "register", "status": "failed", "message": "Email already exists. Please use a different email." }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;&lt;strong&gt;MongoDB Users Collection Schema&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ObjectId&lt;/td&gt;
&lt;td&gt;Unique document ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;clientId&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Unique client identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fullName&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;User full name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;email&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Unique email&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;password&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Hashed password&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;confirmPassword&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Hashed password (same as password)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;roles&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;array&lt;/td&gt;
&lt;td&gt;Assigned roles (e.g., &lt;code&gt;["Applicant","Auditor"]&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Registration status (&lt;code&gt;not_found&lt;/code&gt;, &lt;code&gt;success&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;profile&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;object&lt;/td&gt;
&lt;td&gt;User profile data (avatar, first/last name, contact info)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;createdAt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Date&lt;/td&gt;
&lt;td&gt;Timestamp of account creation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;updatedAt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Date&lt;/td&gt;
&lt;td&gt;Last update timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Sample document:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "_id": "68f830f9d6c4398ea5f5cbdf",
  "clientId": "GiHBKhnJvqNbA6dYRqWHF",
  "fullName": "David Kim",
  "email": "david.kim@brightwave.co",
  "password": "$2b$10$MiGhJqBXNIJhayVOnqG1C...",
  "roles": ["Applicant","Auditor"],
  "status": "not_found",
  "profile": {
    "firstName": "David",
    "lastName": "Kim",
    "avatarUrl": "data:image/jpeg;base64,..."
  },
  "createdAt": "2025-10-22T01:18:49.129Z",
  "updatedAt": "2025-10-28T02:20:04.260Z"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Security Considerations&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Passwords are hashed using bcrypt before storage.&lt;/li&gt;
&lt;li&gt;Emails must be unique; duplicate entries are rejected.&lt;/li&gt;
&lt;li&gt;The clientId is used to track frontend sessions securely.&lt;/li&gt;
&lt;li&gt;Ensure HTTPS is enforced for all frontend/backend communications.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  4.2 Sign In Flow
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;High-Level Flow:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Frontend (Vue/React)
      ↓ uibuilder.send
Node-RED Flow
      ↓ MongoDB Users &amp;amp; Tokens Collections
      ↓ uibuilder.onChange (response)
Frontend Redirect / Error Handling
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frow5lhkdg83z1vgd0ugh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frow5lhkdg83z1vgd0ugh.png" alt=" " width="467" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frontend Sign In Action&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When the user clicks the &lt;code&gt;Sign In&lt;/code&gt; button, the following function runs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;signinButton() {
    const isEmailValid = this.validateEmail();
    const isPasswordValid = this.validatePassword();

    if (!isEmailValid || !isPasswordValid) {
        return;
    }

    const clientId = uibuilder.get("clientId");
    uibuilder.send({
        auth: {
            clientId: clientId,
            email: this.email,
            password: this.password,
            rememberMe: this.rememberMe,
            type: "login"
        }
    });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Sample Request Payload:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "auth": {},
  "clientId": "oD6i_WpIes8pBvWjNXy81",
  "email": "h@gmail.com",
  "password": "111111",
  "rememberMe": false,
  "type": "login",
  "_socketId": "70nLJLlIrgzsiFLpAEhQ",
  "topic": "uibuilder",
  "_msgid": "2e88832acfbcd402"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Backend Node-RED Flow&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Prepare Auth Data&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Validates &lt;code&gt;auth&lt;/code&gt; payload, ensures &lt;code&gt;email&lt;/code&gt; exists, attaches &lt;code&gt;socketId&lt;/code&gt; and saves original payload&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Prepare Filter for Email Check&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Creates MongoDB query payload to find user by email&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Find User by Email&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MongoDB&lt;/td&gt;
&lt;td&gt;Queries &lt;code&gt;Users&lt;/code&gt; collection for the given email&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Check Email &amp;amp; Password&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Compares entered password with stored hashed password; generates JWT if successful&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Check Login Result&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Switch&lt;/td&gt;
&lt;td&gt;Routes flow based on &lt;code&gt;payload.status&lt;/code&gt; (&lt;code&gt;success&lt;/code&gt; or &lt;code&gt;invalidCredentials&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Sign JWT&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;JWT Sign&lt;/td&gt;
&lt;td&gt;Signs a JWT token using &lt;code&gt;HS256&lt;/code&gt; with 1-hour expiration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Save JWT to DB&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Prepares messages for both MongoDB &lt;code&gt;Tokens&lt;/code&gt; collection insert and frontend response&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Prepare Filter for DB Insert&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Inserts token into &lt;code&gt;Tokens&lt;/code&gt; collection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;set warning&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Returns failure response when credentials are invalid&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;login&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Debug&lt;/td&gt;
&lt;td&gt;Logs final response for monitoring&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Backend Flow Summary&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Node-RED receives login data from the frontend via &lt;code&gt;uibuilder.send&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Validates payload and ensures &lt;code&gt;email&lt;/code&gt; is provided.&lt;/li&gt;
&lt;li&gt;Queries the &lt;code&gt;Users&lt;/code&gt; collection for the given email.&lt;/li&gt;
&lt;li&gt;If the email exists, compares the entered password against the stored hashed password using &lt;code&gt;bcrypt&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If the password matches:&lt;/li&gt;
&lt;li&gt;Generates a &lt;strong&gt;JWT&lt;/strong&gt; token.&lt;/li&gt;
&lt;li&gt;Prepares a &lt;code&gt;profile&lt;/code&gt; object including &lt;code&gt;userId&lt;/code&gt;, &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;roles&lt;/code&gt;, and &lt;code&gt;fullName&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Sends response to frontend and inserts token into Tokens collection.&lt;/li&gt;
&lt;li&gt;If the &lt;code&gt;email&lt;/code&gt; or &lt;code&gt;password&lt;/code&gt; is invalid, returns a failure message with status &lt;strong&gt;invalidCredentials&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Sample Responses (uibuilder.onChange)&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Response&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Invalid Email&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "action": "login", "status": "invalidCredentials", "message": "Email not found." }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Invalid Password&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "action": "login", "status": "invalidCredentials", "message": "Password does not match." }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Success&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "action": "login", "status": "success", "message": "Logged In Successfully" }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;&lt;strong&gt;Security Considerations&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Passwords are stored as bcrypt hashes.&lt;/li&gt;
&lt;li&gt;JWT tokens are signed with a secret key and expire after &lt;strong&gt;1&lt;/strong&gt; hour.&lt;/li&gt;
&lt;li&gt;Tokens are saved in the Tokens collection for session tracking.&lt;/li&gt;
&lt;li&gt;Always use &lt;strong&gt;HTTPS&lt;/strong&gt; for communication between frontend and Node-RED.&lt;/li&gt;
&lt;li&gt;Ensure JWT tokens are stored securely on the client (&lt;code&gt;cookies with Secure;SameSite=Strict&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;MongoDB Tokens Collection&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ObjectId&lt;/td&gt;
&lt;td&gt;Unique document ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;email&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;User email&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;userId&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;MongoDB user &lt;code&gt;_id&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;number&lt;/td&gt;
&lt;td&gt;Internal user ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;token&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;JWT token&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;createdAt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Date&lt;/td&gt;
&lt;td&gt;Token creation timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;expiresAt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Date&lt;/td&gt;
&lt;td&gt;Token expiration timestamp (1 hour by default)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Sample Document&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "_id": "69024c1bd6c4398ea5f5cd17",
  "email": "david.kim@brightwave.co",
  "userId": "68f830f9d6c4398ea5f5cbdf",
  "id": 1,
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IiJ9...",
  "createdAt": "2025-10-29T17:17:15.326Z",
  "expiresAt": "2025-10-29T18:17:15.326Z"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  4.3 Reset Password Flow
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;High-Level Flow:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[User clicks "Forgot Password"]
        │
        ▼
[Frontend: Sends reset request with email]
        │
        ▼
[Node-RED: Validate Reset Request Input]
        │
        ├── Invalid → Stop flow (missing auth/email)
        └── Valid → Attach socketId &amp;amp; forward for email verification
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4vtakorlctlorcumtkb8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4vtakorlctlorcumtkb8.png" alt=" " width="416" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frontend Reset Password Action&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;When a user submits their email in the &lt;code&gt;Forgot Password&lt;/code&gt; form, the frontend sends a request via uibuilder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resetPasswordRequest() {
  const clientId = uibuilder.get("clientId");
  uibuilder.send({
    auth: {
      email: this.email,
      type: "resetPassword"
    },
    _socketId: clientId
  });
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Sample Request Payload:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "auth": {
    "email": "user@example.com",
    "type": "resetPassword"
  },
  "_socketId": "TtK9mNkl_2Fh8Wx2K3DdW"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Backend Node-RED Flow&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node Name&lt;/th&gt;
&lt;th&gt;What It Does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;resetPassword(in)&lt;/td&gt;
&lt;td&gt;Entry point for the reset password flow; receives incoming reset requests.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Validate Reset Request Input&lt;/td&gt;
&lt;td&gt;Checks that &lt;code&gt;msg.auth&lt;/code&gt; and &lt;code&gt;msg.auth.email&lt;/code&gt; exist, attaches &lt;code&gt;socketId&lt;/code&gt;, saves original payload.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Users Collection&lt;/td&gt;
&lt;td&gt;Prepares MongoDB &lt;code&gt;find&lt;/code&gt; operation on the &lt;code&gt;Users&lt;/code&gt; collection using the email.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Find User by Email&lt;/td&gt;
&lt;td&gt;Queries the MongoDB &lt;code&gt;Users&lt;/code&gt; collection to check if the email exists.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Validate User Existence&lt;/td&gt;
&lt;td&gt;Checks the query result, sets &lt;code&gt;msg.payload.status&lt;/code&gt; to &lt;code&gt;success&lt;/code&gt; or &lt;code&gt;invalidEmail&lt;/code&gt;, prepares user data.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Branch by User Status&lt;/td&gt;
&lt;td&gt;Routes the flow based on user existence (&lt;code&gt;success&lt;/code&gt; → generate code, &lt;code&gt;invalidEmail&lt;/code&gt; → failure response).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Generate and Store Reset Code&lt;/td&gt;
&lt;td&gt;Generates a 6-digit reset code, inserts a record into &lt;code&gt;PasswordResets&lt;/code&gt; collection, sets expiration.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Insert Reset Code Record&lt;/td&gt;
&lt;td&gt;Inserts the reset code record into MongoDB.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Compose Reset Email Message&lt;/td&gt;
&lt;td&gt;Prepares the email content with the reset code to be sent to the user.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prepare Success Response&lt;/td&gt;
&lt;td&gt;Prepares the response message indicating that the reset code was sent.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prepare Failure Response&lt;/td&gt;
&lt;td&gt;Prepares the response message indicating the email was not found.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;validEmail (debug)&lt;/td&gt;
&lt;td&gt;Debug node to inspect successful reset responses in the sidebar.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;invalidEmail (debug)&lt;/td&gt;
&lt;td&gt;Debug node to inspect failed reset responses in the sidebar.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Backend Flow Summary&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Validate Reset Request Input&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Receives the reset request from the frontend via &lt;code&gt;uibuilder.send&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Validates that the &lt;code&gt;auth&lt;/code&gt; object and &lt;code&gt;email&lt;/code&gt; field exist.&lt;/li&gt;
&lt;li&gt;Attaches &lt;code&gt;socketId&lt;/code&gt; and preserves the original payload for tracking.&lt;/li&gt;
&lt;li&gt;Stops the flow if validation fails.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Prepare Filter for Email Check&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Constructs a MongoDB query: &lt;code&gt;{ email: msg.auth.email }&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Prepares the message for the next MongoDB node.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Find User by Email&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Queries the &lt;code&gt;Users&lt;/code&gt; collection in MongoDB.&lt;/li&gt;
&lt;li&gt;Returns an array (&lt;code&gt;msg.payload&lt;/code&gt;) containing matching user(s).&lt;/li&gt;
&lt;li&gt;If no user is found → triggers a generic response to prevent enumeration attacks.&lt;/li&gt;
&lt;li&gt;If a user exists → forwards data to generate a reset token.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Generate Reset Token &amp;amp; Save (Next Step in Flow)&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates a unique 6-digit code or UUID token.&lt;/li&gt;
&lt;li&gt;Stores token in &lt;code&gt;ResetCodes&lt;/code&gt; collection with:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;userId&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;email&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;createdAt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;expiresAt&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;used: false&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Prepares payload for sending email.&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Send Reset Code / Email&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sends an email to the user with the reset code.&lt;/li&gt;
&lt;li&gt;Returns a generic success response to the frontend.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Sample Responses (uibuilder.onChange)&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;status&lt;/th&gt;
&lt;th&gt;Response&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Valid request&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "status": "ok", "message": "Email validation initiated." }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Missing email&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "status": "error", "message": "Email is required." }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;MongoDB PasswordResets Collection&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ObjectId&lt;/td&gt;
&lt;td&gt;Unique document ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;email&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;User email&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;userId&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;MongoDB &lt;code&gt;_id&lt;/code&gt; of the user&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;code&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;One-time 6-digit reset code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;used&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;Whether code has been used (default &lt;code&gt;false&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;createdAt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Date&lt;/td&gt;
&lt;td&gt;Timestamp of token creation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;expiresAt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Date&lt;/td&gt;
&lt;td&gt;Expiration timestamp (e.g., 2 minutes)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Sample Document&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "_id": "69078db8d6c4398ea5f5cd54",
  "code": "994015",
  "email": "li@gmail.com",
  "userId": "69076591d6c4398ea5f5cd48",
  "id": 15,
  "createdAt": "2025-11-02T16:58:32.299+00:00",
  "expiresAt": "2025-11-02T17:00:32.299+00:00",
  "used": false
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  4.4 sendResetCode Flow
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;High-Level Flow:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User clicks "Forgot Password" → Enter email
             ↓
       Vue.js Frontend
             ↓ uibuilder.send
      Node-RED Backend Flow
             ↓ MongoDB Users &amp;amp; ResetCodes
             ↓ uibuilder.onChange (response)
       Frontend Shows Verification Code Input

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F31pjdmmxkrtpr6anw1fo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F31pjdmmxkrtpr6anw1fo.png" alt=" " width="466" height="467"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frontend Reset Password Action&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;handleDigitInput&lt;/code&gt; method&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;handleDigitInput(index, event) {
    const value = event.target.value;
    if (value &amp;amp;&amp;amp; index &amp;lt; 5) {
        this.verificationInputs[index + 1].focus();
    } else if (value &amp;amp;&amp;amp; index === 5) {
        const allFilled = this.verificationDigits.every(digit =&amp;gt; digit !== '');
        if (allFilled) {
            const code = this.verificationDigits.join('');
            uibuilder.send({
                auth: {
                    type: "sendResetCode",
                    email: this.resetEmail,
                    code: code
                }
            });
            this.showVerificationSuccess = true;
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;verificationDigits.join('')&lt;/code&gt; ensures the code is concatenated properly.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;auth&lt;/code&gt; payload structure matches your sample request payload.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;resendCode&lt;/code&gt; method&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   resendCode() {


            this.verificationDigits = ['', '', '', '', '', ''];
            this.startTimer();

            uibuilder.send({
                auth:{
                    email: this.resetEmail,
                    type: "resendResetPassword",
                }
            })
        },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Sample Request Payload&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "auth": {},
  "type": "sendResetCode",
  "code": "373600",
  "email": "h@gmail.com",
  "_socketId": "TQQZkMEJW3yr8AXbAEhi",
  "topic": "uibuilder",
  "_msgid": "563ae2fa2bd25a81"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Backend Node-RED Flow&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Responsibility / Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sendResetCode(in)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Link In&lt;/td&gt;
&lt;td&gt;Entry point for the send reset code flow; triggers when a reset code request comes in.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Validate Auth &amp;amp; Prepare Payload&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Validates that &lt;code&gt;auth&lt;/code&gt; object and &lt;code&gt;email&lt;/code&gt; exist; attaches &lt;code&gt;socketId&lt;/code&gt; and stores original payload.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Prepare DB Query&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Prepares a MongoDB query to check if a reset code record exists for the email.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Find Password Reset Record&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MongoDB4&lt;/td&gt;
&lt;td&gt;Queries the &lt;code&gt;PasswordResets&lt;/code&gt; collection in MongoDB. Returns matching records as an array.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Check Reset Record Existence&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Checks if a record exists; sets status to &lt;code&gt;success&lt;/code&gt; if found, &lt;code&gt;invalidEmail&lt;/code&gt; if not. Prepares &lt;code&gt;_data&lt;/code&gt; for next node.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Branch by Status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Switch&lt;/td&gt;
&lt;td&gt;Routes the flow based on &lt;code&gt;payload.status&lt;/code&gt;: &lt;code&gt;success&lt;/code&gt; → process code, &lt;code&gt;invalidEmail&lt;/code&gt; → failure response.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Handle Invalid Email&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Prepares payload for invalid email or missing code scenarios.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;link out 48&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Link Out&lt;/td&gt;
&lt;td&gt;Connects the invalid email path to the main response flow.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Prepare DB Query&lt;/code&gt; (for code)&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Prepares MongoDB query to find the specific reset code that is not used and matches the email/code.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Find Password Reset Record&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MongoDB4&lt;/td&gt;
&lt;td&gt;Queries &lt;code&gt;PasswordResets&lt;/code&gt; collection to verify the entered code.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Check Reset Record Existence&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Validates if code exists, is unused, and not expired. Sets &lt;code&gt;success&lt;/code&gt;, &lt;code&gt;invalidCode&lt;/code&gt;, or &lt;code&gt;expired&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;Branch by Status&lt;/code&gt; (code)&lt;/td&gt;
&lt;td&gt;Switch&lt;/td&gt;
&lt;td&gt;Routes flow based on code verification status: &lt;code&gt;success&lt;/code&gt; → update used flag, &lt;code&gt;invalidCode&lt;/code&gt; or &lt;code&gt;expired&lt;/code&gt; → fail.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Compare Code &amp;amp; Update Used Flag&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Prepares &lt;code&gt;updateOne&lt;/code&gt; operation to mark the reset code as &lt;code&gt;used&lt;/code&gt; in MongoDB.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Update Used Flag&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MongoDB4&lt;/td&gt;
&lt;td&gt;Executes the update operation to mark the reset code as used.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Prepare Success Response&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Prepares the success payload (&lt;code&gt;validCode&lt;/code&gt;) for frontend consumption.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;validCode&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Debug&lt;/td&gt;
&lt;td&gt;Displays success message and payload in the Node-RED sidebar.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;invalidEmail&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Debug&lt;/td&gt;
&lt;td&gt;Displays invalid email or missing code payload in the sidebar.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;link out 49/50/51&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Link Out&lt;/td&gt;
&lt;td&gt;Connects the flow outputs to the main response flow to send back to frontend.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Backend Flow Summary&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;User submits email  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validated by &lt;code&gt;Validate Auth &amp;amp; Prepare Payload&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check for existing reset record  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nodes: &lt;code&gt;Prepare DB Query&lt;/code&gt; + &lt;code&gt;Find Password Reset Record&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Record exists?  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Checked via &lt;code&gt;Check Reset Record Existence&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Branch by status:

&lt;ul&gt;
&lt;li&gt;If invalid email → handled by &lt;code&gt;Handle Invalid Email&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;If code entered → verify via &lt;code&gt;Find Password Reset Record&lt;/code&gt; + &lt;code&gt;Check Reset Record Existence&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;Update used flag if valid  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nodes: &lt;code&gt;Compare Code &amp;amp; Update Used Flag&lt;/code&gt; + &lt;code&gt;Update Used Flag&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Send response back to frontend  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nodes: &lt;code&gt;Prepare Success Response&lt;/code&gt; and debug nodes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Response Examples (uibuilder.onChange)&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Response&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;invalidCode&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "action": "resetPassword", "status": "invalidCode", "message": "code not found" }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;expired&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "action": "resetPassword", "status": "expired", "message": "your code has been expired" }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;validCode&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "action": "resetPassword", "status": "validCode", "message": "Code matched successfully" }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;&lt;strong&gt;MongoDB PasswordResets Collection&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ObjectId&lt;/td&gt;
&lt;td&gt;Unique document ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;email&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;User email&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;userId&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;MongoDB &lt;code&gt;_id&lt;/code&gt; of the user&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;code&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;One-time 6-digit reset code&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;used&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;Whether code has been used (default &lt;code&gt;false&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;createdAt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Date&lt;/td&gt;
&lt;td&gt;Timestamp of token creation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;expiresAt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Date&lt;/td&gt;
&lt;td&gt;Expiration timestamp (e.g., 2 minutes)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Sample Document&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "_id": "69078db8d6c4398ea5f5cd54",
  "code": "994015",
  "email": "li@gmail.com",
  "userId": "69076591d6c4398ea5f5cd48",
  "id": 15,
  "createdAt": "2025-11-02T16:58:32.299+00:00",
  "expiresAt": "2025-11-02T17:00:32.299+00:00",
  "used": false
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  4.5 setNewPassword Flow
&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;High-Level Flow:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User enters email &amp;amp; new password
         ↓
      Frontend (Vue.js)
         ↓ uibuilder.send
   Node-RED: setNewPassword flow
         ↓
  Check email in MongoDB
         ↓
 ┌───────────────┐
 │ Email exists  │ → Update password → Success response
 └───────────────┘
 ┌───────────────┐
 │ Email invalid │ → Error response
 └───────────────┘
         ↓
      Frontend shows result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0k25edh0wvu67fzkh138.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0k25edh0wvu67fzkh138.png" alt=" " width="488" height="471"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frontend setNewPassword Action&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;submitNewPassword() {
    if (!this.newPassword) {
        alert('Please enter a new password');
        return;
    }
    if (this.newPassword !== this.confirmNewPassword) {
        alert('Passwords do not match');
        return;
    }

    // Send new password to backend via uibuilder
    uibuilder.send({
        auth: {
            type: "setNewPassword",
            email: this.resetEmail,
            password: this.newPassword
        }
    });

    console.log('New password set for:', this.resetEmail);

    // Close modal and reset fields
    this.closeSetNewPasswordModal();
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Validates that both new password and confirmation are entered and match.&lt;/li&gt;
&lt;li&gt;Sends the &lt;code&gt;setNewPassword&lt;/code&gt; action along with the email and new password to the backend via &lt;code&gt;uibuilder.send()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Closes the modal and clears fields.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Sample Request Payload&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "auth": {},
  "type": "setNewPassword",
  "email": "h@gmail.com",
  "password": "123456",
  "_socketId": "3hHNyKWUI-Khbn9cAEh0",
  "topic": "TrustedCloud Password Reset Code – Action Required",
  "_msgid": "4a86446e49c05025"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Backend Node-RED Flow&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Responsibility / Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;setNewPassword(in)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Link In&lt;/td&gt;
&lt;td&gt;Entry point of the flow; receives the request to set a new password.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Validate Auth &amp;amp; Prepare Payload&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Checks if &lt;code&gt;msg.auth&lt;/code&gt; exists and has an email. Adds &lt;code&gt;socketId&lt;/code&gt; and preserves the original payload.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Check User by Email&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Prepares a MongoDB query to find the user in the &lt;code&gt;Users&lt;/code&gt; collection by email.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Find User Record&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MongoDB&lt;/td&gt;
&lt;td&gt;Executes the query against the &lt;code&gt;Users&lt;/code&gt; collection and returns the matching user document(s).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Check if Email Exists in DB&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Checks if the user exists. Prepares a response: &lt;code&gt;success&lt;/code&gt; if email exists, &lt;code&gt;invalidEmail&lt;/code&gt; if not. Also stores user data for further processing.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Branch by Email Status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Switch&lt;/td&gt;
&lt;td&gt;Routes the flow depending on whether the email exists (&lt;code&gt;success&lt;/code&gt;) or not (&lt;code&gt;invalidEmail&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Update User Password&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Hashes the new password using bcrypt, prepares the MongoDB update operation, and stores a success response.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Update User Password&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MongoDB&lt;/td&gt;
&lt;td&gt;Updates the user’s password in the &lt;code&gt;Users&lt;/code&gt; collection.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Branch by Update Result&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Switch&lt;/td&gt;
&lt;td&gt;Checks the result of the update operation; routes to success or invalid user.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Prepare Success Response&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Prepares the final success payload: &lt;code&gt;"Password updated successfully"&lt;/code&gt; with status &lt;code&gt;success&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Handle Invalid Email&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Prepares a response if the email was not found: &lt;code&gt;"Email address not found"&lt;/code&gt; with status &lt;code&gt;invalidEmail&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Handle Invalid User&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Prepares a response if the user is invalid: &lt;code&gt;"User not found"&lt;/code&gt; with status &lt;code&gt;invalidUser&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;invalidEmail&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Debug&lt;/td&gt;
&lt;td&gt;Outputs invalid email response for debugging.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;success&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Debug&lt;/td&gt;
&lt;td&gt;Outputs success response for debugging.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;invalidUser&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Debug&lt;/td&gt;
&lt;td&gt;Outputs invalid user response for debugging.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Backend Flow Summary&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Validation &amp;amp; Payload Preparation (&lt;code&gt;Validate Auth &amp;amp; Prepare Payload&lt;/code&gt;)  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Validates the request contains a valid &lt;code&gt;auth&lt;/code&gt; object and email.
&lt;/li&gt;
&lt;li&gt;Adds &lt;code&gt;socketId&lt;/code&gt; and preserves the original payload for tracking.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Check User Existence (&lt;code&gt;Check User by Email&lt;/code&gt; + &lt;code&gt;Find User Record&lt;/code&gt;)&lt;br&gt;&lt;br&gt;&lt;br&gt;
Queries the &lt;code&gt;Users&lt;/code&gt; collection in MongoDB to verify whether the provided email exists.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Decision Branching (&lt;code&gt;Check if Email Exists in DB&lt;/code&gt; + &lt;code&gt;Branch by Email Status&lt;/code&gt;)  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If the email exists: proceeds to update the password.
&lt;/li&gt;
&lt;li&gt;If not: sends an &lt;code&gt;invalidEmail&lt;/code&gt; response.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Password Update (&lt;code&gt;Update User Password&lt;/code&gt; Function + MongoDB node)  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Hashes the new password using &lt;strong&gt;bcrypt&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Updates it in the database.
&lt;/li&gt;
&lt;li&gt;Prepares a success response.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;p&gt;Post-Update Decision (&lt;code&gt;Branch by Update Result&lt;/code&gt;)  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If update is successful: sends &lt;code&gt;success&lt;/code&gt; response.
&lt;/li&gt;
&lt;li&gt;If the user is invalid or not found: sends &lt;code&gt;invalidUser&lt;/code&gt; response.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;p&gt;Response Handling (&lt;code&gt;Prepare Success Response&lt;/code&gt;, &lt;code&gt;Handle Invalid Email&lt;/code&gt;, &lt;code&gt;Handle Invalid User&lt;/code&gt;)  &lt;/p&gt;&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Response Examples (uibuilder.onChange)&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Status&lt;/th&gt;
&lt;th&gt;Response&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;invalidEmail&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "action": "sendResetCode", "status": "invalidEmail", "message": "Email address not found." }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;invalidUser&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "action": "setNewPassword", "status": "invalidUser", "message": "User not found." }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;success&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "action": "setNewPassword", "status": "success", "message": "Password updated successfully." }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;p&gt;&lt;strong&gt;MongoDB Users Collection Schema&lt;/strong&gt;&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;_id&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;ObjectId&lt;/td&gt;
&lt;td&gt;Unique document ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;clientId&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Unique client identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fullName&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;User full name&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;email&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Unique email&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;password&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Hashed password&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;confirmPassword&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Hashed password (same as password)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;roles&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;array&lt;/td&gt;
&lt;td&gt;Assigned roles (e.g., &lt;code&gt;["Applicant","Auditor"]&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;status&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;Registration status (&lt;code&gt;not_found&lt;/code&gt;, &lt;code&gt;success&lt;/code&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;profile&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;object&lt;/td&gt;
&lt;td&gt;User profile data (avatar, first/last name, contact info)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;createdAt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Date&lt;/td&gt;
&lt;td&gt;Timestamp of account creation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;updatedAt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Date&lt;/td&gt;
&lt;td&gt;Last update timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Sample document:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "_id": "68f830f9d6c4398ea5f5cbdf",
  "clientId": "GiHBKhnJvqNbA6dYRqWHF",
  "fullName": "David Kim",
  "email": "david.kim@brightwave.co",
  "password": "$2b$10$MiGhJqBXNIJhayVOnqG1C...",
  "roles": ["Applicant","Auditor"],
  "status": "not_found",
  "profile": {
    "firstName": "David",
    "lastName": "Kim",
    "avatarUrl": "data:image/jpeg;base64,..."
  },
  "createdAt": "2025-10-22T01:18:49.129Z",
  "updatedAt": "2025-10-28T02:20:04.260Z"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  Dashboard Interface
&lt;/h1&gt;

&lt;h1&gt;
  
  
  1. UIBuilder Frontend Initialization
&lt;/h1&gt;

&lt;p&gt;Before accessing any &lt;strong&gt;dashboard&lt;/strong&gt; or request management page — such as &lt;code&gt;getDashboard&lt;/code&gt;, &lt;code&gt;editCompanyDetails&lt;/code&gt;, &lt;code&gt;archiveRequest&lt;/code&gt;, &lt;code&gt;editProfile&lt;/code&gt;, &lt;code&gt;auditRequest&lt;/code&gt;, &lt;code&gt;approveRequest&lt;/code&gt;, or &lt;code&gt;createRequest&lt;/code&gt; — the user must be &lt;strong&gt;authenticated&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Once the user logs in or registers successfully, the Vue/React app starts the uibuilder connection:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uibuilder.start();
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Key points&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Establishes a &lt;strong&gt;WebSocket&lt;/strong&gt; connection between the browser and Node-RED.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Each client is assigned a unique &lt;strong&gt;clientId&lt;/strong&gt; &lt;code&gt;(stored as a uibuilder-client-id cookie)&lt;/code&gt; for session tracking.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Every new user is initially assigned the &lt;strong&gt;Applicant role&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If a userToken exists and is valid, Node-RED restores the session and redirects the user to the correct dashboard based on their role.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If authentication fails or no token is present, the user must log in or register before accessing any dashboard or request functionality.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Purpose:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensures that only authenticated users can access dashboards or perform request-related actions.&lt;/li&gt;
&lt;li&gt;Enables role-based access control and persistent login.&lt;/li&gt;
&lt;li&gt;Provides a consistent framework for all request types (getDashboard, editProfile, etc.).&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  2. Cookie-Based Session Check
&lt;/h1&gt;

&lt;p&gt;On page load &lt;code&gt;(mounted() hook in Vue or onMounted() in React)&lt;/code&gt;, the app checks whether a &lt;strong&gt;userToken&lt;/strong&gt; cookie already exists:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if (this.getCookie("userToken")) {
  uibuilder.send({
    auth: {
      userToken: this.getCookie("userToken"),
      clientId: this.getCookie("uibuilder-client-id"),
    },
  });
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Behavior:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Token exists:&lt;/strong&gt; Node-RED validates it and restores the session. The user is then redirected to the dashboard corresponding to their role (Applicant, Approver, Auditor, etc.).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Token missing or invalid:&lt;/strong&gt; Node-RED treats it as a new session. The user must log in or register to access the dashboard or perform request-related actions.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Purpose:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enables persistent login across sessions.&lt;/li&gt;
&lt;li&gt;Ensures role-based access control from the first page load.&lt;/li&gt;
&lt;/ul&gt;




&lt;h1&gt;
  
  
  3. Token Validation and Routing Flow
&lt;/h1&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Node Name&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Type&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Identify Action Type&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;function&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Checks the incoming message &lt;code&gt;msg.type&lt;/code&gt; and sets flags like &lt;code&gt;_archiveRequest&lt;/code&gt;, &lt;code&gt;_editCompanyDetails&lt;/code&gt;, &lt;code&gt;_editProfile&lt;/code&gt;, &lt;code&gt;_auditRequest&lt;/code&gt;, &lt;code&gt;_approveRequest&lt;/code&gt;. Also extracts the user token and prepares a MongoDB query to validate it.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Extract User Record&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;function&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Extracts the first user record from MongoDB results (&lt;code&gt;msg.payload[0]&lt;/code&gt;) and attaches it to &lt;code&gt;msg.payload.user&lt;/code&gt;. If no record found, sets &lt;code&gt;user: null&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Handle Action Type&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;switch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Routes the message based on &lt;code&gt;msg.type&lt;/code&gt; to different flows: &lt;code&gt;getDashboard&lt;/code&gt;, &lt;code&gt;editCompanyDetails&lt;/code&gt;, &lt;code&gt;archiveRequest&lt;/code&gt;, &lt;code&gt;editProfile&lt;/code&gt;, &lt;code&gt;auditRequest&lt;/code&gt;, &lt;code&gt;approveRequest&lt;/code&gt;, or &lt;code&gt;createRequest&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Prepare User Lookup&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;function&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Uses the token to fetch the corresponding user ID and prepares a MongoDB query to find the user by &lt;code&gt;_id&lt;/code&gt; in the &lt;code&gt;Users&lt;/code&gt; collection.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Find User by ID&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mongodb4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Queries the &lt;code&gt;Users&lt;/code&gt; collection in MongoDB using the &lt;code&gt;_id&lt;/code&gt; prepared in the previous node.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Find Token Record&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mongodb4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Queries the &lt;code&gt;Tokens&lt;/code&gt; collection in MongoDB to validate the token provided in the request.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Check Token Presence&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;function&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Checks if &lt;code&gt;msg.auth.userToken&lt;/code&gt; exists and is valid. If not, redirects to signin. If valid, continues the flow.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;TrustedCloud UI&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;debug&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Logs the full incoming message for debugging purposes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Not Logged In&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;function&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Prepares a &lt;code&gt;msg.payload&lt;/code&gt; indicating the user is not logged in (&lt;code&gt;state: "notLoggedIn"&lt;/code&gt;) and passes it to the appropriate link output.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;status&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;switch&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Routes messages based on token validation status (&lt;code&gt;expired&lt;/code&gt;, &lt;code&gt;empty&lt;/code&gt;, &lt;code&gt;valid&lt;/code&gt;) to either &lt;code&gt;Not Logged In&lt;/code&gt; or &lt;code&gt;Prepare User Lookup&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Token Expiration&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;function&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Checks whether the token exists and is still valid. Updates &lt;code&gt;msg.payload.status&lt;/code&gt; to &lt;code&gt;valid&lt;/code&gt;, &lt;code&gt;expired&lt;/code&gt;, or &lt;code&gt;empty&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;link out 7&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;link out&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sends the message to another part of the flow (&lt;code&gt;1a592f68894d0c59&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;link out 36&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;link out&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sends messages to another part of the flow when the user is not logged in.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;getDashboard&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;link out&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sends messages to the &lt;code&gt;getDashboard&lt;/code&gt; flow (&lt;code&gt;f69577e33ab460d9&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;MongoDB Client&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mongodb4-client&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;MongoDB client configuration connecting to &lt;code&gt;hediyehTC&lt;/code&gt; database using TLS.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h1&gt;
  
  
  4. Authentication Flow Integration
&lt;/h1&gt;

&lt;p&gt;Once token validation is complete, the flow dynamically routes the request based on the &lt;code&gt;auth.type&lt;/code&gt; received from the frontend.&lt;br&gt;
Each &lt;code&gt;auth.type&lt;/code&gt; corresponds to a dedicated backend sub-flow that performs specific MongoDB operations and response handling:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;strong&gt;Request Type&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Description&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Target Collection&lt;/strong&gt;&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Roles / Access&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;getDashboard&lt;/td&gt;
&lt;td&gt;Fetches dashboard data tailored to the user’s role.&lt;/td&gt;
&lt;td&gt;Dashboard&lt;/td&gt;
&lt;td&gt;- &lt;strong&gt;Applicant &amp;amp; Auditor&lt;/strong&gt;: Sees requests they created or audited.&lt;br&gt;- &lt;strong&gt;Applicant &amp;amp; Approver&lt;/strong&gt;: Sees requests they created or approved.&lt;br&gt;- &lt;strong&gt;Applicant&lt;/strong&gt;: Sees only their own requests.&lt;br&gt;- &lt;strong&gt;Admin&lt;/strong&gt;: Full dashboard access.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;editCompanyDetails&lt;/td&gt;
&lt;td&gt;Updates company information for the authenticated user.&lt;/td&gt;
&lt;td&gt;CompanyDetails&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;archiveRequest&lt;/td&gt;
&lt;td&gt;Toggles the archived state of a request.&lt;/td&gt;
&lt;td&gt;Requests&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;editProfile&lt;/td&gt;
&lt;td&gt;Updates the user’s profile information (name, email, etc.).&lt;/td&gt;
&lt;td&gt;Users&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;auditRequest&lt;/td&gt;
&lt;td&gt;Records the auditing action taken on a request.&lt;/td&gt;
&lt;td&gt;Requests / AuditLog&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;approveRequest&lt;/td&gt;
&lt;td&gt;Records the approval of a request.&lt;/td&gt;
&lt;td&gt;Requests / AuditLog&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createRequest&lt;/td&gt;
&lt;td&gt;Creates a new request record in the system.&lt;/td&gt;
&lt;td&gt;Requests&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Behavior:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Frontend&lt;/strong&gt; sends &lt;strong&gt;msg.type&lt;/strong&gt; to Node-RED via uibuilder.&lt;/li&gt;
&lt;li&gt;Node-RED checks &lt;strong&gt;user token&lt;/strong&gt; and validates session.&lt;/li&gt;
&lt;li&gt;Switch node routes the request to the corresponding sub-flow &lt;code&gt;(getDashboard, editProfile, etc.)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Role-based access checks are applied for sensitive actions &lt;code&gt;(approveRequest, auditRequest, etc.)&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;The backend performs the database operation and sends the response back to the frontend.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Purpose:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensures that each request type has a dedicated processing flow.&lt;/li&gt;
&lt;li&gt;Implements &lt;strong&gt;role-based access control&lt;/strong&gt; for dashboard and request management.&lt;/li&gt;
&lt;li&gt;Maintains a consistent pattern for routing, validation, and response handling across all request types.&lt;/li&gt;
&lt;/ul&gt;


&lt;h1&gt;
  
  
  4.1.1 getDashboard (Applicant) Flow
&lt;/h1&gt;
&lt;h2&gt;
  
  
  High-Level Flow:
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User logs in
     ↓
Node-RED: Determine User Roles
     ↓
Switch routes by role:
     ├─ Applicant → Fetch user's own requests
     │        ↓
     │   MongoDB: Requests collection
     │        ↓
     │   Dashboard Payload → uibuilder (frontend)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Frontend getDashboard (Applicant)
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   uibuilder.start();
    this.isLoading = true; 
    var vueApp = this;

    // Send dashboard request
    uibuilder.send({
        type: 'getDashboard',
        auth: {
            userToken: this.getCookie('userToken'),
            clientId: this.getCookie('uibuilder-client-id')
        }
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;uibuilder.start()&lt;/code&gt; starts the communication channel with Node-RED via &lt;strong&gt;WebSocket&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;It sets &lt;code&gt;isLoading = true&lt;/code&gt; to show a loading indicator (e.g., spinner).&lt;/li&gt;
&lt;li&gt;Then it sends a message to Node-RED requesting the &lt;strong&gt;dashboard data&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; The request message looks like:&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Sample Request Payload
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "type": "getDashboard",
  "auth": {},
  "userToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwidXNlclRva2VuIjoiU09NRV9SQU5ET01fVE9LRU5fMTc2MTU5OTExNzkxNCIsInByb2ZpbGUiOnsidXNlcklkIjoiNjhmZmNjMjFkNmM0Mzk4ZWE1ZjVjY2Y5IiwiaWQiOjEwLCJlbWFpbCI6ImhAZ21haWwuY29tIiwicm9sZXMiOlsiYXBwbGljYW50Il0sImZ1bGxOYW1lIjoiaGVkaXllaCJ9LCJhY3Rpb24iOiJsb2dpbiIsImlhdCI6MTc2MTU5OTExNywiZXhwIjoxNzYxNjAyNzE3fQ.mkvYqaZX1Y8m8gJdS3VAlQvDJ7zj3amk-Rc59rKkR8k",
  "clientId": "DucPqZtrHFQNgOnyiGV02",
  "_socketId": "X6ZKjzzFvV-ibjhwAEiI",
  "_msgid": "8bd0ae08cdfe06a9"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Backend Node-RED Flow
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Responsibility&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Determine User Roles&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Reads user object from &lt;code&gt;msg.user&lt;/code&gt; or &lt;code&gt;msg.payload&lt;/code&gt;. Checks user roles (&lt;code&gt;Applicant&lt;/code&gt;, &lt;code&gt;Auditor&lt;/code&gt;, &lt;code&gt;Approver&lt;/code&gt;) and sets &lt;code&gt;msg.payload&lt;/code&gt; to one of: &lt;code&gt;Applicant&lt;/code&gt;, &lt;code&gt;ApplicantandAuditor&lt;/code&gt;, &lt;code&gt;ApplicantandApprover&lt;/code&gt;, or &lt;code&gt;Admin&lt;/code&gt;. Attaches full user info in &lt;code&gt;msg.user&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Route by Role Type&lt;/td&gt;
&lt;td&gt;Switch&lt;/td&gt;
&lt;td&gt;Routes flow based on &lt;code&gt;msg.payload&lt;/code&gt; role type. Sends messages to different paths for each role type.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fetch Applicant Requests&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Prepares MongoDB query for &lt;code&gt;Requests&lt;/code&gt; collection. Filters requests where &lt;code&gt;createdBy.id&lt;/code&gt; matches user ID. Sets &lt;code&gt;msg.collection&lt;/code&gt; and &lt;code&gt;msg.payload&lt;/code&gt; for MongoDB node.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Applicant Requests&lt;/td&gt;
&lt;td&gt;MongoDB4&lt;/td&gt;
&lt;td&gt;Executes query to fetch requests created by the applicant. Returns results as an array in &lt;code&gt;msg.payload&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dashboard Payload&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Builds the final dashboard payload: &lt;code&gt;type&lt;/code&gt;, &lt;code&gt;state&lt;/code&gt;, &lt;code&gt;applicantRequests&lt;/code&gt;, &lt;code&gt;requests&lt;/code&gt;. Adds &lt;code&gt;profile&lt;/code&gt; info from &lt;code&gt;msg.user&lt;/code&gt; or &lt;code&gt;msg.userData&lt;/code&gt; including user ID, email, name, roles, avatar, and contact info.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Applicant (Debug)&lt;/td&gt;
&lt;td&gt;Debug&lt;/td&gt;
&lt;td&gt;Logs the final payload for the applicant to the Node-RED debug sidebar. Useful for monitoring and troubleshooting.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Backend Flow Summary
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Determine User Roles&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose:&lt;/strong&gt; Identify the user’s role(s) based on data from MongoDB.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logic:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Checks the &lt;code&gt;roles&lt;/code&gt; array in the user object.&lt;/li&gt;
&lt;li&gt;Maps combinations to one of four categories:&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Applicant&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ApplicantandAuditor&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ApplicantandApprover&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Admin&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output:&lt;/strong&gt; Sets &lt;code&gt;msg.payload&lt;/code&gt; to role type and attaches full user info in &lt;code&gt;msg.user&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Route by Role Type&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose:&lt;/strong&gt; Directs the flow depending on the role determined.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logic:&lt;/strong&gt; Uses a &lt;strong&gt;Switch node&lt;/strong&gt; to route messages to different downstream nodes for Applicants, Approvers, Auditors, or Admins.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outcome:&lt;/strong&gt; Ensures role-specific logic is applied to dashboard requests.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Fetch Requests (Role-Based)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose:&lt;/strong&gt; Retrieve relevant requests from MongoDB for the user.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logic:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;For &lt;strong&gt;Applicants&lt;/strong&gt;: query &lt;code&gt;Requests&lt;/code&gt; collection where &lt;code&gt;createdBy.id = userId&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br&gt;
Applicant Dashboard&lt;br&gt;
Can view requests in: &lt;code&gt;Pending&lt;/code&gt;, &lt;code&gt;Audited&lt;/code&gt;, &lt;code&gt;Approved&lt;/code&gt;, &lt;code&gt;Rejected&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prepare Dashboard Payload&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Purpose:&lt;/strong&gt; Format data for front-end consumption.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logic:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;Combines request data (&lt;code&gt;applicantRequests&lt;/code&gt;, &lt;code&gt;requests&lt;/code&gt;) with user profile info (&lt;code&gt;id&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;roles&lt;/code&gt;, &lt;code&gt;avatar&lt;/code&gt;, &lt;code&gt;contact info&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Ensures front-end receives a standardized object regardless of role.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Output:&lt;/strong&gt; &lt;code&gt;msg.payload&lt;/code&gt; ready to send to UI via &lt;strong&gt;uibuilder&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Sending Data to Front-End&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Link/Debug Nodes:&lt;/strong&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;Link Out&lt;/code&gt; node passes data to the front-end flow.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Debug&lt;/code&gt; nodes monitor output for verification and troubleshooting.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Response Examples (uibuilder.onChange)
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "type": "getDashboard",
  "auth": {},
  "userToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwidXNlclRva2VuIjoiU09NRV9SQU5ET01fVE9LRU5fMTc2MTU5OTkyNTMyNCIsInByb2ZpbGUiOnsidXNlcklkIjoiNjhmZmUxOTZkNmM0Mzk4ZWE1ZjVjZDA2IiwiaWQiOjksImVtYWlsIjoibEBnbWFpbC5jb20iLCJyb2xlcyI6WyJBcHBsaWNhbnQiXSwiZnVsbE5hbWUiOiJsaWxpYSJ9LCJhY3Rpb24iOiJsb2dpbiIsImlhdCI6MTc2MTU5OTkyNSwiZXhwIjoxNzYxNjAzNTI1fQ.SJLPhRoJOVnLvUQLsk5ngvdw4d2MgFw28p5yG6Uh4wc",
  "clientId": "DucPqZtrHFQNgOnyiGV02",
  "_socketId": "2xxN12-ysdStG4sBAEj5",
  "_msgid": "09d2712e6aea20b0",
  "collection": "Requests",
  "operation": "find",
  "payload": {
    "type": "getDashboard",
    "state": "requestsFetched",
    "applicantRequests": [
      {
        "_id": "68ffe1e7d6c4398ea5f5cd08",
        "id": 18,
        "createdBy": {},
        "companyDetails": {},
        "priority": "low",
        "status": "Pending",
        "archive": false,
        "timeEstimation": "10 business day",
        "assignedTo": "",
        "auditInfo": {},
        "approveInfo": {},
        "createdAt": "2025-10-27T21:19:35.315Z",
        "profile": {
          "userId": "68ffe196d6c4398ea5f5cd06",
          "email": "l@gmail.com",
          "name": "",
          "role": "",
          "roles": ["Applicant"],
          "avatarUrl": "./images/sara-profile.png",
          "firstName": "lilia",
          "lastName": "",
          "contactNumber": "",
          "address": "",
          "country": "",
          "stateOrProvince": "",
          "postalCode": "",
          "options": {},
          "output": "toArray"
        }
      }
    ]
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  MongoDB &lt;code&gt;Requests&lt;/code&gt; Collection Schema
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;_id&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Unique MongoDB document identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;id&lt;/td&gt;
&lt;td&gt;Number&lt;/td&gt;
&lt;td&gt;Internal record ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.userId&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;ID of the user who created the record&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.id&lt;/td&gt;
&lt;td&gt;Number&lt;/td&gt;
&lt;td&gt;Creator’s internal ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.fullName&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Name of the creator (e.g., David Kim)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.email&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Creator’s email address&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.avatarUrl&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Base64-encoded profile image URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.priority&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Task or request priority (e.g., low)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.status&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Current status (e.g., Approved)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.archive&lt;/td&gt;
&lt;td&gt;Boolean&lt;/td&gt;
&lt;td&gt;Indicates if the record is archived&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.timeEstimation&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Estimated completion time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.assignedTo&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Assigned user (empty if none)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;auditInfo&lt;/td&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;Audit tracking data (timestamps, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;approveInfo&lt;/td&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;Approval metadata or history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdAt&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;td&gt;Record creation timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;updatedAt&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;td&gt;Last update timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Sample document:
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "_id": "6907636ed6c4398ea5f5cd42",
  "id": 2,
  "createdBy": {
    "userId": "68f830f9d6c4398ea5f5cbdf",
    "id": 1,
    "fullName": "David Kim",
    "email": "david.kim@brightwave.co",
    "avatarUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxIQEhUSEhI…"
  },
  "companyDetails": {
    "priority": "low",
    "status": "Approved",
    "archive": false,
    "timeEstimation": "10 business day",
    "assignedTo": ""
  },
  "auditInfo": {},
  "approveInfo": {},
  "createdAt": "2025-11-02T13:58:06.411+00:00",
  "updatedAt": "2025-11-02T14:05:05.471+00:00"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  4.1.2 getDashboard(Applicant and Auditor) Flow
&lt;/h1&gt;
&lt;h2&gt;
  
  
  High-Level Flow:
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User logs in
     ↓
Node-RED: Determine User Roles
     ↓
Switch routes by role:
     ├─ Applicant and Auditor → Fetch user's own requests
     │        ↓
     │   MongoDB: Requests collection
     │        ↓
     │   Dashboard Payload → uibuilder (frontend)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Frontend getDashboard (Applicant and Auditor)
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   uibuilder.start();
    this.isLoading = true; 
    var vueApp = this;

    // Send dashboard request
    uibuilder.send({
        type: 'getDashboard',
        auth: {
            userToken: this.getCookie('userToken'),
            clientId: this.getCookie('uibuilder-client-id')
        }
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;uibuilder.start()&lt;/code&gt; starts the communication channel with Node-RED via &lt;strong&gt;WebSocket&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;It sets &lt;code&gt;isLoading = true&lt;/code&gt; to show a loading indicator (e.g., spinner).&lt;/li&gt;
&lt;li&gt;Then it sends a message to Node-RED requesting the &lt;strong&gt;dashboard data&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; The request message looks like:&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Sample Request Payload
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "type": "getDashboard",
  "auth": {},
  "userToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwidXNlclRva2VuIjoiU09NRV9SQU5ET01fVE9LRU5fMTc2MTU5OTExNzkxNCIsInByb2ZpbGUiOnsidXNlcklkIjoiNjhmZmNjMjFkNmM0Mzk4ZWE1ZjVjY2Y5IiwiaWQiOjEwLCJlbWFpbCI6ImhAZ21haWwuY29tIiwicm9sZXMiOlsiYXBwbGljYW50Il0sImZ1bGxOYW1lIjoiaGVkaXllaCJ9LCJhY3Rpb24iOiJsb2dpbiIsImlhdCI6MTc2MTU5OTExNywiZXhwIjoxNzYxNjAyNzE3fQ.mkvYqaZX1Y8m8gJdS3VAlQvDJ7zj3amk-Rc59rKkR8k",
  "clientId": "DucPqZtrHFQNgOnyiGV02",
  "_socketId": "X6ZKjzzFvV-ibjhwAEiI",
  "_msgid": "8bd0ae08cdfe06a9"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Backend Node-RED Flow
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Determine User Roles&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Identifies the user’s roles from the MongoDB user object and categorizes them into one of four types: &lt;code&gt;Applicant&lt;/code&gt;, &lt;code&gt;ApplicantandAuditor&lt;/code&gt;, &lt;code&gt;ApplicantandApprover&lt;/code&gt;, or &lt;code&gt;Admin&lt;/code&gt;. Sets &lt;code&gt;msg.payload&lt;/code&gt; to the detected role and attaches user details to &lt;code&gt;msg.user&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Route by Role Type&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Switch&lt;/td&gt;
&lt;td&gt;Routes the message to the appropriate flow branch based on &lt;code&gt;msg.payload&lt;/code&gt; (role type). For example, users with the &lt;code&gt;ApplicantandAuditor&lt;/code&gt; role are routed to nodes that handle both applicant and auditor data retrieval.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fetch Applicant Requests&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Builds a MongoDB query to fetch all requests created by the logged-in user (&lt;code&gt;createdBy.id = userId&lt;/code&gt;). Adds &lt;code&gt;_phase: "Applicant"&lt;/code&gt; for tracking.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Applicant Requests&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;MongoDB4&lt;/td&gt;
&lt;td&gt;Executes the database query built in the previous function and retrieves all applicant-related requests. Passes the data to the next node.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Fetch Auditor Requests&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Executes only after applicant requests are fetched. Builds a new MongoDB query to find all requests requiring auditor attention (&lt;code&gt;status: Pending&lt;/code&gt;, &lt;code&gt;Audited&lt;/code&gt;, or &lt;code&gt;Rejected&lt;/code&gt;). Sets &lt;code&gt;_phase: "Auditor"&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Auditor Requests&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;MongoDB4&lt;/td&gt;
&lt;td&gt;Runs the MongoDB query for auditor-related requests and returns matching records as an array in &lt;code&gt;msg.payload&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Normalize Auditor Requests&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Cleans and enriches the auditor requests array by adding user metadata (name, email, avatar). Ensures consistent structure for UI rendering.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Dashboard Payload&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Combines &lt;code&gt;applicantRequests&lt;/code&gt;, &lt;code&gt;auditorRequests&lt;/code&gt;, and full user profile data into a single &lt;code&gt;msg.payload&lt;/code&gt; formatted for front-end use (&lt;code&gt;type: "getDashboard"&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Link Out&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Link Out&lt;/td&gt;
&lt;td&gt;Sends the final formatted dashboard payload to the front-end flow handled by &lt;strong&gt;uibuilder&lt;/strong&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;ApplicantandAuditor (Debug)&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Debug&lt;/td&gt;
&lt;td&gt;Displays the final output payload in Node-RED’s debug sidebar for inspection and troubleshooting.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h2&gt;
  
  
  Backend Flow Summary
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Purpose
&lt;/h3&gt;

&lt;p&gt;This backend flow dynamically builds the &lt;strong&gt;Applicant and Auditor dashboard&lt;/strong&gt; by retrieving and combining user-specific and role-specific data from MongoDB.&lt;/p&gt;
&lt;h3&gt;
  
  
  Process Overview
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Identify User Role:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
   Extracts and interprets the user’s roles to determine access type (Applicant, Auditor, etc.).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Route by Role:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
   Directs the flow to the appropriate logic branch depending on the identified role.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Retrieve Requests:&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Applicant Requests:&lt;/strong&gt; Queries records created by the user.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auditor Requests:&lt;/strong&gt; Fetches items pending review or action based on role permissions.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br&gt;
Auditor Dashboard&lt;br&gt;
Can view requests in: &lt;code&gt;Pending, Audited, Rejected&lt;br&gt;
Applicant Dashboard&lt;/code&gt;&lt;br&gt;
Can view requests in: &lt;code&gt;Pending, Audited, Approved, Rejected&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Normalize Data:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
   Standardizes each record’s format for the front-end, enriching it with user and request metadata.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prepare Final Dashboard Payload:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
   Merges both Applicant and Auditor data streams with the user’s full profile to produce a unified, front-end-ready response.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Send to Front-End (uibuilder):&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
   The formatted payload is sent through a &lt;strong&gt;Link Out&lt;/strong&gt; node, then displayed in the user’s dashboard interface.&lt;/p&gt;


&lt;h2&gt;
  
  
  Response Examples (uibuilder.onChange)
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
{
  "type": "getDashboard",
  "auth": {},
  "_socketId": "0KAO_QB8U2vpv5xDAElI",
  "_msgid": "b668b84c0ec154e7",
  "collection": "Requests",
  "operation": "find",
  "payload": {
    "options": {},
    "userId": "68f830f9d6c4398ea5f5cbdf",
    "user": {},
    "_phase": "Auditor",
    "applicantRequests": [
      /* 13 request objects */
    ],
    "auditorRequests": [
      /* 16 request objects */
    ]
  }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  MongoDB &lt;code&gt;Requests&lt;/code&gt; Collection Schema
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;_id&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Unique MongoDB document identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;id&lt;/td&gt;
&lt;td&gt;Number&lt;/td&gt;
&lt;td&gt;Internal record ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.userId&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;ID of the user who created the record&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.id&lt;/td&gt;
&lt;td&gt;Number&lt;/td&gt;
&lt;td&gt;Creator’s internal ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.fullName&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Name of the creator (e.g., David Kim)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.email&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Creator’s email address&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.avatarUrl&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Base64-encoded profile image URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.priority&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Task or request priority (e.g., low)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.status&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Current status (e.g., Approved)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.archive&lt;/td&gt;
&lt;td&gt;Boolean&lt;/td&gt;
&lt;td&gt;Indicates if the record is archived&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.timeEstimation&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Estimated completion time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.assignedTo&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Assigned user (empty if none)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;auditInfo&lt;/td&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;Audit tracking data (timestamps, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;approveInfo&lt;/td&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;Approval metadata or history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdAt&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;td&gt;Record creation timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;updatedAt&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;td&gt;Last update timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Sample document:
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "_id": "6907636ed6c4398ea5f5cd42",
  "id": 2,
  "createdBy": {
    "userId": "68f830f9d6c4398ea5f5cbdf",
    "id": 1,
    "fullName": "David Kim",
    "email": "david.kim@brightwave.co",
    "avatarUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxIQEhUSEhI…"
  },
  "companyDetails": {
    "priority": "low",
    "status": "Approved",
    "archive": false,
    "timeEstimation": "10 business day",
    "assignedTo": ""
  },
  "auditInfo": {},
  "approveInfo": {},
  "createdAt": "2025-11-02T13:58:06.411+00:00",
  "updatedAt": "2025-11-02T14:05:05.471+00:00"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  4.1.3 getDashboard(Applicant and Approver) Flow
&lt;/h1&gt;
&lt;h2&gt;
  
  
  High-Level Flow:
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User logs in
     ↓
Node-RED: Determine User Roles
     ↓
Switch routes by role:
     ├─ Applicant and Approver→ Fetch user's own requests
     │        ↓
     │   MongoDB: Requests collection
     │        ↓
     │   Dashboard Payload → uibuilder (frontend)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Frontend getDashboard (Applicant and Approver)
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   uibuilder.start();
    this.isLoading = true; 
    var vueApp = this;

    // Send dashboard request
    uibuilder.send({
        type: 'getDashboard',
        auth: {
            userToken: this.getCookie('userToken'),
            clientId: this.getCookie('uibuilder-client-id')
        }
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;uibuilder.start()&lt;/code&gt; starts the communication channel with Node-RED via &lt;strong&gt;WebSocket&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;It sets &lt;code&gt;isLoading = true&lt;/code&gt; to show a loading indicator (e.g., spinner).&lt;/li&gt;
&lt;li&gt;Then it sends a message to Node-RED requesting the &lt;strong&gt;dashboard data&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; The request message looks like:&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Sample Request Payload
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "type": "getDashboard",
  "auth": {},
  "userToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwidXNlclRva2VuIjoiU09NRV9SQU5ET01fVE9LRU5fMTc2MTU5OTExNzkxNCIsInByb2ZpbGUiOnsidXNlcklkIjoiNjhmZmNjMjFkNmM0Mzk4ZWE1ZjVjY2Y5IiwiaWQiOjEwLCJlbWFpbCI6ImhAZ21haWwuY29tIiwicm9sZXMiOlsiYXBwbGljYW50Il0sImZ1bGxOYW1lIjoiaGVkaXllaCJ9LCJhY3Rpb24iOiJsb2dpbiIsImlhdCI6MTc2MTU5OTExNywiZXhwIjoxNzYxNjAyNzE3fQ.mkvYqaZX1Y8m8gJdS3VAlQvDJ7zj3amk-Rc59rKkR8k",
  "clientId": "DucPqZtrHFQNgOnyiGV02",
  "_socketId": "X6ZKjzzFvV-ibjhwAEiI",
  "_msgid": "8bd0ae08cdfe06a9"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Backend Node-RED Flow
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Determine User Roles&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Determines the user’s role(s) from MongoDB and categorizes into &lt;code&gt;Applicant&lt;/code&gt;, &lt;code&gt;ApplicantandApprover&lt;/code&gt;, &lt;code&gt;ApplicantandAuditor&lt;/code&gt;, or &lt;code&gt;Admin&lt;/code&gt;. Sets &lt;code&gt;msg.payload&lt;/code&gt; to the role and attaches the full user object in &lt;code&gt;msg.user&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Route by Role Type&lt;/td&gt;
&lt;td&gt;Switch&lt;/td&gt;
&lt;td&gt;Routes messages based on &lt;code&gt;msg.payload&lt;/code&gt; (role type) to the correct downstream flow for Applicants, Approvers, or Admins.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fetch Applicant Requests&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Prepares MongoDB query to fetch requests created by the logged-in user (&lt;code&gt;createdBy.id = userId&lt;/code&gt;). Adds &lt;code&gt;_phase: "Applicant"&lt;/code&gt; to track workflow.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Applicant Requests (MongoDB)&lt;/td&gt;
&lt;td&gt;MongoDB4&lt;/td&gt;
&lt;td&gt;Executes the applicant request query and returns results in &lt;code&gt;msg.payload&lt;/code&gt; array.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fetch Approver Requests&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Prepares MongoDB query for requests the approver needs to act on (&lt;code&gt;status: Audited, Approved, Rejected&lt;/code&gt;). Sets &lt;code&gt;_phase: "Approver"&lt;/code&gt; for tracking.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Approver Requests (MongoDB)&lt;/td&gt;
&lt;td&gt;MongoDB4&lt;/td&gt;
&lt;td&gt;Executes the approver request query and returns matching requests as an array in &lt;code&gt;msg.payload&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Normalize Approver Requests&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Standardizes the structure of approver requests. Adds creator metadata (name, email, avatar) for UI display.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dashboard Payload&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Combines &lt;code&gt;applicantRequests&lt;/code&gt; and &lt;code&gt;approverRequests&lt;/code&gt; with the user’s profile info into a single object formatted for the front-end (&lt;code&gt;msg.payload.type = "getDashboard"&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Link Out&lt;/td&gt;
&lt;td&gt;Link Out&lt;/td&gt;
&lt;td&gt;Sends the final dashboard payload to the front-end via uibuilder or other linked flows.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ApplicantandApprover (Debug)&lt;/td&gt;
&lt;td&gt;Debug&lt;/td&gt;
&lt;td&gt;Shows final combined dashboard payload for testing and verification.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h2&gt;
  
  
  Backend Flow Summary
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Purpose
&lt;/h3&gt;

&lt;p&gt;The backend flow dynamically generates the &lt;strong&gt;Applicant and Approver dashboard&lt;/strong&gt; by fetching and combining requests based on user role from MongoDB.&lt;/p&gt;
&lt;h3&gt;
  
  
  Workflow
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Role Detection:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
   Extracts the user’s roles and categorizes them into one of four types. Sets &lt;code&gt;msg.payload&lt;/code&gt; and &lt;code&gt;msg.user&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Role-Based Routing:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
   Uses a switch node to send messages to different flow branches depending on the user role.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fetch Requests:&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Applicant Requests:&lt;/strong&gt; Fetches all requests created by the &lt;strong&gt;logged-in user&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Approver Requests:&lt;/strong&gt; Fetches requests with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Status &lt;strong&gt;Audited&lt;/strong&gt; or &lt;strong&gt;Approved&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rejected&lt;/strong&gt; requests, but only those rejected by Approvers, excluding any rejected by Auditors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Normalize Data:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
   Formats requests to include essential user metadata for consistent front-end rendering.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prepare Dashboard Payload:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
   Combines applicant and approver requests with full user profile to generate &lt;code&gt;msg.payload&lt;/code&gt; for the front-end.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Send to Front-End:&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
   Final payload is passed through a Link Out node to UI components (e.g., uibuilder).&lt;/p&gt;
&lt;h2&gt;
  
  
  Response Examples (uibuilder.onChange)
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  ""type"": ""getDashboard"",
  ""auth"": {
    ""userToken"": ""eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwidXNlclRva2VuIjoiU09NRV9SQU5ET01fVE9LRU5fMTc2MTYxODg3NTczNSIsInByb2ZpbGUiOnsidXNlcklkIjoiNjhmODM2MzhkNmM0Mzk4ZWE1ZjVjYmU2IiwiaWQiOjIsImVtYWlsIjoibGVpbGEuaGFzc2FuQHNreW5ldC5zeXN0ZW1zIiwicm9sZXMiOlsiQXBwbGljYW50IiwiQXBwcm92ZXIiXSwiZnVsbE5hbWUiOiJMZWlsYSBIYXNzYW4ifSwiYWN0aW9uIjoibG9naW4iLCJpYXQiOjE3NjE2MTg4NzUsImV4cCI6MTc2MTYyMjQ3NX0.yC6fr76smTVPPr0kCrmTARcJQ5qiuGqYKvl8_16rcts""
  },
  ""clientId"": ""DucPqZtrHFQNgOnyiGV02"",
  ""_socketId"": ""l9Mu_3V_ZjsFAHcfAElj"",
  ""_msgid"": ""235919a3a70d095a"",
  ""collection"": ""Requests"",
  ""operation"": ""find"",
  ""payload"": {},
  ""options"": {},
  ""userId"": ""68f83638d6c4398ea5f5cbe6"",
  ""user"": {},
  ""_phase"": ""Approver"",
  ""applicantRequests"": [],
  ""approverRequests"": [
    {},
    {},
    {},
    {}
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  MongoDB &lt;code&gt;Requests&lt;/code&gt; Collection Schema
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;_id&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Unique MongoDB document identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;id&lt;/td&gt;
&lt;td&gt;Number&lt;/td&gt;
&lt;td&gt;Internal record ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.userId&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;ID of the user who created the record&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.id&lt;/td&gt;
&lt;td&gt;Number&lt;/td&gt;
&lt;td&gt;Creator’s internal ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.fullName&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Name of the creator (e.g., David Kim)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.email&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Creator’s email address&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.avatarUrl&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Base64-encoded profile image URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.priority&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Task or request priority (e.g., low)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.status&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Current status (e.g., Approved)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.archive&lt;/td&gt;
&lt;td&gt;Boolean&lt;/td&gt;
&lt;td&gt;Indicates if the record is archived&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.timeEstimation&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Estimated completion time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.assignedTo&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Assigned user (empty if none)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;auditInfo&lt;/td&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;Audit tracking data (timestamps, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;approveInfo&lt;/td&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;Approval metadata or history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdAt&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;td&gt;Record creation timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;updatedAt&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;td&gt;Last update timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Sample document:
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "_id": "6907636ed6c4398ea5f5cd42",
  "id": 2,
  "createdBy": {
    "userId": "68f830f9d6c4398ea5f5cbdf",
    "id": 1,
    "fullName": "David Kim",
    "email": "david.kim@brightwave.co",
    "avatarUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxIQEhUSEhI…"
  },
  "companyDetails": {
    "priority": "low",
    "status": "Approved",
    "archive": false,
    "timeEstimation": "10 business day",
    "assignedTo": ""
  },
  "auditInfo": {},
  "approveInfo": {},
  "createdAt": "2025-11-02T13:58:06.411+00:00",
  "updatedAt": "2025-11-02T14:05:05.471+00:00"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  4.1.4 getDashboard(Admin) Flow
&lt;/h1&gt;
&lt;h2&gt;
  
  
  High-Level Flow:
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User logs in
     ↓
Node-RED: Determine User Roles
     ↓
Switch routes by role:
     ├─ Admin→ Fetch user's own requests
     │        ↓
     │   MongoDB: Requests collection
     │        ↓
     │   Dashboard Payload → uibuilder (frontend)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Frontend getDashboard (Admin)
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   uibuilder.start();
    this.isLoading = true; 
    var vueApp = this;

    // Send dashboard request
    uibuilder.send({
        type: 'getDashboard',
        auth: {
            userToken: this.getCookie('userToken'),
            clientId: this.getCookie('uibuilder-client-id')
        }
    });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;uibuilder.start()&lt;/code&gt; starts the communication channel with Node-RED via &lt;strong&gt;WebSocket&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;It sets &lt;code&gt;isLoading = true&lt;/code&gt; to show a loading indicator (e.g., spinner).&lt;/li&gt;
&lt;li&gt;Then it sends a message to Node-RED requesting the &lt;strong&gt;dashboard data&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt; The request message looks like:&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Sample Request Payload
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "type": "getDashboard",
  "auth": {},
  "userToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwidXNlclRva2VuIjoiU09NRV9SQU5ET01fVE9LRU5fMTc2MTU5OTExNzkxNCIsInByb2ZpbGUiOnsidXNlcklkIjoiNjhmZmNjMjFkNmM0Mzk4ZWE1ZjVjY2Y5IiwiaWQiOjEwLCJlbWFpbCI6ImhAZ21haWwuY29tIiwicm9sZXMiOlsiYXBwbGljYW50Il0sImZ1bGxOYW1lIjoiaGVkaXllaCJ9LCJhY3Rpb24iOiJsb2dpbiIsImlhdCI6MTc2MTU5OTExNywiZXhwIjoxNzYxNjAyNzE3fQ.mkvYqaZX1Y8m8gJdS3VAlQvDJ7zj3amk-Rc59rKkR8k",
  "clientId": "DucPqZtrHFQNgOnyiGV02",
  "_socketId": "X6ZKjzzFvV-ibjhwAEiI",
  "_msgid": "8bd0ae08cdfe06a9"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Backend Node-RED Flow
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Route by Role Type&lt;/td&gt;
&lt;td&gt;Switch&lt;/td&gt;
&lt;td&gt;Routes messages based on &lt;code&gt;msg.payload&lt;/code&gt; (role type) to the correct downstream flow. Here, the Admin role is handled separately.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prepare Requests Query&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Prepares a generic MongoDB query for fetching all requests (no filter) for the Admin role. Sets collection to &lt;code&gt;Requests&lt;/code&gt; and output format to &lt;code&gt;toArray&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Fetch Requests&lt;/td&gt;
&lt;td&gt;MongoDB4&lt;/td&gt;
&lt;td&gt;Executes the Admin requests query and returns all requests in &lt;code&gt;msg.payload&lt;/code&gt; array.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dashboard Payload&lt;/td&gt;
&lt;td&gt;Function&lt;/td&gt;
&lt;td&gt;Combines fetched requests with the Admin user’s profile into a structured object for the front-end (&lt;code&gt;msg.payload.type = "getDashboard"&lt;/code&gt;).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Link Out 16&lt;/td&gt;
&lt;td&gt;Link Out&lt;/td&gt;
&lt;td&gt;Sends the final Admin dashboard payload to the front-end or linked flows.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Admin&lt;/td&gt;
&lt;td&gt;Debug&lt;/td&gt;
&lt;td&gt;Displays the Admin dashboard payload for testing and verification.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;


&lt;h2&gt;
  
  
  Backend Flow Summary
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The flow identifies the user role as &lt;strong&gt;Admin&lt;/strong&gt; via the &lt;strong&gt;Route by Role Type&lt;/strong&gt; switch.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prepare Requests Query&lt;/strong&gt; constructs a MongoDB query with no restrictions, allowing Admins to see all requests.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Fetch Requests&lt;/strong&gt; node executes the query on the &lt;strong&gt;Requests&lt;/strong&gt; collection in MongoDB.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dashboard Payload&lt;/strong&gt; formats the data together with Admin profile information (email, name, roles, avatar, contact info, etc.) for front-end consumption.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Link Out 16&lt;/strong&gt; sends the formatted payload to the UI, while the &lt;strong&gt;Admin Debug&lt;/strong&gt; node allows developers to verify the output.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Response Examples (uibuilder.onChange)
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
"{
  ""type"": ""getDashboard"",
  ""auth"": {
    ""userToken"": ""eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwidXNlclRva2VuIjoiU09NRV9SQU5ET01fVE9LRU5fMTc2MTYxOTI0MjQ4MiIsInByb2ZpbGUiOnsidXNlcklkIjoiNjhmODQ0NDlkNmM0Mzk4ZWE1ZjVjYmVlIiwiaWQiOjQsImVtYWlsIjoiZmFyaWQubW9yYWRpQHF1YW50dW1lZGdlLmlvIiwicm9sZXMiOlsiQWRtaW4iXSwiZnVsbE5hbWUiOiJGYXJpZCBNb3JhZGkifSwiYWN0aW9uIjoibG9naW4iLCJpYXQiOjE3NjE2MTkyNDIsImV4cCI6MTc2MTYyMjg0Mn0.GhkUkVsHVYPN3HtrJ8dgnCggAdXGXP0KSQIJYWtPx_w""
  },
  ""clientId"": ""DucPqZtrHFQNgOnyiGV02"",
  ""_socketId"": ""pP_KxEJNyY96NbnHAEl1"",
  ""_msgid"": ""1f420fa785af463d"",
  ""collection"": ""Requests"",
  ""operation"": ""find"",
  ""payload"": {
    ""type"": ""getDashboard"",
    ""requests"": [
      {},

    ],
    ""profile"": {},
    ""options"": {}
  },
  ""userId"": ""68f84449d6c4398ea5f5c""
}
"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  MongoDB &lt;code&gt;Requests&lt;/code&gt; Collection Schema
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;_id&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Unique MongoDB document identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;id&lt;/td&gt;
&lt;td&gt;Number&lt;/td&gt;
&lt;td&gt;Internal record ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.userId&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;ID of the user who created the record&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.id&lt;/td&gt;
&lt;td&gt;Number&lt;/td&gt;
&lt;td&gt;Creator’s internal ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.fullName&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Name of the creator (e.g., David Kim)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.email&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Creator’s email address&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.avatarUrl&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Base64-encoded profile image URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.priority&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Task or request priority (e.g., low)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.status&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Current status (e.g., Approved)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.archive&lt;/td&gt;
&lt;td&gt;Boolean&lt;/td&gt;
&lt;td&gt;Indicates if the record is archived&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.timeEstimation&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Estimated completion time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.assignedTo&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Assigned user (empty if none)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;auditInfo&lt;/td&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;Audit tracking data (timestamps, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;approveInfo&lt;/td&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;Approval metadata or history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdAt&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;td&gt;Record creation timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;updatedAt&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;td&gt;Last update timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Sample document:
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "_id": "6907636ed6c4398ea5f5cd42",
  "id": 2,
  "createdBy": {
    "userId": "68f830f9d6c4398ea5f5cbdf",
    "id": 1,
    "fullName": "David Kim",
    "email": "david.kim@brightwave.co",
    "avatarUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxIQEhUSEhI…"
  },
  "companyDetails": {
    "priority": "low",
    "status": "Approved",
    "archive": false,
    "timeEstimation": "10 business day",
    "assignedTo": ""
  },
  "auditInfo": {},
  "approveInfo": {},
  "createdAt": "2025-11-02T13:58:06.411+00:00",
  "updatedAt": "2025-11-02T14:05:05.471+00:00"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  4.2.editCompanyDetails Flow
&lt;/h1&gt;
&lt;h2&gt;
  
  
  High-Level Flow:
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

Incoming Message (msg._editCompanyDetails)
             ↓
Validate Existence of _editCompanyDetails and id
             ↓
Convert id to Numeric → Return null if invalid
             ↓
Extract companyDetails Object
             ↓
Remove Empty or Undefined Fields
             ↓
Prepare MongoDB Update Payload
             ↓
Send to → "Update CompanyDetails" (MongoDB Node)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjmdi1cjme95rg624ys4b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjmdi1cjme95rg624ys4b.png" alt=" " width="755" height="609"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Frontend editCompanyDetails
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;editCompanyDetails&lt;/strong&gt; method is part of the frontend logic  responsible for sending updated company information to the backend and updating the local UI state reactively.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
      editCompanyDetails(request) {
          // 1️⃣ Send update to backend
          uibuilder.send({
            type: 'editCompanyDetails',
            auth: {
              userToken: this.getCookie('userToken'),
              clientId: this.getCookie('uibuilder-client-id')
            },
            requestID: request.id || request._id,
            companyDetails: { ...this.formData }
          });

          // 2️⃣ Update local array reactively (Vue 3)
          const reqId = request.id || request._id;
          const index = this.applicantRequests.findIndex(
            r =&amp;gt; (r.id || r._id) === reqId
          );

          if (index !== -1) {
            // Use splice instead of $set in Vue 3
            this.applicantRequests.splice(index, 1, {
              ...this.applicantRequests[index],
              companyDetails: { ...this.formData }
            });
          }

            this.waitingForResponse = true;

            setTimeout(() =&amp;gt; {
              if (this.waitingForResponse) {
                this.showNotification('Network error! Please refresh.', 'error');
                this.waitingForResponse = false;
                this.submissionSuccess = false;
                this.closeModal(); // optional: close modal automatically
              }
           }, 6000);

        },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;&lt;strong&gt;Sending Update Request&lt;/strong&gt;&lt;br&gt;
When a user edits company information and confirms changes, the method sends a structured message to the Node-RED backend using &lt;strong&gt;uibuilder.send()&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Purpose:&lt;/strong&gt;&lt;br&gt;
This ensures that the backend flow (editCompanyDetails) receives the request along with the necessary authentication context.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reactive Local Update&lt;/strong&gt;&lt;br&gt;
After sending the update request, the function updates the &lt;strong&gt;applicantRequests&lt;/strong&gt; array locally to reflect the new company details immediately — without waiting for a server response.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Finds the target record by matching &lt;code&gt;_id&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Uses &lt;code&gt;splice()&lt;/code&gt; to replace the updated record.
&lt;/li&gt;
&lt;li&gt;Ensures the UI remains synchronized with the user’s latest input.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Response Handling &amp;amp; Timeout Control&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;To manage network reliability, a &lt;strong&gt;6-second timeout&lt;/strong&gt; is implemented.&lt;br&gt;&lt;br&gt;
If the backend does not respond within this period:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;strong&gt;network error notification&lt;/strong&gt; is displayed.
&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;waitingForResponse&lt;/code&gt; flag is reset.
&lt;/li&gt;
&lt;li&gt;The modal window is optionally closed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;setTimeout(() =&amp;gt; {
  if (this.waitingForResponse) {
    this.showNotification('Network error! Please refresh.', 'error');
    this.waitingForResponse = false;
    this.submissionSuccess = false;
    this.closeModal();
  }
}, 6000);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Sample Request Payload
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  ""type"": ""editCompanyDetails"",
  ""auth"": {
    ""userToken"": ""eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwidXNlclRva2VuIjoiU09NRV9SQU5ET01fVE9LRU5fMTc2MTYxNjk5NjI1NSIsInByb2ZpbGUiOnsidXNlcklkIjoiNjhmODMwZjlkNmM0Mzk4ZWE1ZjVjYmRmIiwiaWQiOjEsImVtYWlsIjoiZGF2aWQua2ltQGJyaWdodHdhdmUuY28iLCJyb2xlcyI6WyJBcHBsaWNhbnQiLCJBdWRpdG9yIl0sImZ1bGxOYW1lIjoiRGF2aWQgS2ltIn0sImFjdGlvbiI6ImxvZ2luIiwiaWF0IjoxNzYxNjE2OTk2LCJleHAiOjE3NjE2MjA1OTZ9.I0hARpxoFQPfZjfn5ZqjV-sRJO6SKpAw7KZBR4mH6iI""
  },
  ""clientId"": ""DucPqZtrHFQNgOnyiGV02"",
  ""companyDetails"": {},
  ""_socketId"": ""0KAO_QB8U2vpv5xDAElI"",
  ""topic"": ""uibuilder"",
  ""_msgid"": ""318f5048ec2d""
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Backend Node-RED Flow
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Log Captured EditCompanyDetails&lt;/td&gt;
&lt;td&gt;&lt;code&gt;function&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Checks if an edit request exists in &lt;code&gt;msg._editCompanyDetails&lt;/code&gt;. If missing, logs a warning message. If present, logs the captured request for debugging. Passes the message to the next node.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prepare CompanyDetails Update&lt;/td&gt;
&lt;td&gt;&lt;code&gt;function&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Validates the presence of &lt;code&gt;msg._editCompanyDetails.id&lt;/code&gt;. If valid, extracts the &lt;code&gt;id&lt;/code&gt; and builds an update payload containing non-empty &lt;code&gt;companyDetails&lt;/code&gt; fields. Configures MongoDB update parameters using: &lt;br&gt; - &lt;code&gt;msg.collection = "Requests"&lt;/code&gt; &lt;br&gt; - &lt;code&gt;msg.operation = "updateOne"&lt;/code&gt; &lt;br&gt; - &lt;code&gt;msg.payload = [ { id }, { $set: updateData }, { upsert: false } ]&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Update CompanyDetails&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mongodb4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Executes the MongoDB &lt;code&gt;updateOne&lt;/code&gt; operation on the &lt;strong&gt;Requests&lt;/strong&gt; collection, applying the &lt;code&gt;$set&lt;/code&gt; changes defined in the previous node. Returns a result array for further processing.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Change (Set Response)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;change&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Creates a success response payload:  &lt;br&gt;&lt;code&gt;msg.response = { "status": "success", "action": "editCompanyDetails", "message": "success" }&lt;/code&gt;.  This response is later sent to the frontend.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;editCompanyDetails&lt;/td&gt;
&lt;td&gt;&lt;code&gt;debug&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Outputs the final message (including the success response) to the Node-RED Debug sidebar for monitoring and validation.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;link out 39&lt;/td&gt;
&lt;td&gt;&lt;code&gt;link out&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sends the message to another flow via a link node (connected to &lt;code&gt;"1a592f68894d0c59"&lt;/code&gt;), allowing the response to be transmitted to the UI or a higher-level flow controller.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Backend Flow Summary
&lt;/h2&gt;

&lt;p&gt;The &lt;strong&gt;editCompanyDetails&lt;/strong&gt; backend flow in &lt;strong&gt;Node-RED&lt;/strong&gt; is designed to handle update operations for company details associated with a request record stored in &lt;strong&gt;MongoDB&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Input Message Reception&lt;/strong&gt;&lt;br&gt;
The flow receives a message (&lt;code&gt;msg._editCompanyDetails&lt;/code&gt;) containing updated company details and the corresponding request ID.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Validation &amp;amp; Logging&lt;/strong&gt;&lt;br&gt;
The &lt;strong&gt;Log Captured EditCompanyDetails&lt;/strong&gt; node ensures that a valid edit request object exists.  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If not, a warning is logged to help debug missing or malformed requests.
&lt;/li&gt;
&lt;li&gt;If valid, the message proceeds to the update preparation stage.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Update Preparation&lt;/strong&gt;&lt;br&gt;
The &lt;strong&gt;Prepare CompanyDetails Update&lt;/strong&gt; node constructs a clean MongoDB update payload:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Verifies that &lt;code&gt;id&lt;/code&gt; is numeric and valid.
&lt;/li&gt;
&lt;li&gt;Removes empty or undefined fields from &lt;code&gt;companyDetails&lt;/code&gt; to prevent overwriting existing data with null values.
&lt;/li&gt;
&lt;li&gt;Sets operation parameters for MongoDB (&lt;code&gt;collection&lt;/code&gt;, &lt;code&gt;operation&lt;/code&gt;, and &lt;code&gt;payload&lt;/code&gt;).
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example Payload:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "collection": "Requests",
  "operation": "updateOne",
  "payload": [
    { "id": 123 },
    { "$set": { "companyDetails": { "name": "New Corp" } } },
    { "upsert": false }
  ]
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Database Update Execution&lt;/strong&gt;&lt;br&gt;
The &lt;strong&gt;Update CompanyDetails&lt;/strong&gt; node performs the MongoDB &lt;code&gt;updateOne&lt;/code&gt; operation in the &lt;strong&gt;Requests&lt;/strong&gt; collection using the prepared payload.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Response Handling&lt;/strong&gt;&lt;br&gt;
After the database operation, the &lt;strong&gt;Change&lt;/strong&gt; node generates a standardized success response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": "success",
  "action": "editCompanyDetails",
  "message": "success"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Response Examples (uibuilder.onChange)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Success Response
{
    "status": "success",
    "action": "editCompanyDetails",
    "message": "success"
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  MongoDB &lt;code&gt;Requests&lt;/code&gt; Collection Schema
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;_id&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Unique MongoDB document identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;id&lt;/td&gt;
&lt;td&gt;Number&lt;/td&gt;
&lt;td&gt;Internal record ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.userId&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;ID of the user who created the record&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.id&lt;/td&gt;
&lt;td&gt;Number&lt;/td&gt;
&lt;td&gt;Creator’s internal ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.fullName&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Name of the creator (e.g., David Kim)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.email&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Creator’s email address&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.avatarUrl&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Base64-encoded profile image URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.priority&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Task or request priority (e.g., low)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.status&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Current status (e.g., Approved)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.archive&lt;/td&gt;
&lt;td&gt;Boolean&lt;/td&gt;
&lt;td&gt;Indicates if the record is archived&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.timeEstimation&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Estimated completion time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.assignedTo&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Assigned user (empty if none)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;auditInfo&lt;/td&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;Audit tracking data (timestamps, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;approveInfo&lt;/td&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;Approval metadata or history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdAt&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;td&gt;Record creation timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;updatedAt&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;td&gt;Last update timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Sample document:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "_id": "6907636ed6c4398ea5f5cd42",
  "id": 2,
  "createdBy": {
    "userId": "68f830f9d6c4398ea5f5cbdf",
    "id": 1,
    "fullName": "David Kim",
    "email": "david.kim@brightwave.co",
    "avatarUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxIQEhUSEhI…"
  },
  "companyDetails": {
    "priority": "low",
    "status": "Approved",
    "archive": false,
    "timeEstimation": "10 business day",
    "assignedTo": ""
  },
  "auditInfo": {},
  "approveInfo": {},
  "createdAt": "2025-11-02T13:58:06.411+00:00",
  "updatedAt": "2025-11-02T14:05:05.471+00:00"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  4.3.archiveRequest Flow
&lt;/h1&gt;

&lt;h2&gt;
  
  
  High-Level Flow:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Incoming Message (msg._archiveRequest)
             ↓
Log Captured EditRequest
             ↓
Prepare Archive Toggle Update
             ↓
Update Request Archive (MongoDB)
             ↓
Set Success Response
             ↓
Send to → archiveRequest (Debug + Link Out)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqjuh6q6cu0f9frykk0kn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqjuh6q6cu0f9frykk0kn.png" alt=" " width="800" height="188"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Frontend archiveRequest
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    archiveRequest(request){
              request.archive = !request.archive

              uibuilder.send({
                type: 'archiveRequest',
                auth: {
                    userToken: this.getCookie('userToken'),
                    clientId:this.getCookie('uibuilder-client-id')
                },
                requestID: request.id

              })


          },

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Purpose:&lt;/strong&gt;&lt;br&gt;
This function is responsible for triggering the &lt;code&gt;archive/unarchive&lt;/code&gt; action of a specific request directly from the UIBuilder frontend.&lt;br&gt;
It toggles the request’s archive status locally in the UI and sends an update event to the Node-RED backend via the uibuilder communication channel.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;archiveRequest(request) {
    request.archive = !request.archive
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;&lt;p&gt;The function receives a request object (typically an entry displayed in the user interface, e.g., a row in a request table).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It immediately toggles the current state of the archive property:&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If &lt;code&gt;archive&lt;/code&gt; was &lt;code&gt;true&lt;/code&gt;, it becomes &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If &lt;code&gt;archive&lt;/code&gt;was &lt;code&gt;false&lt;/code&gt;, it becomes &lt;code&gt;true&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This local toggle gives instant UI feedback without waiting for the backend response.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;uibuilder.send({
  type: 'archiveRequest',
  auth: {
      userToken: this.getCookie('userToken'),
      clientId: this.getCookie('uibuilder-client-id')
  },
  requestID: request.id
})
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;After toggling, the function sends a message to the Node-RED backend using &lt;code&gt;uibuilder.send()&lt;/code&gt; — the built-in communication bridge between the frontend and Node-RED.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Sample Request Payload
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  ""type"": ""archiveRequest"",
  ""auth"": {
    ""userToken"": ""eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwidXNlclRva2VuIjoiU09NRV9SQU5ET01fVE9LRU5fMTc2MTYxNjk5NjI1NSIsInByb2ZpbGUiOnsidXNlcklkIjoiNjhmODMwZjlkNmM0Mzk4ZWE1ZjVjYmRmIiwiaWQiOjEsImVtYWlsIjoiZGF2aWQua2ltQGJyaWdodHdhdmUuY28iLCJyb2xlcyI6WyJBcHBsaWNhbnQiLCJBdWRpdG9yIl0sImZ1bGxOYW1lIjoiRGF2aWQgS2ltIn0sImFjdGlvbiI6ImxvZ2luIiwiaWF0IjoxNzYxNjE2OTk2LCJleHAiOjE3NjE2MjA1OTZ9.I0hARpxoFQPfZjfn5ZqjV-sRJO6SKpAw7KZBR4mH6iI""
  },
  ""clientId"": ""DucPqZtrHFQNgOnyiGV02"",
  ""requestID"": 13,
  ""_socketId"": ""0KAO_QB8U2vpv5xDAElI"",
  ""topic"": ""uibuilder"",
  ""_msgid"": ""7c5fc73c0374d772""
}


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Backend Node-RED Flow
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description / Function&lt;/th&gt;
&lt;th&gt;Key Operations / Outputs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Log Captured EditRequest&lt;/td&gt;
&lt;td&gt;function&lt;/td&gt;
&lt;td&gt;Checks whether an incoming &lt;code&gt;_archiveRequest&lt;/code&gt; exists in the message. Logs it for debugging.&lt;/td&gt;
&lt;td&gt;Warns “No editRequest captured yet” if missing. Logs full request if present. Passes message forward.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prepare Archive Toggle Update&lt;/td&gt;
&lt;td&gt;function&lt;/td&gt;
&lt;td&gt;Extracts the request ID from &lt;code&gt;_archiveRequest&lt;/code&gt; or &lt;code&gt;msg.payload&lt;/code&gt;, validates it, and prepares the MongoDB update payload to toggle the &lt;code&gt;archive&lt;/code&gt; field.&lt;/td&gt;
&lt;td&gt;Determines &lt;code&gt;requestId&lt;/code&gt;. Builds &lt;code&gt;msg.payload&lt;/code&gt; for MongoDB &lt;code&gt;updateOne&lt;/code&gt;. Operation: &lt;code&gt;{ $set: { archive: { $not: ["$archive"] } } }&lt;/code&gt;. Sets &lt;code&gt;collection = "Requests"&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Update Request Archive&lt;/td&gt;
&lt;td&gt;mongodb4&lt;/td&gt;
&lt;td&gt;Executes the prepared MongoDB &lt;code&gt;updateOne&lt;/code&gt; operation against the &lt;code&gt;Requests&lt;/code&gt; collection.&lt;/td&gt;
&lt;td&gt;Performs update with &lt;code&gt;upsert: false&lt;/code&gt;. Output mode: &lt;code&gt;toArray&lt;/code&gt;. Uses MongoDB client: &lt;code&gt;3947f4ac602166f9&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;(Unnamed)&lt;/td&gt;
&lt;td&gt;change&lt;/td&gt;
&lt;td&gt;Sets a structured response message indicating success.&lt;/td&gt;
&lt;td&gt;Sets &lt;code&gt;msg.response = { "status": "success", "action": "archiveRequest", "message": "success" }&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;archiveRequest&lt;/td&gt;
&lt;td&gt;debug&lt;/td&gt;
&lt;td&gt;Displays the final message (full &lt;code&gt;msg&lt;/code&gt; object) in the Node-RED Debug sidebar for inspection.&lt;/td&gt;
&lt;td&gt;Outputs final message for confirmation and troubleshooting.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;link out 40&lt;/td&gt;
&lt;td&gt;link out&lt;/td&gt;
&lt;td&gt;Sends the successful result (&lt;code&gt;msg.response&lt;/code&gt;) to another linked flow for further processing.&lt;/td&gt;
&lt;td&gt;Connects to Link node: &lt;code&gt;1a592f68894d0c59&lt;/code&gt; (destination flow).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Backend Flow Summary
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This flow manages toggling the &lt;code&gt;archive&lt;/code&gt; status of a specific &lt;code&gt;request&lt;/code&gt; in the Requests MongoDB collection.&lt;br&gt;
It validates incoming data, performs a conditional update, and returns a structured success response.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Log Captured EditRequest&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This function node checks whether an incoming &lt;code&gt;_archiveRequest&lt;/code&gt; exists in the message.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If it’s &lt;strong&gt;missing&lt;/strong&gt;, a warning message is logged:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; No editRequest captured yet
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;If it’s &lt;strong&gt;present&lt;/strong&gt;, the full request object is logged for debugging.
After logging, the message is passed to the next node.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Prepare Archive Toggle Update&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This Function node extracts and validates the request ID, then prepares the MongoDB update operation.&lt;/p&gt;

&lt;p&gt;It searches for the ID in &lt;code&gt;_archiveRequest&lt;/code&gt; or &lt;code&gt;msg.payload&lt;/code&gt;, checking fields such as:&lt;br&gt;
&lt;code&gt;id&lt;/code&gt;, &lt;code&gt;requestID&lt;/code&gt;, &lt;code&gt;requestId&lt;/code&gt;, or &lt;code&gt;_id&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If no ID is found, the node returns null to stop the flow.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If a valid ID is found, it builds the parameters needed for a MongoDB updateOne operation.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This operation is designed to toggle the value of the archive field using the following expression:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{ $set: { archive: { $not: ["$archive"] } } }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It then sets the target collection to &lt;code&gt;Requests&lt;/code&gt;and attaches the constructed payload to &lt;code&gt;msg&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update Request Archive&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Update Request Archive&lt;/strong&gt; MongoDB node executes the update operation using the configured client connection:&lt;br&gt;
&lt;code&gt;3947f4ac602166f9&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The node performs the update with &lt;code&gt;upsert&lt;/code&gt; disabled (so it won’t create new documents).&lt;/li&gt;
&lt;li&gt;The operation output is returned as an array.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Change Node&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After a successful update, the message passes through a Change node that creates a structured response object:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": "success",
  "action": "archiveRequest",
  "message": "success"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This response replaces &lt;code&gt;msg.response&lt;/code&gt;, preparing it for output or further handling.&lt;/p&gt;

&lt;h2&gt;
  
  
  Response Examples (uibuilder.onChange)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Success Response
{
    "status": "success",
    "action": "archiveRequest",
    "message": "success"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  MongoDB &lt;code&gt;Requests&lt;/code&gt; Collection Schema
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;_id&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Unique MongoDB document identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;id&lt;/td&gt;
&lt;td&gt;Number&lt;/td&gt;
&lt;td&gt;Internal record ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.userId&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;ID of the user who created the record&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.id&lt;/td&gt;
&lt;td&gt;Number&lt;/td&gt;
&lt;td&gt;Creator’s internal ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.fullName&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Name of the creator (e.g., David Kim)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.email&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Creator’s email address&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.avatarUrl&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Base64-encoded profile image URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.priority&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Task or request priority (e.g., low)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.status&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Current status (e.g., Approved)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.archive&lt;/td&gt;
&lt;td&gt;Boolean&lt;/td&gt;
&lt;td&gt;Indicates if the record is archived&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.timeEstimation&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Estimated completion time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.assignedTo&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Assigned user (empty if none)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;auditInfo&lt;/td&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;Audit tracking data (timestamps, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;approveInfo&lt;/td&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;Approval metadata or history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdAt&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;td&gt;Record creation timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;updatedAt&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;td&gt;Last update timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Sample document:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "_id": "6907636ed6c4398ea5f5cd42",
  "id": 2,
  "createdBy": {
    "userId": "68f830f9d6c4398ea5f5cbdf",
    "id": 1,
    "fullName": "David Kim",
    "email": "david.kim@brightwave.co",
    "avatarUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxIQEhUSEhI…"
  },
  "companyDetails": {
    "priority": "low",
    "status": "Approved",
    "archive": false,
    "timeEstimation": "10 business day",
    "assignedTo": ""
  },
  "auditInfo": {},
  "approveInfo": {},
  "createdAt": "2025-11-02T13:58:06.411+00:00",
  "updatedAt": "2025-11-02T14:05:05.471+00:00"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  4.4.editProfile Flow
&lt;/h1&gt;

&lt;h2&gt;
  
  
  High-Level Flow:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Incoming _editProfile Request
          ↓
 ┌────────────────────────────┐
 │ Log Captured EditProfile   │
 │ Checks if _editProfile     │
 │ exists → Logs details      │
 └────────────────────────────┘
          ↓
 ┌────────────────────────────┐
 │ Prepare EditProfile Update │
 │ - Validates userId &amp;amp;       │
 │   profileDetails           │
 │ - Converts userId to       │
 │   ObjectId                 │
 │ - Builds updateOne query   │
 │   for MongoDB              │
 └────────────────────────────┘
          ↓
 ┌────────────────────────────┐
 │ Update User (MongoDB4)     │
 │ Executes updateOne on      │
 │ Users collection           │
 │ Updates profile, email,    │
 │ and updatedAt fields       │
 └────────────────────────────┘
          ↓
 ┌────────────────────────────┐
 │ Change Node                │
 │ Creates standardized       │
 │ response JSON:             │
 │ {status:"success",         │
 │  action:"editProfile"}     │
 └────────────────────────────┘
          ↓
 ┌────────────────────────────┐
 │ editProfile (Debug)        │
 │ Shows final response in    │
 │ debug sidebar              │
 └────────────────────────────┘
          ↓
 ┌────────────────────────────┐
 │ link out                   │
 │ Sends response to connected│
 │ flow (e.g., frontend)      │
 └────────────────────────────┘


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Frontend editProfile
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;         uibuilder.send({
                type: 'editProfile',
                auth: {
                    userToken: this.getCookie('userToken'),
                    clientId:this.getCookie('uibuilder-client-id')
                },
                profile: this.profile,
                userId: this.profile.userId
            })
            this.showNotification('Profile updated successfully!', 'success');


              this.originalProfile = JSON.parse(JSON.stringify(this.profile));
              this.isProfileEdited = false;


          },

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Sending a Message&lt;/strong&gt;&lt;br&gt;
The &lt;code&gt;uibuilder.send()&lt;/code&gt; function sends a structured JSON message from the frontend (browser) to the Node-RED flow connected to this UI.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Message Type&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;type: 'editProfile'&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Defines the message category.&lt;/li&gt;
&lt;li&gt;The Node-RED backend can filter based on this type:
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;type&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;editProfile&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="c1"&gt;// Handle edit profile logic&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Authentication Object&lt;/strong&gt;&lt;br&gt;
The &lt;code&gt;auth&lt;/code&gt; object includes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;auth: {
    userToken: this.getCookie('userToken'),
    clientId: this.getCookie('uibuilder-client-id')
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;User Authentication&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;userToken&lt;/strong&gt;: Retrieved from browser cookies; acts as a session token to verify user identity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;clientId&lt;/strong&gt;: Unique identifier for this connected UIBuilder client instance. This helps Node-RED know which user’s UI sent the message.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This provides an authentication and traceability layer for the backend.&lt;/p&gt;

&lt;h3&gt;
  
  
  Profile Data
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;profile&lt;/strong&gt;: &lt;br&gt;
&lt;code&gt;profile: this.profile&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The entire profile object containing updated user data (e.g., name, email, phone, etc.).&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;userId: this.profile.userId&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Explicitly adds the userId to make it easy for Node-RED to target the correct database entry or API endpoint.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Show Notification&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;this.showNotification('Profile updated successfully!', 'success');
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Purpose:&lt;/strong&gt; Immediately give UX feedback to the user that their profile &lt;br&gt;
update was sent successfully.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;showNotification()&lt;/code&gt; is likely a local method that triggers a UI alert or toast popup.&lt;/li&gt;
&lt;li&gt;The 'success' type may apply specific colors/icons (e.g., green checkmark).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This runs immediately after sending the request, not after backend confirmation — so it’s a frontend optimistic update.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Reset State&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;this.originalProfile = JSON.parse(JSON.stringify(this.profile));
this.isProfileEdited = false;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Purpose and behavior:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;JSON.parse(JSON.stringify(...))&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deep-copies the current profile object.&lt;/li&gt;
&lt;li&gt;Ensures that originalProfile and profile are not referencing the same object in memory.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;this.originalProfile = ...&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Stores the last successfully sent version of the user’s profile.&lt;/li&gt;
&lt;li&gt;Used later to detect unsaved changes.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;this.isProfileEdited = false;&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Resets the “edit mode” flag, telling the UI that there are no pending unsaved edits anymore.&lt;/li&gt;
&lt;li&gt;Often used to disable “Save” buttons or hide “unsaved changes” warnings.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Sample Request Payload
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"{
  ""type"": ""editProfile"",
  ""auth"": {
    ""userToken"": ""eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwidXNlclRva2VuIjoiU09NRV9SQU5ET01fVE9LRU5fMTc2MTYxNjk5NjI1NSIsInByb2ZpbGUiOnsidXNlcklkIjoiNjhmODMwZjlkNmM0Mzk4ZWE1ZjVjYmRmIiwiaWQiOjEsImVtYWlsIjoiZGF2aWQua2ltQGJyaWdodHdhdmUuY28iLCJyb2xlcyI6WyJBcHBsaWNhbnQiLCJBdWRpdG9yIl0sImZ1bGxOYW1lIjoiRGF2aWQgS2ltIn0sImFjdGlvbiI6ImxvZ2luIiwiaWF0IjoxNzYxNjE2OTk2LCJleHAiOjE3NjE2MjA1OTZ9.I0hARpxoFQPfZjfn5ZqjV-sRJO6SKpAw7KZBR4mH6iI""
  },
  ""clientId"": ""DucPqZtrHFQNgOnyiGV02"",
  ""profile"": {
    ""userId"": ""68f830f9d6c4398ea5f5cbdf"",
    ""email"": ""david.kim@brightwave.co"",
    ""role"": ""Applicant"",
    ""roles"": [""Applicant"", ""Auditor""],
    ""avatarUrl"": ""data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxIQEhUSEhIVFhAXFRUSFRUVFRAVFRAVFRIXFxcVFRUYHSggGBolHRUVITEhJSkrLi4uFx8zODMtNygtLisBCgoKDg0OFxAQFS0dIB0tLS0tLSstLSstLS0tKystLSsrLS0tKy0tLS0rLS0rLS0tNys3Ky0tLSsrLSsrKy0rK//AABEIARMAtwMBIgACEQEDEQA/ANulCQXQnRFnIXQE6F2EhjQE6F2F2EANhdDV1dSA5lXCE9cIQAzKugLqc1qBnIShPhIhAhkLoXYSQAl0JhcuZkDJUkzMlnSAekmSugoAckkkgCqE5PypZVZA0Jy6GruVAzgC6AuhqcAkMbCUJySAGJLpWY4p4vpWQc0eOt+Qf093Hl5IA0r3gCSQB1Og+Khp4lScYbUYT0D2k/AFeI4rxXWu3EOcQIJ00a0cg0dU3D7xzADlMxuIPqE6Ge5uvWBwbmGc8pE/BTryUcSVKrQ1whwdIMBp84566rV4TxqwhrKzXNqbEwIMc/VSFGtKjcU62rNqtDmmWlPNNAiq5yUqc0Vz2KBkcroUgpJ4poAiATpTi1NISAQKSQCSAJcqWVPXU7FQwNXcqeuosZHlShOe6FWddhFgSkKpiV/Tt2GpVdlYPiew6rmJYm2hSfVds0T5rxbiHiepc1HOfsJyN/pYOW257pxViZp8Z42uawLbdgpt2znV3pyWQuKZAJeRn11cZkk8pPxKEVMRq..."",
    ""firstName"": ""David"",
    ""lastName"": ""Kim"",
    ""contactNumber"": """",
    ""address"": """",
    ""country"": """",
    ""stateOrProvince"": """",
    ""postalCode"": """"
  },
  ""_socketId"": ""0KAO_QB8U2vpv5xDAElI"",
  ""topic"": ""uibuilder"",
  ""_msgid"": ""37a193fd9e74e""
}
"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Backend Node-RED Flow
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Log Captured EditProfile&lt;/td&gt;
&lt;td&gt;&lt;code&gt;function&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Checks if an &lt;code&gt;_editProfile&lt;/code&gt; object exists in the incoming message. If it does not exist, logs a warning message &lt;code&gt;"No editProfile captured yet"&lt;/code&gt;. If it exists, logs the captured editProfile details as a JSON string for debugging. Passes the message to the next node.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prepare EditProfile Update&lt;/td&gt;
&lt;td&gt;&lt;code&gt;function&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Validates the &lt;code&gt;_editProfile&lt;/code&gt; object. Extracts &lt;code&gt;userId&lt;/code&gt; and &lt;code&gt;profileDetails&lt;/code&gt; from it. If either is missing, stops the flow. Removes the email field from &lt;code&gt;profileDetails&lt;/code&gt;, stores it separately, and converts &lt;code&gt;userId&lt;/code&gt; into a MongoDB ObjectId. Prepares an &lt;code&gt;updateOne&lt;/code&gt; operation for the &lt;code&gt;Users&lt;/code&gt; collection, setting new profile data, email, and an updated timestamp. Passes the MongoDB query to the next node.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Update User&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mongodb4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Executes the prepared &lt;code&gt;updateOne&lt;/code&gt; operation on the &lt;code&gt;Users&lt;/code&gt; collection in the connected MongoDB database. Updates the user’s profile and email based on the provided ObjectId. After the operation, sends the output to the next node.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Change&lt;/td&gt;
&lt;td&gt;&lt;code&gt;change&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Creates a standardized response object inside the message payload: &lt;code&gt;{"status":"success","action":"editProfile","message":"success"}&lt;/code&gt;. This ensures the front end receives a clear and consistent update confirmation. Sends the message to the debug and link nodes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;editProfile&lt;/td&gt;
&lt;td&gt;&lt;code&gt;debug&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Displays the final message in the Node-RED debug sidebar for verification and troubleshooting. Useful for confirming successful updates and checking the output data structure.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;link out&lt;/td&gt;
&lt;td&gt;&lt;code&gt;link out&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Sends the final response message to another flow or group in Node-RED that is linked via the same link ID. This allows the result of the profile update operation to be routed to other connected processes (such as UI feedback or logging flows).&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Backend Flow Summary
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;EditProfile&lt;/code&gt; flow handles updating a user’s profile information in the MongoDB database. It performs input validation, data transformation, and database update operations, followed by returning a success response.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Input and Validation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The process begins with the Log Captured &lt;code&gt;EditProfile&lt;/code&gt; function node.&lt;/li&gt;
&lt;li&gt;It checks whether &lt;code&gt;msg._editProfile&lt;/code&gt; exists.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If not found, it logs a warning and halts further updates.&lt;/p&gt;

&lt;p&gt;If found, it logs the full content for debugging.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This ensures only valid edit requests proceed to the update logic.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Data Preparation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The Prepare &lt;code&gt;EditProfile&lt;/code&gt; Update node extracts &lt;strong&gt;userId&lt;/strong&gt; and &lt;strong&gt;profileDetails&lt;/strong&gt; from &lt;code&gt;msg._editProfile&lt;/code&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;It performs the following technical steps:&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Validates both fields’ existence.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Separates the &lt;code&gt;email&lt;/code&gt; from the &lt;code&gt;profileDetails&lt;/code&gt; object (to be updated independently).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Converts the &lt;code&gt;userId&lt;/code&gt; string into a valid mongodb.ObjectId.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If the &lt;code&gt;ObjectId&lt;/code&gt; is invalid, the flow logs an error and stops.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Constructs an &lt;code&gt;updateOne&lt;/code&gt; operation with &lt;code&gt;$set&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "profile": "&amp;lt;profileDetails&amp;gt;",
  "email": "&amp;lt;email&amp;gt;",
  "updatedAt": "&amp;lt;current timestamp&amp;gt;"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Stores the query as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;msg.collection = "Users";
msg.operation = "updateOne";
msg.payload = [ { _id: ObjectId }, { $set: {...} }, { upsert: false } ];
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Database Operation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Update User node (MongoDB4 node) connects to the defined MongoDB cluster.&lt;/li&gt;
&lt;li&gt;Executes the updateOne operation on the Users collection.&lt;/li&gt;
&lt;li&gt;It ensures only one matching record (by _id) is updated without inserting a new one.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Response Construction&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After the update completes, the change node builds a standardized response:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": "success",
  "action": "editProfile",
  "message": "success"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;This structured response ensures the front-end receives consistent output regardless of internal flow complexity.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Response Examples (uibuilder.onChange)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Success Response
{
    "status": "success",
    "action": "editProfile",
    "message": "success"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  MongoDB &lt;code&gt;Requests&lt;/code&gt; Collection Schema
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;_id&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Unique MongoDB document identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;id&lt;/td&gt;
&lt;td&gt;Number&lt;/td&gt;
&lt;td&gt;Internal record ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.userId&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;ID of the user who created the record&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.id&lt;/td&gt;
&lt;td&gt;Number&lt;/td&gt;
&lt;td&gt;Creator’s internal ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.fullName&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Name of the creator (e.g., David Kim)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.email&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Creator’s email address&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.avatarUrl&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Base64-encoded profile image URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.priority&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Task or request priority (e.g., low)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.status&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Current status (e.g., Approved)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.archive&lt;/td&gt;
&lt;td&gt;Boolean&lt;/td&gt;
&lt;td&gt;Indicates if the record is archived&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.timeEstimation&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Estimated completion time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.assignedTo&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Assigned user (empty if none)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;auditInfo&lt;/td&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;Audit tracking data (timestamps, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;approveInfo&lt;/td&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;Approval metadata or history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdAt&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;td&gt;Record creation timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;updatedAt&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;td&gt;Last update timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Sample document:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "_id": "6907636ed6c4398ea5f5cd42",
  "id": 2,
  "createdBy": {
    "userId": "68f830f9d6c4398ea5f5cbdf",
    "id": 1,
    "fullName": "David Kim",
    "email": "david.kim@brightwave.co",
    "avatarUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxIQEhUSEhI…"
  },
  "companyDetails": {
    "priority": "low",
    "status": "Approved",
    "archive": false,
    "timeEstimation": "10 business day",
    "assignedTo": ""
  },
  "auditInfo": {},
  "approveInfo": {},
  "createdAt": "2025-11-02T13:58:06.411+00:00",
  "updatedAt": "2025-11-02T14:05:05.471+00:00"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  4.5.auditRequest Flow
&lt;/h1&gt;

&lt;h2&gt;
  
  
  High-Level Flow:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Incoming _auditRequest
          ↓
 ┌─────────────────────────────────────┐
 │ Log Captured Audit Request          │
 │ Checks if _auditRequest exists      │
 │ → Logs full request for debugging   │
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ Prepare Audit Update                │
 │ - Extracts audit.id and userId      │
 │ - Determines decision and newStatus │
 │ - Builds updateOne query for MongoDB│
 │   to update status and auditInfo    │
 │   { date, auditorId, comment }      │
 │ - Adds updatedAt timestamp          │
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ Update Request Record (MongoDB4)    │
 │ Executes updateOne on "Requests"    │
 │ collection to apply audit decision  │
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ Change Node                         │
 │ Sets standardized response:         │
 │ {status:"success", action:"auditRequest"} │
 │ Prepares final output message       │
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ auditRequest (Debug)                │
 │ Displays final response in debug    │
 │ sidebar for verification            │
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ link out                          │
 │ Sends response to connected flows   │
 │ (e.g., UI or further processing)    │
 └─────────────────────────────────────┘

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Frontend auditRequest
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; auditRequest() {
              const req = this.currentRequest;
              const updatedStatus = req.status.charAt(0).toUpperCase() + req.status.slice(1).toLowerCase();
              const auditDate = req.auditDate || new Date().toISOString().split('T')[0];
              const comment = req.auditorComment || '';

              // send to backend
              uibuilder.send({
                type: 'auditRequest',
                auth: {
                  userToken: this.getCookie('userToken'),
                  clientId: this.getCookie('uibuilder-client-id')
                },
                userId: this.profile.userId,
                requestId: req.id || req._id,
                auditDecision: { status: updatedStatus, auditDate, comment }
              });

              // show waiting state
              this.waitingForResponse = true;

              // update in all dashboards immediately
              const updateLists = [this.applicantRequests, this.auditorRequests, this.adminRequests];
              updateLists.forEach(list =&amp;gt; {
                const index = list.findIndex(r =&amp;gt; (r.id || r._id) === (req.id || req._id));
                if (index !== -1) {
                  list.splice(index, 1, {
                    ...list[index],
                    status: updatedStatus,
                    auditDate,
                    auditorComment: comment
                  });
                }
              });

              setTimeout(() =&amp;gt; {
                  if (this.waitingForResponse) {
                    this.showNotification('Network error! Please refresh.', 'error');
                    this.waitingForResponse = false;
                    this.submissionSuccess = false;
                    this.closeModal(); // optional: close modal automatically
                  }
               }, 6000);
            },

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;auditRequest()&lt;/code&gt; function handles sending an audit decision from the frontend to the backend and updates the UI immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Extract &amp;amp; Normalize Data&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gets current request&lt;/strong&gt;: 

&lt;ul&gt;
&lt;li&gt;This is done using &lt;code&gt;this.currentRequest&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;strong&gt;Formats&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Status&lt;/li&gt;
&lt;li&gt;Sets &lt;code&gt;auditDate&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Extracts &lt;code&gt;auditorComment&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Send to Backend&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Uses &lt;code&gt;uibuilder.send()&lt;/code&gt; with the following parameters:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;authentication&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;userId&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;requestId&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;auditDecision&lt;/code&gt; payload&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Optimistic UI Update&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Instantly updates the following lists for a responsive UI:

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;applicantRequests&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;auditorRequests&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;adminRequests&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Error Handling&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sets a &lt;strong&gt;6-second timeout&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;If no response is received, it shows a network error.&lt;/li&gt;
&lt;li&gt;Resets flags.&lt;/li&gt;
&lt;li&gt;Optionally closes the modal.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;&lt;br&gt;
The purpose of this function is to ensure fast and responsive feedback to the auditor while securely submitting the decision to the backend for database updates.&lt;/p&gt;
&lt;h2&gt;
  
  
  Sample Request Payload
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"{
  ""type"": ""auditRequest"",
  ""auth"": {
    ""userToken"": ""eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwidXNlclRva2VuIjoiU09NRV9SQU5ET01fVE9LRU5fMTc2MTYxNjk5NjI1NSIsInByb2ZpbGUiOnsidXNlcklkIjoiNjhmODMwZjlkNmM0Mzk4ZWE1ZjVjYmRmIiwiaWQiOjEsImVtYWlsIjoiZGF2aWQua2ltQGJyaWdodHdhdmUuY28iLCJyb2xlcyI6WyJBcHBsaWNhbnQiLCJBdWRpdG9yIl0sImZ1bGxOYW1lIjoiRGF2aWQgS2ltIn0sImFjdGlvbiI6ImxvZ2luIiwiaWF0IjoxNzYxNjE2OTk2LCJleHAiOjE3NjE2MjA1OTZ9.I0hARpxoFQPfZjfn5ZqjV-sRJO6SKpAw7KZBR4mH6iI""
  },
  ""clientId"": ""DucPqZtrHFQNgOnyiGV02"",
  ""userId"": ""68f830f9d6c4398ea5f5cbdf"",
  ""requestId"": 18,
  ""auditDecision"": {
    ""status"": ""Audited"",
    ""auditDate"": ""2025-10-28"",
    ""comment"": ""yes""
  },
  ""_socketId"": ""0KAO_QB8U2vpv5xDAElI"",
  ""topic"": ""uibuilder"",
  ""_msgid"": ""196c7d70d5cc4""
}
"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Backend Node-RED Flow
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Log Captured Audit Request&lt;/td&gt;
&lt;td&gt;&lt;code&gt;function&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Checks whether an incoming &lt;code&gt;_auditRequest&lt;/code&gt; exists in the message. If missing, logs a warning “No auditRequest captured yet”. If present, logs the full audit request for debugging. Passes the message to the next node.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prepare Audit Update&lt;/td&gt;
&lt;td&gt;&lt;code&gt;function&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Extracts audit details from &lt;code&gt;msg._auditRequest&lt;/code&gt; and determines the target user ID from either &lt;code&gt;msg.userId&lt;/code&gt; or &lt;code&gt;msg.auth.userId&lt;/code&gt;. If no valid audit data or ID is found, the message is dropped. Otherwise, it prepares a MongoDB &lt;code&gt;updateOne&lt;/code&gt; operation for the &lt;code&gt;Requests&lt;/code&gt; collection, updating fields such as status, audit information (date, auditor ID, comment, decision), and timestamp.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Update Request Record&lt;/td&gt;
&lt;td&gt;&lt;code&gt;mongodb4&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Executes the MongoDB update operation prepared by the previous node. It connects to the specified MongoDB cluster (&lt;code&gt;hediyehTC&lt;/code&gt; database) and applies the update to the &lt;code&gt;Requests&lt;/code&gt; collection.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;change&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Creates a standardized response message confirming successful audit update. Sets &lt;code&gt;msg.response&lt;/code&gt; to a JSON object containing &lt;code&gt;status: success&lt;/code&gt;, &lt;code&gt;action: auditRequest&lt;/code&gt;, and &lt;code&gt;message: success&lt;/code&gt;. Passes the response to the debug and link-out nodes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;auditRequest&lt;/td&gt;
&lt;td&gt;&lt;code&gt;debug&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Displays the final message object in the Node-RED debug sidebar, allowing developers to verify the response payload and data structure after database update.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;link out 38&lt;/td&gt;
&lt;td&gt;&lt;code&gt;link out&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Forwards the processed message to another part of the flow using a link connection (&lt;code&gt;1a592f68894d0c59&lt;/code&gt;), typically to send the response back to the frontend or trigger additional logic.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Backend Flow Summary
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Capture and Log the Incoming Audit Request&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Log Captured Audit&lt;/strong&gt; Request function node checks for the presence of &lt;code&gt;_auditRequest&lt;/code&gt; in the message.&lt;/li&gt;
&lt;li&gt;If the field is missing, it logs a warning to indicate no request has been received yet.&lt;/li&gt;
&lt;li&gt;If present, the entire request object is logged for traceability and debugging.&lt;/li&gt;
&lt;li&gt;This ensures early validation and helps identify missing or malformed messages before database operations begin.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Prepare MongoDB Update Operation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Prepare Audit Update node extracts and structures the necessary update parameters.&lt;/li&gt;
&lt;li&gt;It determines:&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;The request ID from audit.id&lt;br&gt;
The auditor ID from msg.userId or msg.auth.userId&lt;br&gt;
The new status based on audit.auditDecision.status or audit.status&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;If no valid audit data is found, the message flow stops (return null).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Otherwise, it constructs a MongoDB &lt;code&gt;updateOne&lt;/code&gt; command &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Execute Database Update&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Update Request Record node (mongodb4) connects to the &lt;code&gt;hediyehTC&lt;/code&gt; MongoDB database.&lt;/li&gt;
&lt;li&gt;It applies the update operation defined in the previous node to the &lt;code&gt;Requests&lt;/code&gt; collection.&lt;/li&gt;
&lt;li&gt;The operation updates the record matching the provided request ID without inserting new records &lt;code&gt;(upsert: false)&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Generate Standardized Response&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;After a successful update, the change node sets a response object:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": "success",
  "action": "auditRequest",
  "message": "success"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;This response is stored in &lt;code&gt;msg.response&lt;/code&gt; for consistent backend–frontend communication.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Response Examples (uibuilder.onChange)
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Success Response
   {
    "status": "success",
    "action": "auditRequest",
    "message": "success"
    }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  MongoDB &lt;code&gt;Requests&lt;/code&gt; Collection Schema
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;_id&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Unique MongoDB document identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;id&lt;/td&gt;
&lt;td&gt;Number&lt;/td&gt;
&lt;td&gt;Internal record ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.userId&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;ID of the user who created the record&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.id&lt;/td&gt;
&lt;td&gt;Number&lt;/td&gt;
&lt;td&gt;Creator’s internal ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.fullName&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Name of the creator (e.g., David Kim)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.email&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Creator’s email address&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.avatarUrl&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Base64-encoded profile image URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.priority&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Task or request priority (e.g., low)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.status&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Current status (e.g., Approved)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.archive&lt;/td&gt;
&lt;td&gt;Boolean&lt;/td&gt;
&lt;td&gt;Indicates if the record is archived&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.timeEstimation&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Estimated completion time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.assignedTo&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Assigned user (empty if none)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;auditInfo&lt;/td&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;Audit tracking data (timestamps, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;approveInfo&lt;/td&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;Approval metadata or history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdAt&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;td&gt;Record creation timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;updatedAt&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;td&gt;Last update timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Sample document:
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "_id": "6907636ed6c4398ea5f5cd42",
  "id": 2,
  "createdBy": {
    "userId": "68f830f9d6c4398ea5f5cbdf",
    "id": 1,
    "fullName": "David Kim",
    "email": "david.kim@brightwave.co",
    "avatarUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxIQEhUSEhI…"
  },
  "companyDetails": {
    "priority": "low",
    "status": "Approved",
    "archive": false,
    "timeEstimation": "10 business day",
    "assignedTo": ""
  },
  "auditInfo": {},
  "approveInfo": {},
  "createdAt": "2025-11-02T13:58:06.411+00:00",
  "updatedAt": "2025-11-02T14:05:05.471+00:00"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  4.6.approveRequest Flow
&lt;/h1&gt;
&lt;h2&gt;
  
  
  High-Level Flow:
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Incoming _approveRequest
          ↓
 ┌─────────────────────────────────────┐
 │ Log Captured Approve Request        │
 │ Checks if _approveRequest exists    │
 │ → Logs full request for debugging   │
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ Prepare Approve Update              │
 │ - Extracts approve.id and userId    │
 │ - Determines decision and newStatus │
 │ - Builds updateOne query for MongoDB│
 │   to update status and approveInfo  │
 │   { date, approverId, comment }     │
 │ - Adds updatedAt timestamp          │
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ Update Request Record (MongoDB4)    │
 │ Executes updateOne on "Requests"    │
 │ collection to apply approval decision│
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ Change Node                         │
 │ Sets standardized response:         │
 │ {status:"success", action:"approveRequest"} │
 │ Prepares final output message       │
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ approveRequest (Debug)              │
 │ Displays final response in debug    │
 │ sidebar for verification            │
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ link out                            │
 │ Sends response to connected flows   │
 │ (e.g., UI or further processing)    │
 └─────────────────────────────────────┘


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Frontend approveRequest
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;       uibuilder.send({
                type: 'approveRequest',
                auth: {
                  userToken: this.getCookie('userToken'),
                  clientId: this.getCookie('uibuilder-client-id')
                },
                userId: this.profile.userId,
                requestId: req.id || req._id,
                approverDecision: { status: updatedStatus, date: approveDate, comment }
              });

              this.waitingForResponse = true;

              const updateLists = [this.applicantRequests, this.approverRequests, this.adminRequests];
              updateLists.forEach(list =&amp;gt; {
                const index = list.findIndex(r =&amp;gt; (r.id || r._id) === (req.id || req._id));
                if (index !== -1) {
                  list.splice(index, 1, {
                    ...list[index],
                    status: updatedStatus,
                    approveDate,
                    approveComment: comment
                  });
                }
              });
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Uses &lt;code&gt;uibuilder.send()&lt;/code&gt; to submit an approval decision.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payload includes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;type&lt;/strong&gt;: &lt;code&gt;"approveRequest"&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;auth&lt;/strong&gt;: User token and client ID from cookies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;userId&lt;/strong&gt;: ID of the approver&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;requestId&lt;/strong&gt;: Target request ID&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;approverDecision&lt;/strong&gt;: 

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;status&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;date&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;comment&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Set Waiting State&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;this.waitingForResponse = true&lt;/code&gt; indicates that the frontend is awaiting backend confirmation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Optimistic UI Update&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Updates local request lists immediately:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;applicantRequests&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;approverRequests&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;adminRequests&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Updates the matching request by ID:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;status&lt;/strong&gt; → Updated approval status&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;approveDate&lt;/strong&gt; → Date of approval&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;approveComment&lt;/strong&gt; → Approver comment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Provides instant feedback to the user while backend processing completes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ensures responsive UI and secure submission of approval decisions to the backend.&lt;/p&gt;
&lt;h2&gt;
  
  
  Sample Request Payload
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"{
  ""type"": ""approveRequest"",
  ""auth"": {
    ""userToken"": ""eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwidXNlclRva2VuIjoiU09NRV9SQU5ET01fVE9LRU5fMTc2MTYxODg3NTczNSIsInByb2ZpbGUiOnsidXNlcklkIjoiNjhmODM2MzhkNmM0Mzk4ZWE1ZjVjYmU2IiwiaWQiOjIsImVtYWlsIjoibGVpbGEuaGFzc2FuQHNreW5ldC5zeXN0ZW1zIiwicm9sZXMiOlsiQXBwbGljYW50IiwiQXBwcm92ZXIiXSwiZnVsbE5hbWUiOiJMZWlsYSBIYXNzYW4ifSwiYWN0aW9uIjoibG9naW4iLCJpYXQiOjE3NjE2MTg4NzUsImV4cCI6MTc2MTYyMjQ3NX0.yC6fr76smTVPPr0kCrmTARcJQ5qiuGqYKvl8_16rcts""
  },
  ""clientId"": ""DucPqZtrHFQNgOnyiGV02"",
  ""userId"": ""68f83638d6c4398ea5f5cbe6"",
  ""requestId"": 18,
  ""approverDecision"": {},
  ""_socketId"": ""fVUzLOHQeYT96ZrqAEla"",
  ""topic"": ""uibuilder"",
  ""_msgid"": ""b26bc97d28188""
}
"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Backend Node-RED Flow
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Log Captured Approve Request&lt;/td&gt;
&lt;td&gt;function&lt;/td&gt;
&lt;td&gt;Checks if &lt;code&gt;_approveRequest&lt;/code&gt; exists in the incoming message. Logs a warning if missing and logs the captured request for debugging if present. Passes the message to the next node.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prepare Approve Update&lt;/td&gt;
&lt;td&gt;function&lt;/td&gt;
&lt;td&gt;Extracts approval details from &lt;code&gt;msg._approveRequest&lt;/code&gt;. Determines the user ID from &lt;code&gt;msg.userId&lt;/code&gt; or &lt;code&gt;msg.auth.userId&lt;/code&gt;. If no valid approval data or ID is found, stops the flow. Otherwise, prepares a MongoDB &lt;code&gt;updateOne&lt;/code&gt; operation to update the &lt;code&gt;Requests&lt;/code&gt; collection with the new status, approver info (date, ID, comment, decision), and timestamp.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Update Request Record&lt;/td&gt;
&lt;td&gt;mongodb4&lt;/td&gt;
&lt;td&gt;Executes the prepared update operation in the &lt;code&gt;Requests&lt;/code&gt; collection of the &lt;code&gt;hediyehTC&lt;/code&gt; MongoDB database. Updates the record matching the approval request ID without inserting new records.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;approveRequest&lt;/td&gt;
&lt;td&gt;debug&lt;/td&gt;
&lt;td&gt;Displays the final message object in the Node-RED debug sidebar for verification, including the standardized response message.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;change&lt;/td&gt;
&lt;td&gt;change&lt;/td&gt;
&lt;td&gt;Sets &lt;code&gt;msg.response&lt;/code&gt; to a JSON object indicating success: &lt;code&gt;status: success&lt;/code&gt;, &lt;code&gt;action: approveRequest&lt;/code&gt;, and &lt;code&gt;message: success&lt;/code&gt;. Passes the message to debug and link-out nodes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;link out&lt;/td&gt;
&lt;td&gt;link out&lt;/td&gt;
&lt;td&gt;Forwards the processed message to another part of the flow (&lt;code&gt;1a592f68894d0c59&lt;/code&gt;), typically to send the response back to the frontend or trigger additional backend logic.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mongodb4-client&lt;/td&gt;
&lt;td&gt;mongodb4-client&lt;/td&gt;
&lt;td&gt;Provides the MongoDB connection to the &lt;code&gt;hediyehTC&lt;/code&gt; database on DigitalOcean, supporting secure TLS connection and pooling. Used by the &lt;code&gt;Update Request Record&lt;/code&gt; node for executing operations.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Backend Flow Summary
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Capture and Log the Incoming Approval Request&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Log Captured Approve Request&lt;/strong&gt; function node checks for the presence of &lt;code&gt;_approveRequest&lt;/code&gt; in the message.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;If missing&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Logs a warning.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;If present&lt;/strong&gt;: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Logs the full request object for debugging and traceability.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This ensures that all subsequent operations have valid approval data.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prepare MongoDB Update Operation&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Prepare Approve Update&lt;/strong&gt; function extracts the request and user details:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Approval request object&lt;/strong&gt;: &lt;code&gt;msg._approveRequest&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User ID&lt;/strong&gt;: &lt;code&gt;msg.userId&lt;/code&gt; or &lt;code&gt;msg.auth.userId&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Decision details&lt;/strong&gt;: 

&lt;ul&gt;
&lt;li&gt;Status&lt;/li&gt;
&lt;li&gt;Date&lt;/li&gt;
&lt;li&gt;Comment&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Validates that the approval request exists and has an ID. If not, the flow stops.&lt;/p&gt;

&lt;p&gt;Constructs a MongoDB &lt;code&gt;updateOne&lt;/code&gt; operation to ensure only the targeted request is updated with new approval info, without creating a new record.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Execute Database Update&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Update Request Record&lt;/strong&gt; node connects to the &lt;code&gt;hediyehTC&lt;/code&gt; MongoDB database.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Executes the prepared &lt;code&gt;updateOne&lt;/code&gt; operation to update the Requests collection.&lt;/li&gt;
&lt;li&gt;Ensures atomic and safe updates of request status and approver information.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Generate Standardized Response&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After a successful update, the change node sets a consistent response in &lt;code&gt;msg.response&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": "success",
  "action": "approveRequest",
  "message": "success"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows the frontend to handle success consistently for UI feedback.&lt;/p&gt;

&lt;h2&gt;
  
  
  Response Examples (uibuilder.onChange)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// Success Response
 {
    "status": "success",
    "action": "approveRequest",
    "message": "success"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  MongoDB &lt;code&gt;Requests&lt;/code&gt; Collection Schema
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;_id&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Unique MongoDB document identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;id&lt;/td&gt;
&lt;td&gt;Number&lt;/td&gt;
&lt;td&gt;Internal record ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.userId&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;ID of the user who created the record&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.id&lt;/td&gt;
&lt;td&gt;Number&lt;/td&gt;
&lt;td&gt;Creator’s internal ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.fullName&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Name of the creator (e.g., David Kim)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.email&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Creator’s email address&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.avatarUrl&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Base64-encoded profile image URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.priority&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Task or request priority (e.g., low)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.status&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Current status (e.g., Approved)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.archive&lt;/td&gt;
&lt;td&gt;Boolean&lt;/td&gt;
&lt;td&gt;Indicates if the record is archived&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.timeEstimation&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Estimated completion time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.assignedTo&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Assigned user (empty if none)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;auditInfo&lt;/td&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;Audit tracking data (timestamps, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;approveInfo&lt;/td&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;Approval metadata or history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdAt&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;td&gt;Record creation timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;updatedAt&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;td&gt;Last update timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Sample document:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "_id": "6907636ed6c4398ea5f5cd42",
  "id": 2,
  "createdBy": {
    "userId": "68f830f9d6c4398ea5f5cbdf",
    "id": 1,
    "fullName": "David Kim",
    "email": "david.kim@brightwave.co",
    "avatarUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxIQEhUSEhI…"
  },
  "companyDetails": {
    "priority": "low",
    "status": "Approved",
    "archive": false,
    "timeEstimation": "10 business day",
    "assignedTo": ""
  },
  "auditInfo": {},
  "approveInfo": {},
  "createdAt": "2025-11-02T13:58:06.411+00:00",
  "updatedAt": "2025-11-02T14:05:05.471+00:00"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  4.7.createRequest Flow
&lt;/h1&gt;

&lt;h2&gt;
  
  
  High-Level Flow:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Frontend sends request creation data
          ↓
 ┌─────────────────────────────────────┐
 │ Prepare Last Request Query           │
 │ - Extracts user info from payload   │
 │ - Builds MongoDB find query to get  │
 │   the last request (sort by id desc)│
 │ - Attaches companyDetails and user  │
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ Find Last Request (MongoDB4)        │
 │ - Executes find query to get last   │
 │   request to determine new requestId│
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ Build New Request Document           │
 │ - Calculates new request ID         │
 │ - Populates createdBy info (user)   │
 │ - Sets companyDetails, default status,│
 │   priority, archive, timeEstimation │
 │ - Initializes auditInfo and approveInfo │
 │ - Adds createdAt timestamp           │
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ Insert Request into MongoDB (MongoDB4) │
 │ - Inserts the new request document into│
 │   "Requests" collection               │
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ Prepare Response Data                │
 │ - Extracts key fields from request   │
 │ - Prepares payload for frontend:     │
 │   { id, status, companyDetails, auditDate,│
 │     auditorComment, timeEstimation } │
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ Change Node                          │
 │ - Sets standardized response:        │
 │   {status:"success", action:"createRequest"} │
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ success (Debug)                     │
 │ - Outputs response for verification │
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ link out / further processing       │
 │ - Sends response to connected flows │
 └─────────────────────────────────────┘
Frontend sends request creation data
          ↓
 ┌─────────────────────────────────────┐
 │ Prepare Last Request Query           │
 │ - Extracts user info from payload   │
 │ - Builds MongoDB find query to get  │
 │   the last request (sort by id desc)│
 │ - Attaches companyDetails and user  │
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ Find Last Request (MongoDB4)        │
 │ - Executes find query to get last   │
 │   request to determine new requestId│
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ Build New Request Document           │
 │ - Calculates new request ID         │
 │ - Populates createdBy info (user)   │
 │ - Sets companyDetails, default status,│
 │   priority, archive, timeEstimation │
 │ - Initializes auditInfo and approveInfo │
 │ - Adds createdAt timestamp           │
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ Insert Request into MongoDB (MongoDB4) │
 │ - Inserts the new request document into│
 │   "Requests" collection               │
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ Prepare Response Data                │
 │ - Extracts key fields from request   │
 │ - Prepares payload for frontend:     │
 │   { id, status, companyDetails, auditDate,│
 │     auditorComment, timeEstimation } │
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ Change Node                          │
 │ - Sets standardized response:        │
 │   {status:"success", action:"createRequest"} │
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ success (Debug)                     │
 │ - Outputs response for verification │
 └─────────────────────────────────────┘
          ↓
 ┌─────────────────────────────────────┐
 │ link out / further processing       │
 │ - Sends response to connected flows │
 └─────────────────────────────────────┘



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Frontend createRequest
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    uibuilder.send({
            type: 'createRequest',
            auth: {
              userToken: this.getCookie('userToken'),
              clientId: this.getCookie('uibuilder-client-id')
            },
            companyDetails: { ...this.formData }
          });

          this.waitingForResponse = true;

            setTimeout(() =&amp;gt; {
              if (this.waitingForResponse) {
                this.showNotification('Network error! Please refresh.', 'error');
                this.waitingForResponse = false;
                this.submissionSuccess = false;
                this.closeModal(); // optional: close modal automatically
              }
           }, 6000);

        },
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Uses &lt;code&gt;uibuilder.send()&lt;/code&gt; to submit a new request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payload includes:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;type&lt;/strong&gt;: "createRequest"&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;auth&lt;/strong&gt;: User token and client ID from cookies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;companyDetails&lt;/strong&gt;: Form data from the user&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Set Waiting State&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;this.waitingForResponse = true&lt;/code&gt; indicates the frontend is waiting for backend confirmation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Error Handling / Timeout&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sets a &lt;strong&gt;6-second timeout&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;If no response:

&lt;ul&gt;
&lt;li&gt;Displays a network error notification.&lt;/li&gt;
&lt;li&gt;Resets &lt;code&gt;waitingForResponse&lt;/code&gt; and &lt;code&gt;submissionSuccess&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Optionally closes the modal.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Ensures secure submission of new requests to the backend with responsive feedback to the user while handling potential network issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sample Request Payload
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "type": "createRequest",
  "auth": {
    "userToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwidXNlclRva2VuIjoiU09NRV9SQU5ET01fVE9LRU5fMTc2MTYxNjk5NjI1NSIsInByb2ZpbGUiOnsidXNlcklkIjoiNjhmODMwZjlkNmM0Mzk4ZWE1ZjVjYmRmIiwiaWQiOjEsImVtYWlsIjoiZGF2aWQua2ltQGJyaWdodHdhdmUuY28iLCJyb2xlcyI6WyJBcHBsaWNhbnQiLCJBdWRpdG9yIl0sImZ1bGxOYW1lIjoiRGF2aWQgS2ltIn0sImFjdGlvbiI6ImxvZ2luIiwiaWF0IjoxNzYxNjE2OTk2LCJleHAiOjE3NjE2MjA1OTZ9.I0hARpxoFQPfZjfn5ZqjV-sRJO6SKpAw7KZBR4mH6iI"
  },
  "clientId": "DucPqZtrHFQNgOnyiGV02",
  "companyDetails": {},
  "_socketId": "0KAO_QB8U2vpv5xDAElI",
  "topic": "uibuilder",
  "_msgid": "46c1c3b28576"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Backend Node-RED Flow
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Node Name&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;success&lt;/td&gt;
&lt;td&gt;debug&lt;/td&gt;
&lt;td&gt;Displays the final message in the Node-RED debug sidebar for verification of the request creation process.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Build New Request Document&lt;/td&gt;
&lt;td&gt;function&lt;/td&gt;
&lt;td&gt;Extracts the last request to determine a new &lt;code&gt;id&lt;/code&gt;. Extracts user information from &lt;code&gt;msg.user&lt;/code&gt; and company details from &lt;code&gt;msg.companyDetails&lt;/code&gt; or &lt;code&gt;msg.auth&lt;/code&gt;. Prepares a new request object with default fields (&lt;code&gt;status: Pending&lt;/code&gt;, &lt;code&gt;priority: low&lt;/code&gt;, &lt;code&gt;auditInfo&lt;/code&gt;, &lt;code&gt;approveInfo&lt;/code&gt;, etc.) and sets &lt;code&gt;msg.collection&lt;/code&gt; to &lt;code&gt;Requests&lt;/code&gt; with &lt;code&gt;insertOne&lt;/code&gt; operation. Stores the new request in &lt;code&gt;msg.request&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Insert Request into MongoDB&lt;/td&gt;
&lt;td&gt;mongodb4&lt;/td&gt;
&lt;td&gt;Executes the &lt;code&gt;insertOne&lt;/code&gt; operation to add the newly built request document to the &lt;code&gt;Requests&lt;/code&gt; collection in the &lt;code&gt;hediyehTC&lt;/code&gt; database.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prepare Last Request Query&lt;/td&gt;
&lt;td&gt;function&lt;/td&gt;
&lt;td&gt;Prepares a MongoDB &lt;code&gt;find&lt;/code&gt; query to retrieve the last request document, sorted by &lt;code&gt;id&lt;/code&gt; descending, limited to 1. Passes user info and company details along for the next node.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Find Last Request&lt;/td&gt;
&lt;td&gt;mongodb4&lt;/td&gt;
&lt;td&gt;Executes the &lt;code&gt;find&lt;/code&gt; query to fetch the last request from the &lt;code&gt;Requests&lt;/code&gt; collection. Outputs the result as an array for the next function node to calculate the new request ID.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prepare Response Data&lt;/td&gt;
&lt;td&gt;function&lt;/td&gt;
&lt;td&gt;Formats the inserted request data into a simplified response object, including &lt;code&gt;archive&lt;/code&gt;, &lt;code&gt;auditDate&lt;/code&gt;, &lt;code&gt;auditorComment&lt;/code&gt;, &lt;code&gt;companyDetails&lt;/code&gt;, &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;status&lt;/code&gt;, &lt;code&gt;timeEstimation&lt;/code&gt;, and &lt;code&gt;title&lt;/code&gt;.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;change&lt;/td&gt;
&lt;td&gt;change&lt;/td&gt;
&lt;td&gt;Sets a standardized &lt;code&gt;msg.response&lt;/code&gt; JSON object indicating success (&lt;code&gt;status: success&lt;/code&gt;, &lt;code&gt;action: createRequest&lt;/code&gt;, &lt;code&gt;message: success&lt;/code&gt;). Passes the message to debug and link-out nodes.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;mongodb4-client&lt;/td&gt;
&lt;td&gt;mongodb4-client&lt;/td&gt;
&lt;td&gt;Provides the MongoDB connection to the &lt;code&gt;hediyehTC&lt;/code&gt; database, with TLS security and connection pooling. Used by the MongoDB nodes to perform find and insert operations.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Backend Flow Summary
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Retrieve Last Request&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Prepare Last Request Query&lt;/strong&gt; node constructs a MongoDB find query:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Collection&lt;/strong&gt;: Requests&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Sorted by&lt;/strong&gt;: ID descending&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Limit&lt;/strong&gt;: 1&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The &lt;strong&gt;Find Last Request&lt;/strong&gt; node executes this query to fetch the last request in the collection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Determine the next request ID for the new request.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Build New Request Document&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Build New Request Document&lt;/strong&gt; node:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Calculates &lt;code&gt;newId&lt;/code&gt; based on the last request ID.&lt;/li&gt;
&lt;li&gt;Extracts user information from &lt;code&gt;msg.user&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Extracts company details from &lt;code&gt;msg.companyDetails&lt;/code&gt; or &lt;code&gt;msg.auth&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Builds a request object with default fields:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;status&lt;/strong&gt;: Pending&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;priority&lt;/strong&gt;: low&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;timeEstimation&lt;/strong&gt;: 10 business days&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;auditInfo&lt;/strong&gt;: initialized as null&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;approveInfo&lt;/strong&gt;: initialized as null&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;createdAt&lt;/strong&gt;: timestamp&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Sets &lt;code&gt;msg.collection&lt;/code&gt; to Requests and operation to &lt;code&gt;insertOne&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Insert Request into MongoDB&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Insert Request into MongoDB&lt;/strong&gt; node performs the &lt;code&gt;insertOne&lt;/code&gt; operation on the Requests collection.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ensures&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The new request is saved atomically in the database.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prepare Response Data&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;Prepare Response Data&lt;/strong&gt; node formats the inserted request into a simplified response object for the frontend:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fields include:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;archive&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;auditDate&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;auditorComment&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;companyDetails&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;id&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;status&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;timeEstimation&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;title&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Generate Standardized Response&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The change node sets &lt;code&gt;msg.response&lt;/code&gt; with a standard JSON structure:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": "success",
  "action": "createRequest",
  "message": "success"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;The success debug node logs this response for verification.&lt;/li&gt;
&lt;li&gt;The message can then be sent back to the frontend via a link-out node.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Response Examples (uibuilder.onChange)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "status": "success",
  "action": "createRequest",
  "message": "Request created successfully."
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  MongoDB &lt;code&gt;Requests&lt;/code&gt; Collection Schema
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Field&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;_id&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Unique MongoDB document identifier&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;id&lt;/td&gt;
&lt;td&gt;Number&lt;/td&gt;
&lt;td&gt;Internal record ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.userId&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;ID of the user who created the record&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.id&lt;/td&gt;
&lt;td&gt;Number&lt;/td&gt;
&lt;td&gt;Creator’s internal ID&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.fullName&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Name of the creator (e.g., David Kim)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.email&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Creator’s email address&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdBy.avatarUrl&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Base64-encoded profile image URL&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.priority&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Task or request priority (e.g., low)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.status&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Current status (e.g., Approved)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.archive&lt;/td&gt;
&lt;td&gt;Boolean&lt;/td&gt;
&lt;td&gt;Indicates if the record is archived&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.timeEstimation&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Estimated completion time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;companyDetails.assignedTo&lt;/td&gt;
&lt;td&gt;String&lt;/td&gt;
&lt;td&gt;Assigned user (empty if none)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;auditInfo&lt;/td&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;Audit tracking data (timestamps, etc.)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;approveInfo&lt;/td&gt;
&lt;td&gt;Object&lt;/td&gt;
&lt;td&gt;Approval metadata or history&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createdAt&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;td&gt;Record creation timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;updatedAt&lt;/td&gt;
&lt;td&gt;DateTime&lt;/td&gt;
&lt;td&gt;Last update timestamp&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Sample document:
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "_id": "6907636ed6c4398ea5f5cd42",
  "id": 2,
  "createdBy": {
    "userId": "68f830f9d6c4398ea5f5cbdf",
    "id": 1,
    "fullName": "David Kim",
    "email": "david.kim@brightwave.co",
    "avatarUrl": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxIQEhUSEhI…"
  },
  "companyDetails": {
    "priority": "low",
    "status": "Approved",
    "archive": false,
    "timeEstimation": "10 business day",
    "assignedTo": ""
  },
  "auditInfo": {},
  "approveInfo": {},
  "createdAt": "2025-11-02T13:58:06.411+00:00",
  "updatedAt": "2025-11-02T14:05:05.471+00:00"
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h1&gt;
  
  
  UIBuilder Authentication Flow Overview
&lt;/h1&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Flow Overview&lt;/th&gt;
&lt;th&gt;Collections / Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;signup&lt;/td&gt;
&lt;td&gt;Handles new user registration and account creation.&lt;/td&gt;
&lt;td&gt;Users — A new record is added with details such as fullName, email, password, and role. Validation ensures the email is unique before saving.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;login&lt;/td&gt;
&lt;td&gt;Authenticates existing users and establishes a secure session.&lt;/td&gt;
&lt;td&gt;Users — Validates credentials (email, password). Tokens — Generates a new authentication token to manage the session and track expiration.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sendResetCode&lt;/td&gt;
&lt;td&gt;Initiates the password recovery process when a user requests to reset their password.&lt;/td&gt;
&lt;td&gt;PasswordResets — Creates a record with a verification code, userId, email, createdAt, and expiresAt. This is used to validate the reset request.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;resendResetPassword&lt;/td&gt;
&lt;td&gt;Resends the password reset code when the previous one expires or is lost.&lt;/td&gt;
&lt;td&gt;PasswordResets — Updates or regenerates a reset code and resends it to the registered email.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;setNewPassword&lt;/td&gt;
&lt;td&gt;Updates the password after the reset code is verified.&lt;/td&gt;
&lt;td&gt;PasswordResets — Marks the code as “used.” Users — Updates the password field for the corresponding account.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;resetPassword&lt;/td&gt;
&lt;td&gt;Finalizes password change after user validation, ensuring secure update of credentials.&lt;/td&gt;
&lt;td&gt;Users — Commits the new password. PasswordResets — Confirms the reset process is completed and the code is invalidated.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h1&gt;
  
  
  UIBuilder Dashboard Flow Overview
&lt;/h1&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Flow Overview&lt;/th&gt;
&lt;th&gt;Collections / Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;getDashboard&lt;/td&gt;
&lt;td&gt;Retrieves and displays user-specific dashboard data such as pending, approved, or audited requests.&lt;/td&gt;
&lt;td&gt;Requests — Fetches request data based on user role and status. Users — Determines user role to tailor dashboard view.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;editCompanyDetails&lt;/td&gt;
&lt;td&gt;Allows users (e.g., Applicants) to update company-related information in an existing request.&lt;/td&gt;
&lt;td&gt;Requests — Updates companyDetails fields for a specific requestId. Includes validation and status tracking for edited data.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;archiveRequest&lt;/td&gt;
&lt;td&gt;Moves completed or inactive requests to an archived state to declutter active dashboards.&lt;/td&gt;
&lt;td&gt;Requests — Sets the archive flag to true to mark the request as archived while preserving its existing status for historical tracking and filtered retrieval.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;editProfile&lt;/td&gt;
&lt;td&gt;Enables users to modify their personal information such as full name, email, or password.&lt;/td&gt;
&lt;td&gt;Users — Updates user profile fields.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;auditRequest&lt;/td&gt;
&lt;td&gt;Used by an Auditor to review and mark requests as “Audited.”&lt;/td&gt;
&lt;td&gt;Requests — Updates the status to “Audited” and records auditor details (userId, timestamp, comments).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;approveRequest&lt;/td&gt;
&lt;td&gt;Allows Approvers to review and mark a request as “Approved.”&lt;/td&gt;
&lt;td&gt;Requests — Updates the status to “Approved” and logs approver information. May trigger notification workflows.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createRequest&lt;/td&gt;
&lt;td&gt;Initiates a new request submission by an Applicant.&lt;/td&gt;
&lt;td&gt;Requests — Creates a new record containing companyDetails, userId, status, and timestamps. Users — Associates request with the creator’s user profile.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Collections Overview
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Collection&lt;/th&gt;
&lt;th&gt;Collection Overview&lt;/th&gt;
&lt;th&gt;Contains / Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;PasswordResets&lt;/td&gt;
&lt;td&gt;The Password Reset Collection is used to manage and validate password reset requests in the system.&lt;/td&gt;
&lt;td&gt;Fields such as &lt;code&gt;_id&lt;/code&gt;, &lt;code&gt;code&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;userId&lt;/code&gt;, &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;createdAt&lt;/code&gt;, &lt;code&gt;expiresAt&lt;/code&gt;, and &lt;code&gt;used&lt;/code&gt; — used to track temporary password reset codes, their status, and validity period.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Requests&lt;/td&gt;
&lt;td&gt;Stores user-submitted requests (e.g., access, approvals, or application actions).&lt;/td&gt;
&lt;td&gt;Fields like &lt;code&gt;requestId&lt;/code&gt;, &lt;code&gt;userId&lt;/code&gt;, &lt;code&gt;status&lt;/code&gt;, &lt;code&gt;companyDetails&lt;/code&gt;, and timestamps — representing workflow requests and their approval states.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Tokens&lt;/td&gt;
&lt;td&gt;Handles session and authentication tokens for secure user access.&lt;/td&gt;
&lt;td&gt;Contains &lt;code&gt;token&lt;/code&gt;, &lt;code&gt;userId&lt;/code&gt;, &lt;code&gt;issuedAt&lt;/code&gt;, &lt;code&gt;expiresAt&lt;/code&gt; — used to authenticate users and manage session expiration.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Users&lt;/td&gt;
&lt;td&gt;Maintains registered user account information.&lt;/td&gt;
&lt;td&gt;Includes fields such as &lt;code&gt;userId&lt;/code&gt;, &lt;code&gt;fullName&lt;/code&gt;, &lt;code&gt;email&lt;/code&gt;, &lt;code&gt;password&lt;/code&gt;, &lt;code&gt;roles&lt;/code&gt;, and profile metadata. Roles define access and permissions in the system and may include: Admin, Applicant, Applicant &amp;amp; Approver, or Applicant &amp;amp; Auditor.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Request and Response
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Request Payload&lt;/th&gt;
&lt;th&gt;Response Payload&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;signup&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "auth": {}, "clientId": "oD6i_WpIes8pBvWjNXy81", "fullName": "hediyeh", "email": "h@gmail.com", "password": "111111", "confirmPassword": "111111", "type": "signup", "_socketId": "kmN2iMG_VAMQ7WSFAEhJ", "topic": "uibuilder", "_msgid": "96c8e068f17bef90" }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;// Failure Response { "action": "register", "status": "failed", "message": "Email already exists. Please use a different email." } // Success Response { "action": "register", "status": "success", "message": "You have registered successfully!", "URL": "https://codenxa.leanea.com/hediyeh/signin" }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;login&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "auth": {}, "clientId": "oD6i_WpIes8pBvWjNXy81", "email": "h@gmail.com", "password": "111111", "rememberMe": false, "type": "login", "_socketId": "70nLJLlIrgzsiFLpAEhQ", "topic": "uibuilder", "_msgid": "2e88832acfbcd402" }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;// Failure Response 1 { "action": "login", "status": "invalidCredentials", "message": "Email not found." } // Failure Response 2 { "action": "login", "status": "invalidCredentials", "message": "Password does not match." } // Success Response { "action": "login", "status": "success", "message": "Logged In Successfully" }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;logOut&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "type": "logOut", "auth": {}, "userToken": "...", "clientId": "DucPqZtrHFQNgOnyiGV02", "_socketId": "0TlVsj-P27gZSW9TAEhb", "topic": "uibuilder", "_msgid": "9cfd70eb231eb96c" }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;// Success Response: Typically { "status": "success", "action": "logOut", "message": "Logged out successfully" }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;sendResetCode&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ auth: object, type: "sendResetCode", email: "david.kim@brightwave.co", code: "373600", _socketId: "WGHrhQQe1a8e0uh4AFZJ", topic: "TrustedCloud Password Reset Code – Action Required" }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;// Failure Response 1 { "action": "resetPassword", "status": "invalidCode", "message": "code not found" } // Failure Response 2 { "action": "resetPassword", "status": "expired", "message": "your code has been expired" } // Success Response { "action": "resetPassword", "status": "validCode", "message": "Code matched successfully" }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;resetPassword&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "auth": {}, "type": "resetPassword", "email": "h@gmail.com", "_socketId": "TQQZkMEJW3yr8AXbAEhi", "topic": "uibuilder", "_msgid": "563ae2fa2bd25a81" }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;// Failure Responses // Invalid Email { "action": "sendResetCode", "status": "invalidEmail", "message": "Email address not found." } // Invalid User { "action": "setNewPassword", "status": "invalidUser", "message": "User not found." } // Success Responses { "action": "setNewPassword", "status": "success", "message": "Password updated successfully." }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;resendResetPassword&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "auth": {}, "email": "h@gmail.com", "type": "resendResetPassword", "_socketId": "TQQZkMEJW3yr8AXbAEhi", "topic": "TrustedCloud Password Reset Code – Action Required", "_msgid": "a8539873adf09c69" }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;// Failure Response { "action": "resetPassword", "status": "invalidEmail", "message": "Email address not found." } // Success Response { "action": "resetPassword", "status": "validEmail", "message": "Reset code sent to your email" }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;setNewPassword&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "auth": {}, "type": "setNewPassword", "email": "h@gmail.com", "password": "123456", "_socketId": "3hHNyKWUI-Khbn9cAEh0", "topic": "TrustedCloud Password Reset Code – Action Required", "_msgid": "4a86446e49c05025" }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "action": "setNewPassword", "status": "success", "message": "Password updated successfully." }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;archiveRequest&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "type": "archiveRequest", "auth": { "userToken": "..." }, "clientId": "DucPqZtrHFQNgOnyiGV02", "requestID": 13, "_socketId": "0KAO_QB8U2vpv5xDAElI", "topic": "uibuilder", "_msgid": "7c5fc73c0374d772" }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "status": "success", "action": "archiveRequest", "message": "success" }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;editCompanyDetails&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "type": "editCompanyDetails", "auth": { "userToken": "..." }, "clientId": "DucPqZtrHFQNgOnyiGV02", "companyDetails": {}, "_socketId": "0KAO_QB8U2vpv5xDAElI", "topic": "uibuilder", "_msgid": "318f5048ec2d" }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "status": "success", "action": "editCompanyDetails", "message": "success" }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;editProfile&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "type": "editProfile", "auth": { "userToken": "..." }, "clientId": "DucPqZtrHFQNgOnyiGV02", "profile": { ... }, "_socketId": "0KAO_QB8U2vpv5xDAElI", "topic": "uibuilder", "_msgid": "37a193fd9e74e" }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "status": "success", "action": "editProfile", "message": "success" }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;auditRequest&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "type": "auditRequest", "auth": { "userToken": "..." }, "clientId": "DucPqZtrHFQNgOnyiGV02", "userId": "68f830f9d6c4398ea5f5cbdf", "requestId": 18, "auditDecision": { "status": "Audited", "auditDate": "2025-10-28", "comment": "yes" }, "_socketId": "0KAO_QB8U2vpv5xDAElI", "topic": "uibuilder", "_msgid": "196c7d70d5cc4" }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "status": "success", "action": "auditRequest", "message": "success" }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;approveRequest&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "type": "approveRequest", "auth": { "userToken": "..." }, "clientId": "DucPqZtrHFQNgOnyiGV02", "userId": "68f83638d6c4398ea5f5cbe6", "requestId": 18, "approverDecision": {}, "_socketId": "fVUzLOHQeYT96ZrqAEla", "topic": "uibuilder", "_msgid": "b26bc97d28188" }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "status": "success", "action": "approveRequest", "message": "success" }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;createRequest(Applicant)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "type": "createRequest", "auth": { "userToken": "..." }, "clientId": "DucPqZtrHFQNgOnyiGV02", "companyDetails": {}, "_socketId": "0KAO_QB8U2vpv5xDAElI", "topic": "uibuilder", "_msgid": "46c1c3b28576" }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "status": "success", "action": "createRequest", "message": "Request created successfully." }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;getDashboard(Applicant &amp;amp; Auditor)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "type": "getDashboard", "auth": {}, "userToken": "...", "clientId": "DucPqZtrHFQNgOnyiGV02", "_socketId": "X6ZKjzzFvV-ibjhwAEiI", "_msgid": "8bd0ae08cdfe06a9" }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "type": "getDashboard", "payload": { "applicantRequests": [/* ... */], "auditorRequests": [/* ... */] } }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;getDashboard(Applicant &amp;amp; Approver)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "type": "getDashboard", "auth": {}, "userToken": "...", "clientId": "DucPqZtrHFQNgOnyiGV02", "_socketId": "X6ZKjzzFvV-ibjhwAEiI", "_msgid": "8bd0ae08cdfe06a9" }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "type": "getDashboard", "payload": { "applicantRequests": [], "approverRequests": [{},{},{},{}] } }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;getDashboard(Admin)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "type": "getDashboard", "auth": {}, "userToken": "...", "clientId": "DucPqZtrHFQNgOnyiGV02", "_socketId": "X6ZKjzzFvV-ibjhwAEiI", "_msgid": "8bd0ae08cdfe06a9" }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "type": "getDashboard", "payload": { "requests": [{}], "profile": {}, "options": {} } }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;getDashboard(Applicant)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "type": "getDashboard", "auth": {}, "userToken": "...", "clientId": "DucPqZtrHFQNgOnyiGV02", "_socketId": "X6ZKjzzFvV-ibjhwAEiI", "_msgid": "8bd0ae08cdfe06a9" }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;{ "type": "getDashboard", "payload": { "applicantRequests": [{ "_id": "68ffe1e7d6c4398ea5f5cd08", "id": 18, "status": "Pending", ... }] } }&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
    </item>
    <item>
      <title>Irancell IAM Database Migration</title>
      <dc:creator>hediyeh kianmehr</dc:creator>
      <pubDate>Tue, 28 Oct 2025 15:15:25 +0000</pubDate>
      <link>https://dev.to/hediyeh_kianmehr_45f78137/db-10o5</link>
      <guid>https://dev.to/hediyeh_kianmehr_45f78137/db-10o5</guid>
      <description>&lt;p&gt;&lt;strong&gt;Overview&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This document provides a step-by-step guide to migrating Irancell IAM databases from a local environment to a remote database server. It covers the entire process, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Backing up existing databases (openiam and activiti) from the local IAM machine.&lt;/li&gt;
&lt;li&gt;Setting up MariaDB on a new remote server and configuring it for remote access.&lt;/li&gt;
&lt;li&gt;Creating necessary databases and users on the new server.&lt;/li&gt;
&lt;li&gt;Importing the database dumps into the new server.&lt;/li&gt;
&lt;li&gt;Updating Irancell IAM configuration to point to the new database server and restarting services.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By following this guide, administrators can safely migrate Irancell IAM’s data  and ensuring that all users, tables, and application data are preserved.&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Purpose&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The purpose of this document is to describe the process of migrating the database from the &lt;strong&gt;local environment&lt;/strong&gt; to a &lt;strong&gt;remote environment&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Current setup: A machine with IAM and its database installed locally.&lt;/li&gt;
&lt;li&gt;Target setup: A machine that will act as the &lt;strong&gt;main (remote)&lt;/strong&gt; database server.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;During the Irancell IAM installation process, the installer prompts whether to install the &lt;strong&gt;database locally&lt;/strong&gt;.&lt;br&gt;
Refer to the &lt;a href="https://dev.to/hediyeh_kianmehr_45f78137/-openiam-installation-guide-dom"&gt;Irancell IAM Installation Guide&lt;/a&gt;. for more details.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Installing the database locally is considered a best practice.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The database currently installed on the machine with &lt;strong&gt;IAM&lt;/strong&gt; will be migrated to a &lt;strong&gt;new machine&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
To achieve this, we need to &lt;strong&gt;dump all tables&lt;/strong&gt; from the existing database on the IAM machine.&lt;br&gt;&lt;br&gt;
This process will create a &lt;strong&gt;database dump file&lt;/strong&gt; that contains all the data and user accounts required for the migration.&lt;/p&gt;
&lt;/blockquote&gt;


&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Step 1: Create a Backup Directory on the IAM Machine&lt;/li&gt;
&lt;li&gt;Step 2: Create the Database Dump File in the Backups Directory&lt;/li&gt;
&lt;li&gt;
Step 3: Create Database Dumps

&lt;ul&gt;
&lt;li&gt;Creating a Dump of the openiam Database&lt;/li&gt;
&lt;li&gt;Creating a Dump of the activiti Database&lt;/li&gt;
&lt;li&gt;Notes on Passwords&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
Step 4: Prepare the New Remote Database Server

&lt;ul&gt;
&lt;li&gt;Installing MariaDB on the New Machine&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Step 5: Create Databases and Users&lt;/li&gt;
&lt;li&gt;Step 6: Import Database Dumps&lt;/li&gt;
&lt;li&gt;Step 7: Update Irancell IAM Configuration&lt;/li&gt;
&lt;/ol&gt;


&lt;h2&gt;
  
  
  Step 1: Create a Backup Directory on the IAM Machine
&lt;/h2&gt;

&lt;p&gt;First, create a directory named &lt;code&gt;backups&lt;/code&gt; in &lt;code&gt;/var&lt;/code&gt; on the machine with &lt;strong&gt;IAM&lt;/strong&gt; to store the database dump file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mkdir /var/backups
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 2: Create the Database Dump File in the Backups Directory
&lt;/h2&gt;

&lt;p&gt;Navigate to the &lt;strong&gt;backups&lt;/strong&gt; directory and create a dump of the &lt;code&gt;openiam-db&lt;/code&gt; database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mkdir /var/backups/openiam-db
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Step 3: Create Database Dumps
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;  &lt;/p&gt;

&lt;p&gt;We have two databases, &lt;strong&gt;activiti&lt;/strong&gt; and &lt;strong&gt;openiam&lt;/strong&gt;, each containing many tables, and both are hosted in &lt;strong&gt;MariaDB&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
 To create dump files for migration, we will need to run &lt;strong&gt;two separate commands&lt;/strong&gt;, one for each database.&lt;/p&gt;
&lt;h4&gt;
  
  
  Creating a Dump of the openiam Database and the activiti Database
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Log in with root user 
&lt;code&gt;Linux root password&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;su - 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Set the date variable&lt;/strong&gt; (so the dump file includes the current date):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DATE=$(date +%F)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the &lt;code&gt;${DATE}&lt;/code&gt; variable in the dump command to generate a timestamped backup&lt;/p&gt;

&lt;p&gt;To create a backup of the &lt;strong&gt;openiam&lt;/strong&gt; database using &lt;code&gt;mysqldump&lt;/code&gt; and the &lt;code&gt;root&lt;/code&gt; user, run the following commands:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; mysqldump -u root -p --single-transaction --routines --triggers --events --hex-blob openiam &amp;gt; /var/backups/openiam-db/openiam_${DATE}.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; mysqldump -u root -p   --single-transaction --routines --triggers --events --hex-blob   activiti &amp;gt; /var/backups/openiam-db/activiti_${DATE}.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Notes on Passwords&lt;/strong&gt;&lt;br&gt;
When you run the command, you will be asked for a password (&lt;code&gt;Database root password&lt;/code&gt;) &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;note:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;After completing the dump process, you should see &lt;strong&gt;two database dump files&lt;/strong&gt; containing all the database data on the machine with &lt;strong&gt;IAM&lt;/strong&gt;.&lt;br&gt;
You can now proceed to the next steps.&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 4: Prepare the New Remote Database Server
&lt;/h2&gt;

&lt;p&gt;Now, we should open the &lt;strong&gt;new machine&lt;/strong&gt;, which currently has no data, and prepare it to host the database that we want to migrate.&lt;/p&gt;
&lt;h3&gt;
  
  
  Installing MariaDB on the New Machine
&lt;/h3&gt;

&lt;p&gt;To install &lt;strong&gt;MariaDB&lt;/strong&gt;, follow the steps below in order:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt -y install mariadb-server
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Check if &lt;strong&gt;MariaDB&lt;/strong&gt; is running:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl status mariadb --no-pager 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi1nlbor5cvktehn91ex0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi1nlbor5cvktehn91ex0.jpg" alt=" " width="731" height="210"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can check the installed &lt;strong&gt;MariaDB version&lt;/strong&gt; with the following command:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mysql --version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;run the following command and enter the &lt;strong&gt;root password&lt;/strong&gt; when prompted:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mysql_secure_installation
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;During the process, answer the questions in the &lt;strong&gt;following order&lt;/strong&gt;:&lt;br&gt;
&lt;code&gt;N/Y/Y/Y/Y&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;To allow remote access to MariaDB, open port &lt;strong&gt;3306&lt;/strong&gt; with the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo ufw allow 3306/tcp || true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It changes the &lt;strong&gt;MariaDB&lt;/strong&gt; server’s bind address so that it listens on all network interfaces &lt;code&gt;(0.0.0.0)&lt;/code&gt; instead of just &lt;code&gt;127.0.0.1&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;That means:&lt;br&gt;
The database can now accept connections from other machines on the network, &lt;strong&gt;not only from localhost&lt;/strong&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo sed -i 's/^\s*bind-address\s*=.*/bind-address = 0.0.0.0/' /etc/mysql/mariadb.conf.d/50-server.cnf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the &lt;strong&gt;MariaDB&lt;/strong&gt; config file doesn’t already define a character-set-server, then append &lt;strong&gt;UTF-8 (utf8mb4)&lt;/strong&gt; settings to it.”&lt;br&gt;
&lt;strong&gt;MariaDB&lt;/strong&gt; will start using &lt;strong&gt;UTF-8 encoding&lt;/strong&gt; by default for all databases and tables.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo bash -lc 'grep -q "character-set-server" /etc/mysql/mariadb.conf.d/50-server.cnf || \
&amp;gt;   printf "\n[mysqld]\ncharacter-set-server = utf8mb4\ncollation-server = utf8mb4_unicode_ci\n" | sudo tee -a /etc/mysql/mariadb.conf.d/50-server.cnf'
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Restart MariaDB&lt;/strong&gt; to apply the configuration changes:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl restart mariadb --no-pager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Check the &lt;strong&gt;status&lt;/strong&gt; of the MariaDB service:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;systemctl status mariadb --no-pager
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;note:&lt;/strong&gt;&lt;br&gt;
After running the status command, you should see &lt;strong&gt;active (running)&lt;/strong&gt; in the output, indicating that &lt;strong&gt;MariaDB is running correctly&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You can see the MariaDB &lt;strong&gt;version&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mysql -u root -p -e "SELECT VERSION();"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;You will be prompted to enter the &lt;strong&gt;database user password&lt;/strong&gt;.&lt;br&gt;&lt;br&gt;
&lt;code&gt;Enter the password for the database user to proceed.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The database has now been created successfully.&lt;/em&gt;  &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Next, you should &lt;strong&gt;create the tables&lt;/strong&gt; for both &lt;strong&gt;activiti&lt;/strong&gt; and &lt;strong&gt;openiam&lt;/strong&gt;, and then &lt;strong&gt;import the corresponding dump files&lt;/strong&gt; into them.&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;To create the necessary databases and tables, follow these steps:&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 5: Create Databases and Users
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE DATABASE openiam CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE DATABASE activiti CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Insert the following commands &lt;strong&gt;one by one&lt;/strong&gt; to create the users, assign privileges, and finally apply the changes:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE USER 'idmuser'@'%' IDENTIFIED BY 'idmuser';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE USER 'activiti'@'%' IDENTIFIED BY 'activiti';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GRANT ALL PRIVILEGES ON openiam.* TO 'idmuser'@'%';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GRANT ALL PRIVILEGES ON activiti.* TO 'activiti'@'%';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE USER 'idmuser'@'localhost' IDENTIFIED BY 'idmuser';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE USER 'activiti'@'localhost' IDENTIFIED BY 'activiti';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GRANT ALL PRIVILEGES ON openiam.* TO 'idmuser'@'localhost';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GRANT ALL PRIVILEGES ON activiti.* TO 'activiti'@'localhost';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FLUSH PRIVILEGES;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;The databases are now ready.&lt;br&gt;&lt;br&gt;
The next step is to &lt;strong&gt;import the dump files&lt;/strong&gt; into the respective databases (&lt;code&gt;openiam&lt;/code&gt; and &lt;code&gt;activiti&lt;/code&gt;).&lt;/p&gt;


&lt;h2&gt;
  
  
  Step 6: Import Database Dumps
&lt;/h2&gt;

&lt;p&gt;Source (Machine with Dumps) → Destination (Database Machine):&lt;/p&gt;

&lt;p&gt;Use the &lt;code&gt;scp&lt;/code&gt; command to securely copy your database &lt;strong&gt;dump files&lt;/strong&gt; from the &lt;strong&gt;source machine&lt;/strong&gt; (where the dumps are stored) to the destination machine (the remote database server).&lt;/p&gt;

&lt;p&gt;Run the following command from the source machine:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br&gt;
The &lt;code&gt;&amp;lt;username&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;IP_ADDRESS&amp;gt;&lt;/code&gt;, and destination directory may vary depending on your setup. Adjust them according to your environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo scp /var/backups/openiam-db/* &amp;lt;username&amp;gt;@&amp;lt;IP_ADDRESS&amp;gt;:&amp;lt;Destination&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo scp /var/backups/openiam-db/*  iamdb@10.2.10.130:/home/iamdb&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Import the &lt;code&gt;openiam&lt;/code&gt; dump file into the &lt;code&gt;openiam&lt;/code&gt; database:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mysql openiam &amp;lt; &amp;lt;Destination&amp;gt;openiam_*.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;sudo mysql openiam &amp;lt; /tmp/openiam_2025-09-10.sql&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Import the &lt;code&gt;activiti&lt;/code&gt; dump file into the &lt;code&gt;activiti&lt;/code&gt; database:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mysql activiti &amp;lt; &amp;lt;Destination&amp;gt;activiti_*.sql
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;code&gt;sudo mysql activiti &amp;lt; /tmp/activiti_2025-09-10.sql&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Check the number of &lt;strong&gt;tables&lt;/strong&gt; in &lt;code&gt;Openiam&lt;/code&gt;:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mysql -e "USE openiam; SHOW TABLES;" | wc -l  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Check the number of &lt;strong&gt;users&lt;/strong&gt; in the &lt;code&gt;openiam&lt;/code&gt; database:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo mysql -e "USE openiam; SELECT COUNT(*) AS total_users FROM USERS;"  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 7: Update Irancell IAM Configuration
&lt;/h2&gt;

&lt;p&gt;Now, go back to the machine with &lt;strong&gt;IAM&lt;/strong&gt; and run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo nano /usr/local/openiam/conf/properties/datasource.properties
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This file contains the database connection settings for &lt;strong&gt;Irancell IAM&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjl4t0yb1hvkxqbdqxanw.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjl4t0yb1hvkxqbdqxanw.jpg" alt=" " width="800" height="293"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Update the database &lt;strong&gt;host IP&lt;/strong&gt; by setting the &lt;strong&gt;new database machine’s IP&lt;/strong&gt; address:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jdbc.host=&amp;lt;NEW_DB_IP&amp;gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jdbc.host=10.2.10.130
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;note:&lt;/strong&gt;&lt;br&gt;
Only the IP address is required — no port or extra configuration needed here.&lt;/p&gt;

&lt;p&gt;Restart &lt;strong&gt;Irancell IAM services&lt;/strong&gt; to apply the new database configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo openiam-cli restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Check the service &lt;strong&gt;status&lt;/strong&gt;to ensure everything is running properly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo openiam-cli status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;End of Migration&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Your &lt;strong&gt;Irancell IAM&lt;/strong&gt; instance is now connected to the remote database server with all data migrated successfully.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>ftuhyu</title>
      <dc:creator>hediyeh kianmehr</dc:creator>
      <pubDate>Sun, 21 Sep 2025 11:20:54 +0000</pubDate>
      <link>https://dev.to/hediyeh_kianmehr_45f78137/ftuhyu-3afl</link>
      <guid>https://dev.to/hediyeh_kianmehr_45f78137/ftuhyu-3afl</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8nxwgavgknmrex12vdxj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8nxwgavgknmrex12vdxj.png" alt=" " width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>ytry</title>
      <dc:creator>hediyeh kianmehr</dc:creator>
      <pubDate>Sun, 21 Sep 2025 11:16:50 +0000</pubDate>
      <link>https://dev.to/hediyeh_kianmehr_45f78137/ytry-3j8h</link>
      <guid>https://dev.to/hediyeh_kianmehr_45f78137/ytry-3j8h</guid>
      <description>&lt;p&gt;&lt;strong&gt;fdhgfh&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;hdtyh:&lt;/strong&gt;&lt;code&gt;dfgdh&lt;/code&gt;&lt;/p&gt;




&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Name&lt;/th&gt;
&lt;th&gt;Age&lt;/th&gt;
&lt;th&gt;City&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Alice&lt;/td&gt;
&lt;td&gt;25&lt;/td&gt;
&lt;td&gt;New York&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Bob&lt;/td&gt;
&lt;td&gt;30&lt;/td&gt;
&lt;td&gt;Los Angeles&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Charlie&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;Chicago&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;msg.payload = {
    email: msg.userData.profile.email,
    token: msg.userData.token,
    createdAt: new Date(),
    expiresAt: new Date(Date.now() + 3600*1000)
};
return msg;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;etrytryuyuiyiyui&lt;/p&gt;
&lt;/blockquote&gt;

</description>
    </item>
    <item>
      <title>ytery</title>
      <dc:creator>hediyeh kianmehr</dc:creator>
      <pubDate>Sun, 21 Sep 2025 05:38:15 +0000</pubDate>
      <link>https://dev.to/hediyeh_kianmehr_45f78137/ytery-1pld</link>
      <guid>https://dev.to/hediyeh_kianmehr_45f78137/ytery-1pld</guid>
      <description>&lt;p&gt;یلابلاتبیبل&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Mailbox</title>
      <dc:creator>hediyeh kianmehr</dc:creator>
      <pubDate>Thu, 04 Sep 2025 09:24:10 +0000</pubDate>
      <link>https://dev.to/hediyeh_kianmehr_45f78137/mailbox-3a5g</link>
      <guid>https://dev.to/hediyeh_kianmehr_45f78137/mailbox-3a5g</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;This guide provides a step-by-step process to configure email functionality in OpenIAM using a Gmail account. It covers preparing a Gmail account with an App Password, setting up a Mailbox Configuration in OpenIAM, testing email delivery, and creating a Mail Template for automated user notifications.&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Overview&lt;/li&gt;
&lt;li&gt;Prepare your Gmail account (Mandatory)&lt;/li&gt;
&lt;li&gt;
Configuring Mailbox in OpenIAM

&lt;ul&gt;
&lt;li&gt;Fill in the Mailbox Configuration&lt;/li&gt;
&lt;li&gt;Manual Configuration&lt;/li&gt;
&lt;li&gt;Send Test Mail&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Mail Template Editor&lt;/li&gt;
&lt;li&gt;User Creation and Email Delivery&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Prepare your Gmail account (Mandatory)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Go to your &lt;strong&gt;Google Account&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Open the &lt;strong&gt;Security section&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Turn on &lt;strong&gt;Verification&lt;/strong&gt; (if it is not already enabled).&lt;/li&gt;
&lt;li&gt;Click on &lt;strong&gt;App passwords&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffg5hu3f5r9zvv1dx3ax0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffg5hu3f5r9zvv1dx3ax0.jpg" alt=" " width="800" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In &lt;strong&gt;Select app&lt;/strong&gt;, choose Other (Custom name) and enter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Based on the setup)&lt;br&gt;
 &lt;code&gt;OpenIAM&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8hzkgrw3euu6eq1fxep.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8hzkgrw3euu6eq1fxep.jpg" alt=" " width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click &lt;strong&gt;Generate&lt;/strong&gt; , Google will provide a &lt;strong&gt;16-character password&lt;/strong&gt;. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt;&lt;br&gt;
Copy the generated password exactly as it appears, without any spaces. This will be used as the &lt;strong&gt;SMTP password&lt;/strong&gt; in &lt;code&gt;OpenIAM&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Your regular Gmail password will not work. Only this App Password can be used.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Configuring Mailbox in OpenIAM
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Navigate to the &lt;strong&gt;Administration tab&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;select &lt;strong&gt;Mailbox Configuration&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F20dwk6nfrjda1oeflkf0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F20dwk6nfrjda1oeflkf0.jpg" alt=" " width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select Create Mailbox Configuration.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F64km95tx8hc50kv00tmw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F64km95tx8hc50kv00tmw.png" alt=" " width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Fill in the Mailbox Configuration
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Name:&lt;/strong&gt; &lt;code&gt;desired name&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;(Based on the setup)&lt;br&gt;
&lt;strong&gt;Is Active:&lt;/strong&gt; &lt;code&gt;checked&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If &lt;strong&gt;Read Inbox&lt;/strong&gt; is &lt;code&gt;checked&lt;/code&gt;, enter the email address that will be used to receive and respond to messages.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Is modern auth:&lt;/strong&gt; &lt;code&gt;unchecked&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Default sender:&lt;/strong&gt;&lt;br&gt;
 &lt;code&gt;Enter the email address that will be used to send emails to users.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(Based on the setup)&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Default subject prefix:&lt;/strong&gt;&lt;code&gt;OpenIAM&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SMTP username:&lt;/strong&gt;&lt;code&gt;Enter the email address used as the Default Sender.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SMTP password:&lt;/strong&gt;&lt;code&gt;Enter the 16-character App Password generated in the "Prepare Your Gmail Account (Mandatory)" step.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mailbox Configuration Template:&lt;/strong&gt;&lt;code&gt;G-mail SMTP Relay&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Select a template based on your &lt;strong&gt;email&lt;/strong&gt; and &lt;strong&gt;domain&lt;/strong&gt;. Since our domain is Gmail, choose &lt;code&gt;G-mail SMTP Relay&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This template automatically sets the appropriate &lt;strong&gt;host&lt;/strong&gt; and &lt;strong&gt;port&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If this template is not available, see the &lt;strong&gt;Manual Configuration&lt;/strong&gt; option.&lt;/p&gt;

&lt;h3&gt;
  
  
  Manual Configuration
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SMTP Host/Server:&lt;/strong&gt; &lt;code&gt;smtp.gmail.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Port:&lt;/strong&gt; &lt;code&gt;587&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TLS/STARTTLS:&lt;/strong&gt; &lt;code&gt;Enabled&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Simulation mode:&lt;/strong&gt;&lt;code&gt;unchecked&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkxgclvcvbwvwl6w4sfl3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkxgclvcvbwvwl6w4sfl3.jpg" alt=" " width="800" height="857"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  Send test mail
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Email Address:&lt;/strong&gt;&lt;code&gt;Enter the email address where you want to test the email.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(Optional)&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Is HTML:&lt;/strong&gt; &lt;code&gt;Enable this if you want to use HTML to style the email.&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(Based on the setup)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Subject:&lt;/strong&gt;&lt;code&gt;Test&lt;/code&gt; &lt;br&gt;
&lt;strong&gt;Message&lt;/strong&gt;:&lt;code&gt;hello from OpenIAM&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Save&lt;/strong&gt; to apply the configuration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br&gt;
In this section, we are testing whether the email can be successfully sent from our system.&lt;/p&gt;

&lt;p&gt;The email you just created is a basic setup for further configuration. To continue:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Navigate to the Administration tab.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select Mail Template Editor.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj3uagxni6inxrrcgg65y.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj3uagxni6inxrrcgg65y.jpg" alt=" " width="793" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mail Templete Name:&lt;/strong&gt;&lt;code&gt;New_User_Email&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br&gt;
Because the &lt;strong&gt;Mail Template Name&lt;/strong&gt; is set to &lt;code&gt;New_User_Email&lt;/code&gt;, the following behavior occurs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In this section, you can configure the email that will be sent whenever a new user is added to the system&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkueda6usv7ofd0u6jl4f.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkueda6usv7ofd0u6jl4f.jpg" alt=" " width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mail Templete Content:&lt;/strong&gt;&lt;code&gt;Enter your HTML code here to design the email template.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In this section, you can configure the email that will be sent when a new user is added to the system. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;Mail Template Propertise:&lt;code&gt;identity&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this section, a new user is created, and the &lt;strong&gt;username&lt;/strong&gt; and &lt;strong&gt;lastname&lt;/strong&gt; never change, so we select identity.&lt;/p&gt;




&lt;ul&gt;
&lt;li&gt;Navigate to &lt;strong&gt;User Admin&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Create New User&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Select Turn to &lt;strong&gt;Classic View&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;When a new user is created, the &lt;strong&gt;email&lt;/strong&gt; we configured will be sent to the user.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2sv50rw8rypmtjmlysvn.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2sv50rw8rypmtjmlysvn.jpg" alt=" " width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>OpenIAM Email Configuration Guide</title>
      <dc:creator>hediyeh kianmehr</dc:creator>
      <pubDate>Wed, 03 Sep 2025 07:35:47 +0000</pubDate>
      <link>https://dev.to/hediyeh_kianmehr_45f78137/google-account-2f7b</link>
      <guid>https://dev.to/hediyeh_kianmehr_45f78137/google-account-2f7b</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;This guide provides a step-by-step process to configure email functionality in OpenIAM using a Gmail account. It covers preparing a Gmail account with an App Password, setting up a Mailbox Configuration in OpenIAM, testing email delivery, and creating a Mail Template for automated user notifications.&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Overview&lt;/li&gt;
&lt;li&gt;Prepare your Gmail account (Mandatory)&lt;/li&gt;
&lt;li&gt;
Configuring Mailbox in OpenIAM

&lt;ul&gt;
&lt;li&gt;Fill in the Mailbox Configuration&lt;/li&gt;
&lt;li&gt;Manual Configuration&lt;/li&gt;
&lt;li&gt;Send Test Mail&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Mail Template Editor&lt;/li&gt;
&lt;li&gt;User Creation and Email Delivery&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Prepare your Gmail account (Mandatory)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Go to your &lt;strong&gt;Google Account&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Open the &lt;strong&gt;Security section&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Turn on &lt;strong&gt;Verification&lt;/strong&gt; (if it is not already enabled).&lt;/li&gt;
&lt;li&gt;Click on &lt;strong&gt;App passwords&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffg5hu3f5r9zvv1dx3ax0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffg5hu3f5r9zvv1dx3ax0.jpg" alt=" " width="800" height="324"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In &lt;strong&gt;Select app&lt;/strong&gt;, choose Other (Custom name) and enter&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;(Based on the setup)&lt;br&gt;
 &lt;code&gt;OpenIAM&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8hzkgrw3euu6eq1fxep.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo8hzkgrw3euu6eq1fxep.jpg" alt=" " width="800" height="448"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click &lt;strong&gt;Generate&lt;/strong&gt; , Google will provide a &lt;strong&gt;16-character password&lt;/strong&gt;. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt;&lt;br&gt;
Copy the generated password exactly as shown (for example, &lt;code&gt;A9fG kL2p vQ8rTz&lt;/code&gt;) without adding or removing any characters. This password will be used as the &lt;strong&gt;SMTP password&lt;/strong&gt; in &lt;strong&gt;OpenIAM&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: Your regular Gmail password will not work. Only the generated App Password can be used. Its validity depends on your Gmail security settings and may expire or become invalid based on your account’s security configuration.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  Configuring Mailbox in OpenIAM
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Navigate to the &lt;strong&gt;Administration tab&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;select &lt;strong&gt;Mailbox Configuration&lt;/strong&gt;.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F20dwk6nfrjda1oeflkf0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F20dwk6nfrjda1oeflkf0.jpg" alt=" " width="800" height="383"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Select Create Mailbox Configuration.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F64km95tx8hc50kv00tmw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F64km95tx8hc50kv00tmw.png" alt=" " width="800" height="355"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Fill in the Mailbox Configuration
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Name:&lt;/strong&gt; &lt;code&gt;desired name&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;(Based on the setup)&lt;br&gt;
&lt;strong&gt;Is Active:&lt;/strong&gt; &lt;code&gt;checked&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If &lt;strong&gt;Read Inbox&lt;/strong&gt; is &lt;code&gt;checked&lt;/code&gt;, enter the email address that will be used to receive and respond to messages.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Is modern auth:&lt;/strong&gt; &lt;code&gt;unchecked&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Default sender:&lt;/strong&gt;&lt;br&gt;
 &lt;code&gt;Enter the email address that will be used to send emails to users.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(Based on the setup)&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Default subject prefix:&lt;/strong&gt;&lt;code&gt;OpenIAM&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SMTP username:&lt;/strong&gt;&lt;code&gt;Enter the email address used as the Default Sender.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SMTP password:&lt;/strong&gt;&lt;code&gt;Enter the 16-character App Password generated in the "Prepare Your Gmail Account (Mandatory)" step.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mailbox Configuration Template:&lt;/strong&gt;&lt;code&gt;G-mail SMTP Relay&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Select a template based on your &lt;strong&gt;email&lt;/strong&gt; and &lt;strong&gt;domain&lt;/strong&gt;. Since our domain is Gmail, choose &lt;code&gt;G-mail SMTP Relay&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;This template automatically sets the appropriate &lt;strong&gt;host&lt;/strong&gt; and &lt;strong&gt;port&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If this template is not available, see the &lt;strong&gt;Manual Configuration&lt;/strong&gt; option.&lt;/p&gt;

&lt;h3&gt;
  
  
  Manual Configuration (Gmail Domain)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SMTP Host/Server:&lt;/strong&gt; &lt;code&gt;smtp.gmail.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Port:&lt;/strong&gt; &lt;code&gt;587&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;TLS/STARTTLS:&lt;/strong&gt; &lt;code&gt;Enabled&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simulation mode:&lt;/strong&gt;&lt;code&gt;unchecked&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;This configuration applies specifically to Gmail domain accounts.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkxgclvcvbwvwl6w4sfl3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkxgclvcvbwvwl6w4sfl3.jpg" alt=" " width="800" height="857"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  Send test mail
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Email Address:&lt;/strong&gt;&lt;code&gt;Enter the email address where you want to test the email.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(Optional)&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;Is HTML:&lt;/strong&gt; &lt;code&gt;Enable this if you want to use HTML to style the email.&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(Based on the setup)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Subject:&lt;/strong&gt;&lt;code&gt;Test&lt;/code&gt; &lt;br&gt;
&lt;strong&gt;Message&lt;/strong&gt;:&lt;code&gt;hello from OpenIAM&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Note: Click &lt;strong&gt;Test&lt;/strong&gt; first.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If there are &lt;strong&gt;no errors&lt;/strong&gt;, click &lt;strong&gt;Save&lt;/strong&gt; to apply the configuration.&lt;/li&gt;
&lt;li&gt;If an &lt;strong&gt;error&lt;/strong&gt; occurs, it is likely related to the &lt;strong&gt;SMTP&lt;/strong&gt; settings.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br&gt;
In this section, we are testing if the email can be successfully sent from our system.&lt;/p&gt;

&lt;p&gt;The email you just created is a basic setup for further configuration. To continue:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Navigate to the Administration tab.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select Mail Template Editor.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj3uagxni6inxrrcgg65y.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj3uagxni6inxrrcgg65y.jpg" alt=" " width="793" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In this section, you can configure the email that will be sent when a new user is added to the system. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Mail Templete Name:&lt;/strong&gt;&lt;code&gt;New_User_Email&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br&gt;
Because the &lt;strong&gt;Mail Template Name&lt;/strong&gt; is set to &lt;code&gt;New_User_Email&lt;/code&gt;, the following behavior occurs:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In this section, you can configure the email that will be sent whenever a new user is added to the system&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkueda6usv7ofd0u6jl4f.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkueda6usv7ofd0u6jl4f.jpg" alt=" " width="800" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Mail Templete Content:&lt;/strong&gt;&lt;code&gt;Enter your HTML code here to design the email template.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(Optional)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Mail Template Propertise:&lt;code&gt;identity&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;ul&gt;
&lt;li&gt;Navigate to &lt;strong&gt;User Admin&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Navigate to &lt;strong&gt;Create New User&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Select Turn to &lt;strong&gt;Classic View&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;When a new user is created, the &lt;strong&gt;email&lt;/strong&gt; we configured will be sent to the user.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2sv50rw8rypmtjmlysvn.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2sv50rw8rypmtjmlysvn.jpg" alt=" " width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Adding a Custom Attribute to the User’s Template-Based View</title>
      <dc:creator>hediyeh kianmehr</dc:creator>
      <pubDate>Tue, 02 Sep 2025 15:06:59 +0000</pubDate>
      <link>https://dev.to/hediyeh_kianmehr_45f78137/adding-a-custom-attribute-to-the-users-basic-view-4b86</link>
      <guid>https://dev.to/hediyeh_kianmehr_45f78137/adding-a-custom-attribute-to-the-users-basic-view-4b86</guid>
      <description>&lt;h2&gt;
  
  
  Overview
&lt;/h2&gt;

&lt;p&gt;This guide provides a step-by-step process for adding custom attributes to a user’s Template-Based View. It covers creating custom fields, assigning them to appropriate sections, and ensuring they are visible in the Template-Based View.&lt;/p&gt;




&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
Overview
&lt;/li&gt;
&lt;li&gt;
Template-Based View
&lt;/li&gt;
&lt;li&gt;
Additional Information
&lt;/li&gt;
&lt;li&gt;
Create a Custom Field

&lt;ol&gt;
&lt;li&gt;
Mandatory Fields
&lt;/li&gt;
&lt;li&gt;
Checkbox Options
&lt;/li&gt;
&lt;li&gt;
Custom Field Type
&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;

Create a Text Field Custom Attribute

&lt;ol&gt;
&lt;li&gt;
Text Field Options
&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;li&gt;

Page Template Configuration
&lt;/li&gt;

&lt;li&gt;

Add Custom Attribute to Template
&lt;/li&gt;

&lt;li&gt;Verify Custom Attribute&lt;/li&gt;

&lt;/ol&gt;




&lt;p&gt;In the search bar, locate the &lt;strong&gt;user account&lt;/strong&gt; to which you want to add a &lt;strong&gt;Custom attribute&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv2xfm9ve0r508n8bbk3a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv2xfm9ve0r508n8bbk3a.png" alt=" " width="800" height="68"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Template based view
&lt;/h2&gt;

&lt;p&gt;We chose the &lt;strong&gt;Template-Based View&lt;/strong&gt; because it allows us to provide information to the user.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqhf0ip1km4vqvq59xjk1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqhf0ip1km4vqvq59xjk1.jpg" alt=" " width="800" height="153"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Additional Information
&lt;/h2&gt;

&lt;p&gt;In the &lt;strong&gt;Additional Information&lt;/strong&gt; section, we want to add &lt;strong&gt;Custom attributes&lt;/strong&gt;. The &lt;strong&gt;values&lt;/strong&gt; for these attributes will be retrieved from &lt;strong&gt;Active Directory&lt;/strong&gt; and displayed in this section.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftcw3rnqtov6u2lkootpg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftcw3rnqtov6u2lkootpg.png" alt=" " width="800" height="170"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Create a Custom Field
&lt;/h2&gt;

&lt;p&gt;First, click on the &lt;strong&gt;Administration tab&lt;/strong&gt; and select &lt;strong&gt;Custom Fields&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxdcm1pd9qcz8vtab8z0q.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxdcm1pd9qcz8vtab8z0q.jpg" alt=" " width="386" height="477"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;Choose &lt;strong&gt;Create New Custom Field&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbx7kuv9g5pv35esxc5xj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbx7kuv9g5pv35esxc5xj.jpg" alt=" " width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  Mandatory Fields
&lt;/h4&gt;

&lt;p&gt;You must complete all mandatory fields &lt;code&gt;(marked with *)&lt;/code&gt; in order to create a custom field.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Field Name:&lt;/strong&gt; &lt;code&gt;Set the internal name for your custom field. This value is not displayed to end users.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(Based on the setup)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Field Name:&lt;/strong&gt; &lt;code&gt;Custom attributes&lt;/code&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Display Name English:&lt;/strong&gt; &lt;code&gt;Enter the display name for the field. This is the label shown to users in the interface.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(Based on the setup)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Display Name English:&lt;/strong&gt; &lt;code&gt;company attributes&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24pvgu1h5h63i88h375v.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24pvgu1h5h63i88h375v.jpg" alt=" " width="800" height="373"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  Checkbox Options
&lt;/h4&gt;

&lt;p&gt;There are several &lt;strong&gt;checkboxes&lt;/strong&gt; you can configure based on your requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Is Editable&lt;/strong&gt;  &lt;code&gt;Allows the end user to edit the field.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Is Public&lt;/strong&gt;  &lt;code&gt;Determines whether the field is visible to all users.&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Is Required&lt;/strong&gt;  &lt;code&gt;Makes the field mandatory the user must provide a value before saving.&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;(Based on the setup)&lt;/strong&gt; &lt;br&gt;
&lt;strong&gt;Is Public:&lt;/strong&gt; &lt;code&gt;Checked&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn6cnj6qne2mbu1f8g39g.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn6cnj6qne2mbu1f8g39g.jpg" alt=" " width="800" height="155"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  Custom Field Type
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;The Type of Custom Field:&lt;/strong&gt; &lt;code&gt;This defines the type of the custom field you are creating.&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;(Based on the setup)&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;The Type of Custom Field&lt;/strong&gt; &lt;code&gt;Section&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Section:&lt;/strong&gt; &lt;code&gt;It helps organize fields into logical groups for better readability and usability.&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br&gt;
You can select other field types depending on the system configuration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmif4g1waemk49mfm3mo4.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmif4g1waemk49mfm3mo4.jpg" alt=" " width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, click &lt;strong&gt;Save&lt;/strong&gt; to create the custom attribute in the User’s &lt;strong&gt;Template-Based View&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feja7ccqxyvbh7kqf2zrs.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Feja7ccqxyvbh7kqf2zrs.jpg" alt=" " width="800" height="197"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Create a Text Field Custom Attribute
&lt;/h2&gt;

&lt;p&gt;Choose &lt;strong&gt;Create New Custom Field&lt;/strong&gt; once more.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbx7kuv9g5pv35esxc5xj.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbx7kuv9g5pv35esxc5xj.jpg" alt=" " width="800" height="344"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this step, create a new custom field that will belong to the &lt;strong&gt;Company Attributes&lt;/strong&gt; section you created earlier &lt;strong&gt;(based on the setup)&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Field Name:&lt;/strong&gt; &lt;code&gt;company_floor&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Display Name English:&lt;/strong&gt; &lt;code&gt;floor&lt;/code&gt; &lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Is Public:&lt;/strong&gt; &lt;code&gt;Checked&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;The Type of Custom Field&lt;/strong&gt; &lt;code&gt;Text Field&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Text Field Options
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Text Field:&lt;/strong&gt;  &lt;code&gt;standard text input&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;If you choose Text Field as the type, additional options will appear:&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Field Placeholder:&lt;/strong&gt; &lt;code&gt;Enter a placeholder text that will appear inside the field before the user types anything.&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Default Value:&lt;/strong&gt; &lt;code&gt;You can add any data you want in the fields of this section.&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;English:&lt;/strong&gt; &lt;code&gt;enter the desired value&lt;/code&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;(based on the setup)&lt;/strong&gt;&lt;br&gt;
&lt;strong&gt;English:&lt;/strong&gt; &lt;code&gt;2&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6yw3w06svqc8h7jzov85.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6yw3w06svqc8h7jzov85.jpg" alt=" " width="800" height="287"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br&gt;
The value assigned to the custom field can also be sourced from Active Directory through a script and the synchronization process.&lt;/p&gt;




&lt;h2&gt;
  
  
  Page Template Configuration
&lt;/h2&gt;

&lt;p&gt;click on the &lt;strong&gt;Administration tab&lt;/strong&gt; and select &lt;strong&gt;Page Template&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fete6zaf92ebhp0gpr53i.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fete6zaf92ebhp0gpr53i.jpg" alt=" " width="576" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here, you should select the &lt;strong&gt;Page Template&lt;/strong&gt; you want to use.&lt;/p&gt;

&lt;p&gt;Navigate to the &lt;strong&gt;Actions column&lt;/strong&gt; and click &lt;strong&gt;Edit&lt;/strong&gt; next to the &lt;strong&gt;Page Template&lt;/strong&gt; you wish to modify.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fje9il61jco5yqr3eehg1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fje9il61jco5yqr3eehg1.jpg" alt=" " width="800" height="268"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Add Custom Attribute to Template
&lt;/h2&gt;

&lt;p&gt;In the &lt;strong&gt;Template Fields section&lt;/strong&gt;, search for the &lt;strong&gt;custom attribute&lt;/strong&gt; you created earlier.&lt;/p&gt;

&lt;p&gt;Click &lt;strong&gt;Add to List&lt;/strong&gt; to include it, and you will see your &lt;strong&gt;custom attribute&lt;/strong&gt; appear in the list.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F66xzrauk9juek93tp3cy.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F66xzrauk9juek93tp3cy.jpg" alt=" " width="800" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then, click &lt;strong&gt;Save&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br&gt;
The order of adding custom attributes to the list is important. Sections should be added first, followed by the custom fields that belong to each section.&lt;/p&gt;




&lt;h2&gt;
  
  
  Verify Custom Attribute
&lt;/h2&gt;

&lt;p&gt;Now, we can verify whether the &lt;strong&gt;custom attribute&lt;/strong&gt; has been added to the user’s &lt;strong&gt;Template-Based View&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Search for the name of the user to whom you added a &lt;strong&gt;custom attribute&lt;/strong&gt; in the &lt;strong&gt;search bar&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv2xfm9ve0r508n8bbk3a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv2xfm9ve0r508n8bbk3a.png" alt=" " width="800" height="68"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Choose &lt;strong&gt;Template-Based View&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqhf0ip1km4vqvq59xjk1.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqhf0ip1km4vqvq59xjk1.jpg" alt=" " width="800" height="153"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h4&gt;
  
  
  Additional Information
&lt;/h4&gt;

&lt;p&gt;Verify that in the &lt;strong&gt;Additional Information&lt;/strong&gt; section:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The &lt;strong&gt;Company Attributes&lt;/strong&gt; section is displayed as the organized group.&lt;/li&gt;
&lt;li&gt;The custom field &lt;strong&gt;Floor&lt;/strong&gt; appears within this section.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb62olt2ybo0g8p5wvsyv.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb62olt2ybo0g8p5wvsyv.jpg" alt=" " width="800" height="112"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Uppercase Converter</title>
      <dc:creator>hediyeh kianmehr</dc:creator>
      <pubDate>Mon, 25 Aug 2025 08:32:01 +0000</pubDate>
      <link>https://dev.to/hediyeh_kianmehr_45f78137/uppercase-converter-4152</link>
      <guid>https://dev.to/hediyeh_kianmehr_45f78137/uppercase-converter-4152</guid>
      <description>&lt;h2&gt;
  
  
  Uppercase Converter
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Uppercase Converter
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Uppercase Converter
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Uppercase Converter&lt;/li&gt;
&lt;/ol&gt;

&lt;ul&gt;
&lt;li&gt;Goal: Convert any string to uppercase.&lt;/li&gt;
&lt;li&gt;Inside Subflow:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;msg.payload=String(msg.payload).toUpperCase();
return msg;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Overview&lt;br&gt;
This guide describes the technical steps to onboard a new user into Irancell IAM.&lt;br&gt;
Onboarding ensures that the user’s identity, roles, and entitlements are created and synchronized across Irancell IAM and connected systems (e.g., Active Directory, LDAP, HRMS, or application databases).&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Joiners, Movers, Leavers Processes</title>
      <dc:creator>hediyeh kianmehr</dc:creator>
      <pubDate>Sat, 23 Aug 2025 16:48:36 +0000</pubDate>
      <link>https://dev.to/hediyeh_kianmehr_45f78137/joiners-movers-leavers-processes-3fe9</link>
      <guid>https://dev.to/hediyeh_kianmehr_45f78137/joiners-movers-leavers-processes-3fe9</guid>
      <description>&lt;p&gt;Joiners, Movers and Leavers (JML) process is the way that the Identity system processes the journey the user has in a particular organization.&lt;/p&gt;

&lt;p&gt;This means that there is a necessity to have rules or workflows which define what to do when a person joins (hired to the company), when an employee moves within the organization and such movement potentially will affect the level of access that they have (their job title changes, they move to a different department, a different location). Finally, there has to be rules of regulating the case when somebody leaves the organization.&lt;/p&gt;

&lt;p&gt;These rules may vary depending on the case. For example, one may have one set of rules for employees and another one for contractors. Also, the data about joiners may come from a different source, such as an HR system, and from a manager.&lt;/p&gt;

&lt;p&gt;Hence, the variety of 'movement' within the organization creates a need for having a separate set of rules for each case.&lt;/p&gt;

&lt;h3&gt;
  
  
  Joiners
&lt;/h3&gt;

&lt;p&gt;Joiners process is connected with the fact of a new employee or contractor being added to Irancell IAM. The information about a new hire may come from different sources, such as an HR system, manager, self-registration etc. The new hires are detected after synchronization and they are granted access depending on the business rules.&lt;/p&gt;

&lt;p&gt;The diagram below provides an example of how the information captured above can be complemented.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8g73xvni1jjsosur0iwz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8g73xvni1jjsosur0iwz.png" alt=" " width="656" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Movers
&lt;/h3&gt;

&lt;p&gt;Movers or position changes usually refer to changes in a job and can be identified through changes in title, job code, manager, or department - the attributes are not limited to those named since these are any changes in the position that may impact the access user has in the system. If a change in one or more of these attributes that are associated with position change occurs, then Irancell IAM will start the position change workflows.&lt;/p&gt;

&lt;p&gt;The overall position change process is shown the example below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffik7xiddhcmh3lgt6w8o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffik7xiddhcmh3lgt6w8o.png" alt=" " width="658" height="375"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The movers and joiners workflow begin in the same way - with a synchronization script. However, after the data has been validated by a validation script and the transformation script has mapped the incoming changes to Irancell IAM attributes, several options arise.&lt;/p&gt;

&lt;h4&gt;
  
  
  Option 1
&lt;/h4&gt;

&lt;p&gt;One can define business rules through birthright access which defines the initial access a user should have. Based on that, the required policy map is processed, the access is granted or ended and the message bus sends a message to the connector. Afterwards, the access needed is created in Irancell IAM and the connector receives the message for provisioning.&lt;/p&gt;

&lt;h4&gt;
  
  
  Option 2
&lt;/h4&gt;

&lt;p&gt;A manager can request access in connection with position change. Here, after the scripts are done running, a manager receives a message about the need to review the user's access certification. Afterwards, the manager can request access needed for the user.&lt;/p&gt;

&lt;h4&gt;
  
  
  Option 3
&lt;/h4&gt;

&lt;p&gt;One can also introduce a hybrid solution between Options 1 and 2. For instance, some access type can be granted automatically via business rules set. Other access type can be granted only by a request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Leavers
&lt;/h3&gt;

&lt;p&gt;Movers or terminations refer to users that leave the organization and need to have their access terminated.&lt;/p&gt;

&lt;p&gt;The overall position change process is shown the example below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fex51qeo7ul7lsvu83yif.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fex51qeo7ul7lsvu83yif.png" alt=" " width="655" height="357"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Again, Similar to the leavers process, there are several options for how access can be terminated. The specific thing about leavers process is that on the end date (last day of working) the user status in Irancell IAM is set to Terminated. After that, a message is sent to any managed system where this user has an account and access can be deleted in several ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Access is deleted immediately.&lt;/li&gt;
&lt;li&gt;First, the account is disabled. If the target system is a directory, the user is then moved to a disabled user's OU and deleted from there after some time.&lt;/li&gt;
&lt;li&gt;One can choose a hybrid approach to deleting users, for instance, disable first and then delete, not moving the users to disabled users OU.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here, an important thing to consider is that the rules used to guide JML processes need to be dictated by a business need, so one needs to adapt to how a company works and support their processes.&lt;/p&gt;

&lt;p&gt;In further pages, you will find a tutorial for defining the JML process in Irancell IAM.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Rehire user flow</title>
      <dc:creator>hediyeh kianmehr</dc:creator>
      <pubDate>Sat, 23 Aug 2025 16:03:27 +0000</pubDate>
      <link>https://dev.to/hediyeh_kianmehr_45f78137/rehire-user-flow-3fkn</link>
      <guid>https://dev.to/hediyeh_kianmehr_45f78137/rehire-user-flow-3fkn</guid>
      <description>&lt;p&gt;Rehire user workflow is needed in cases when the employee left and now has been rehired. The same flow would work for both the rehire scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If a User is Terminated and exists in AD.&lt;/li&gt;
&lt;li&gt;If a User is Terminated and does not exist in AD.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;To initiate the workflow, follow the steps below.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Log in to Irancell IAM SelfService portal.&lt;/li&gt;
&lt;li&gt;Go to Access Management &amp;gt; Manage User. Search for the User you want to 
rehire.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcaaxk5g7ead3l2f2ua4l.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcaaxk5g7ead3l2f2ua4l.png" alt=" " width="652" height="294"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Click on the Username from the results list.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3rtzo6fxdwad5ob4sa81.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3rtzo6fxdwad5ob4sa81.png" alt=" " width="652" height="341"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Change the Contract Start date and End date, Vice Presidency etc. as needed. Select Rehire User as Yes. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click the Save button.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftiw7qu0lul0lfze3nh1g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftiw7qu0lul0lfze3nh1g.png" alt=" " width="655" height="322"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;User does not exist in Active Directory&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fry86l7vokrvvr250mwe0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fry86l7vokrvvr250mwe0.png" alt=" " width="646" height="197"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;User is Activated in Irancell IAM, and a new account is created in Active Directory.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp6zduvmnui2fd46u27kz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp6zduvmnui2fd46u27kz.png" alt=" " width="661" height="189"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ybzv6padirc47o45kij.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2ybzv6padirc47o45kij.png" alt=" " width="653" height="235"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Notifications are sent to the User's line manager.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4amwrlj6cuxmf2gtczb0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4amwrlj6cuxmf2gtczb0.png" alt=" " width="661" height="361"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Deprovisioning</title>
      <dc:creator>hediyeh kianmehr</dc:creator>
      <pubDate>Sat, 23 Aug 2025 15:41:48 +0000</pubDate>
      <link>https://dev.to/hediyeh_kianmehr_45f78137/deprovisioning-1c0p</link>
      <guid>https://dev.to/hediyeh_kianmehr_45f78137/deprovisioning-1c0p</guid>
      <description>&lt;p&gt;Deprovisioning refers to the procedure of revoking an employee's access to your company's systems, applications, and internal data resources. Irancell IAM performs deprovisioning in two scenarios:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When the user is deleted from Irancell IAM using the DELETE operation via API or UI.&lt;/li&gt;
&lt;li&gt;When the user no longer has active entitlements. An active entitlement is one with a valid end date. When the end date of an entitlement is earlier than the current date or the role is deleted from a user, the entitlement is considered inactive, and Irancell IAM sends a DELETE operation to the target system.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If your target system does not allow deleting an object, there are two possible solutions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There might be a default provisioning role that can never be deleted from a user. This auxiliary role helps to keep a user's status as active. It is often named a Default Provision User Role. Users can have groups added and deleted, but this role persists, ensuring the user remains active and cannot be deleted.&lt;/li&gt;
&lt;li&gt;There is an option you can set on Managed System attributes - ON_DELETE. Its value can be either DISABLE or UPDATE. If set, the DELETE operation will be replaced by the defined operation when sending data to the connector. If the attribute is not defined, the default behavior is to keep the DELETE operation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Managed System ON_DELETE
&lt;/h3&gt;

&lt;p&gt;Deprovisioning puts an identity into an inactive status. This means that subsequent changes will not be reflected in the target system for the identity that has been deprovisioned. Irancell IAM does not send any updates to the connector or the target system for inactive identities.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
