DEV Community

hediyeh kianmehr
hediyeh kianmehr

Posted on • Edited on

TrustedCloud User & Dashboard Guide

Table of Contents


Introduction

We provide Sign In and Sign Up options, allowing users to create an account and access the TrustedCloud dashboard to submit onboarding requests.

Once a user is successfully authenticated, they are redirected to one of four dashboards based on their assigned role:

  • Admin Dashboard
  • Applicant & Approver Dashboard
  • Applicant & Auditor Dashboard
  • Applicant Dashboard

Note:

Upon initial registration in TrustedCloud, users are assigned the default Applicant role. Administrators can later modify user roles and grant additional access privileges as needed.

Applicants can submit onboarding requests through the system. Approvers and Auditors are responsible for reviewing these requests. They can either approve or reject them and provide comments for clarification or feedback.

Role-Based Dashboard Access

1. Admin Dashboard

  • Can view requests in: Pending, Audited, Approved, Rejected

  • Can access the list of all approved requests that exist in the Service List

2. Approver Dashboard

  • Can view requests in: Audited, Approved

  • Can see only rejected requests that were rejected by Approvers, not those rejected by Auditors

3. Auditor Dashboard

  • Can view requests in: Pending, Audited, Rejected

4. Applicant Dashboard

  • Can view requests in: Pending, Audited, Approved, Rejected

Overview

our authentication system consists of:

A uibuilder front-end (Vue.js app) for handling Sign In, Sign Up, and Forgot Password screens.

A Node-RED backend flow, connected via uibuilder websockets, for verifying user credentials and managing database queries (in our case, MongoDB Users collection).

This setup enables real-time, stateful communication between the browser and Node-RED — no REST API layer is required because uibuilder handles the WebSocket channel.


1. UIBuilder Frontend Initialization

When the user opens the login page, your Vue app runs this block:

uibuilder.start();
Enter fullscreen mode Exit fullscreen mode

This initializes a WebSocket connection between the browser and Node-RED.
uibuilder automatically assigns each client a unique clientId (and a corresponding uibuilder-client-id cookie).
This clientId allows Node-RED to respond directly to the same user session.


2. Cookie-Based Session Check

When the app starts (mounted() hook), it checks for an existing userToken cookie:

if (this.getCookie("userToken")) {
  uibuilder.send({
    auth: {
      userToken: this.getCookie("userToken"),
      clientId: this.getCookie("uibuilder-client-id"),
    },
  });
}
Enter fullscreen mode Exit fullscreen mode

Purpose:

If the token exists, the backend verifies it and automatically logs the user in (session persistence).

If not, the backend treats it as a fresh session.


3. Sign Up Flow

High-level flow:

Frontend (Vue/React)
      ↓ uibuilder.send
Node-RED Flow
      ↓ MongoDB Users Collection
      ↓ uibuilder.onChange (response)
Frontend Redirect
Enter fullscreen mode Exit fullscreen mode

When the user clicks Sign Up, this runs:

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"
        }
    });
}
Enter fullscreen mode Exit fullscreen mode

Sample request payload:

{
  "auth": {},
  "clientId": "oD6i_WpIes8pBvWjNXy81",
  "fullName": "hediyeh",
  "email": "h@gmail.com",
  "password": "111111",
  "confirmPassword": "111111",
  "type": "signup",
  "_socketId": "kmN2iMG_VAMQ7WSFAEhJ",
  "topic": "uibuilder",
  "_msgid": "96c8e068f17bef90"
}
Enter fullscreen mode Exit fullscreen mode

Backend Flow:

Node Name Type Responsibility
Validate Auth Payload Function Checks payload existence, validates email format, attaches socketId, prepares original payload.
User Query Function Queries Users collection for existing email.
Query Users Collection MongoDB Executes the email query.
Check Email Availability Function Determines if email exists; sets status failed or prepares data for insertion.
Evaluate Registration Status Switch Routes flow based on payload.status (success or failed).
Get Last User ID Function Fetches highest id from Users collection to increment.
Fetch Last User MongoDB Executes query for last user document.
Generate New User Data Function Hashes password, generates roles, constructs profile, prepares insertOne payload.
Insert New User MongoDB Inserts new user document into the Users collection.
Registration Success Response Function Returns success response with redirect URL.
set warning Function Returns failure response when email exists.
signin Debug Logs final response for monitoring.
  • Node-RED receives the signup data.
  • Validates if the email already exists.
  • Hashes the password before saving to the Users collection.
  • Returns a success message with:
{
  "payload": {
    "action": "register",
    "status": "success",
    "URL": "/hediyeh/trustedcloud2"
  }
}
Enter fullscreen mode Exit fullscreen mode
  • The frontend receives it and redirects the user to the dashboard.

Sample Responses (uibuilder.onChange)

Status Response
Success { "action": "register", "status": "success", "message": "You have registered successfully!", "URL": "https://codenxa.leanea.com/hediyeh/signin" }
Failure { "action": "register", "status": "failed", "message": "Email already exists. Please use a different email." }

MongoDB Users Collection Schema

Field Type Description
_id ObjectId Unique document ID
clientId string Unique client identifier
fullName string User full name
email string Unique email
password string Hashed password
confirmPassword string Hashed password (same as password)
roles array Assigned roles (e.g., ["Applicant","Auditor"])
status string Registration status (not_found, success)
profile object User profile data (avatar, first/last name, contact info)
createdAt Date Timestamp of account creation
updatedAt Date Last update timestamp

Sample document:

{
  "_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"
}
Enter fullscreen mode Exit fullscreen mode

Security Considerations

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

4. Sign In Flow

High-Level Flow:

Frontend (Vue/React)
      ↓ uibuilder.send
Node-RED Flow
      ↓ MongoDB Users & Tokens Collections
      ↓ uibuilder.onChange (response)
Frontend Redirect / Error Handling
Enter fullscreen mode Exit fullscreen mode

Frontend Sign In Action

When the user clicks the Sign In button, the following function runs:

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"
        }
    });
}
Enter fullscreen mode Exit fullscreen mode

Sample Request Payload:

{
  "auth": {},
  "clientId": "oD6i_WpIes8pBvWjNXy81",
  "email": "h@gmail.com",
  "password": "111111",
  "rememberMe": false,
  "type": "login",
  "_socketId": "70nLJLlIrgzsiFLpAEhQ",
  "topic": "uibuilder",
  "_msgid": "2e88832acfbcd402"
}
Enter fullscreen mode Exit fullscreen mode

Backend Node-RED Flow

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

Backend Flow Summary

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

Sample Responses (uibuilder.onChange)

Status Response
Invalid Email { "action": "login", "status": "invalidCredentials", "message": "Email not found." }
Invalid Password { "action": "login", "status": "invalidCredentials", "message": "Password does not match." }
Success { "action": "login", "status": "success", "message": "Logged In Successfully" }

Security Considerations

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

MongoDB Tokens Collection

Field Type Description
_id ObjectId Unique document ID
email string User email
userId string MongoDB user _id
id number Internal user ID
token string JWT token
createdAt Date Token creation timestamp
expiresAt Date Token expiration timestamp (1 hour by default)

Sample Document

{
  "_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"
}

Enter fullscreen mode Exit fullscreen mode

5. Reset Password Flow

High-Level Flow:

[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 & forward for email verification
Enter fullscreen mode Exit fullscreen mode

Frontend Reset Password Action

When a user submits their email in the Forgot Password form, the frontend sends a request via uibuilder:

resetPasswordRequest() {
  const clientId = uibuilder.get("clientId");
  uibuilder.send({
    auth: {
      email: this.email,
      type: "resetPassword"
    },
    _socketId: clientId
  });
}
Enter fullscreen mode Exit fullscreen mode

Sample Request Payload:

{
  "auth": {
    "email": "user@example.com",
    "type": "resetPassword"
  },
  "_socketId": "TtK9mNkl_2Fh8Wx2K3DdW"
}

Enter fullscreen mode Exit fullscreen mode

Backend Node-RED Flow

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

Backend Flow Summary

Validate Reset Request Input

  • Receives the reset request from the frontend via uibuilder.send.
  • Validates that the auth object and email field exist.
  • Attaches socketId and preserves the original payload for tracking.
  • Stops the flow if validation fails.

Prepare Filter for Email Check

  • Constructs a MongoDB query: { email: msg.auth.email }.
  • Prepares the message for the next MongoDB node.

Find User by Email

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

Generate Reset Token & Save (Next Step in Flow)

  • Creates a unique 6-digit code or UUID token.
  • Stores token in ResetCodes collection with:
    • userId
    • email
    • createdAt
    • expiresAt
    • used: false
  • Prepares payload for sending email.

Send Reset Code / Email

  • Sends an email to the user with the reset code.
  • Returns a generic success response to the frontend.

Sample Responses (uibuilder.onChange)

status Response
Valid request { "status": "ok", "message": "Email validation initiated." }
Missing email { "status": "error", "message": "Email is required." }

MongoDB PasswordResets Collection

Field Type Description
_id ObjectId Unique document ID
email string User email
userId string MongoDB _id of the user
code string One-time 6-digit reset code
used boolean Whether code has been used (default false)
createdAt Date Timestamp of token creation
expiresAt Date Expiration timestamp (e.g., 2 minutes)

Sample Document

{
  "_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
}
Enter fullscreen mode Exit fullscreen mode

6. sendResetCode Flow

High-Level Flow:

User clicks "Forgot Password" → Enter email
             ↓
       Vue.js Frontend
             ↓ uibuilder.send
      Node-RED Backend Flow
             ↓ MongoDB Users & ResetCodes
             ↓ uibuilder.onChange (response)
       Frontend Shows Verification Code Input

Enter fullscreen mode Exit fullscreen mode

Frontend Reset Password Action

handleDigitInput method

handleDigitInput(index, event) {
    const value = event.target.value;
    if (value && index < 5) {
        this.verificationInputs[index + 1].focus();
    } else if (value && index === 5) {
        const allFilled = this.verificationDigits.every(digit => digit !== '');
        if (allFilled) {
            const code = this.verificationDigits.join('');
            uibuilder.send({
                auth: {
                    type: "sendResetCode",
                    email: this.resetEmail,
                    code: code
                }
            });
            this.showVerificationSuccess = true;
        }
    }
}
Enter fullscreen mode Exit fullscreen mode
  • verificationDigits.join('') ensures the code is concatenated properly.
  • auth payload structure matches your sample request payload.

resendCode method

   resendCode() {


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

            uibuilder.send({
                auth:{
                    email: this.resetEmail,
                    type: "resendResetPassword",
                }
            })
        },
Enter fullscreen mode Exit fullscreen mode

Sample Request Payload

{
  "auth": {},
  "type": "sendResetCode",
  "code": "373600",
  "email": "h@gmail.com",
  "_socketId": "TQQZkMEJW3yr8AXbAEhi",
  "topic": "uibuilder",
  "_msgid": "563ae2fa2bd25a81"
}
Enter fullscreen mode Exit fullscreen mode

Backend Node-RED Flow

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

Backend Flow Summary

User submits email

  • Validated by Validate Auth & Prepare Payload.

Check for existing reset record

  • Nodes: Prepare DB Query + Find Password Reset Record.

Record exists?

  • Checked via Check Reset Record Existence.
  • Branch by status:
    • If invalid email → handled by Handle Invalid Email.
    • If code entered → verify via Find Password Reset Record + Check Reset Record Existence.

Update used flag if valid

  • Nodes: Compare Code & Update Used Flag + Update Used Flag.

Send response back to frontend

  • Nodes: Prepare Success Response and debug nodes.

Response Examples (uibuilder.onChange)

Status Response
invalidCode { "action": "resetPassword", "status": "invalidCode", "message": "code not found" }
expired { "action": "resetPassword", "status": "expired", "message": "your code has been expired" }
validCode { "action": "resetPassword", "status": "validCode", "message": "Code matched successfully" }

MongoDB PasswordResets Collection

Field Type Description
_id ObjectId Unique document ID
email string User email
userId string MongoDB _id of the user
code string One-time 6-digit reset code
used boolean Whether code has been used (default false)
createdAt Date Timestamp of token creation
expiresAt Date Expiration timestamp (e.g., 2 minutes)

Sample Document

{
  "_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
}
Enter fullscreen mode Exit fullscreen mode

7. setNewPassword Flow

High-Level Flow:

User enters email & 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
Enter fullscreen mode Exit fullscreen mode

Frontend setNewPassword Action

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();
}

Enter fullscreen mode Exit fullscreen mode
  • Validates that both new password and confirmation are entered and match.
  • Sends the setNewPassword action along with the email and new password to the backend via uibuilder.send().
  • Closes the modal and clears fields.

Sample Request Payload

{
  "auth": {},
  "type": "setNewPassword",
  "email": "h@gmail.com",
  "password": "123456",
  "_socketId": "3hHNyKWUI-Khbn9cAEh0",
  "topic": "TrustedCloud Password Reset Code – Action Required",
  "_msgid": "4a86446e49c05025"
}
Enter fullscreen mode Exit fullscreen mode

Backend Node-RED Flow

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

Backend Flow Summary

  • Validation & Payload Preparation (Validate Auth & Prepare Payload)

    • Validates the request contains a valid auth object and email.
    • Adds socketId and preserves the original payload for tracking.
  • Check User Existence (Check User by Email + Find User Record)


    Queries the Users collection in MongoDB to verify whether the provided email exists.

  • Decision Branching (Check if Email Exists in DB + Branch by Email Status)

    • If the email exists: proceeds to update the password.
    • If not: sends an invalidEmail response.
  • Password Update (Update User Password Function + MongoDB node)

    • Hashes the new password using bcrypt.
    • Updates it in the database.
    • Prepares a success response.
  • Post-Update Decision (Branch by Update Result)

    • If update is successful: sends success response.
    • If the user is invalid or not found: sends invalidUser response.
  • Response Handling (Prepare Success Response, Handle Invalid Email, Handle Invalid User)

Response Examples (uibuilder.onChange)

Status Response
invalidEmail { "action": "sendResetCode", "status": "invalidEmail", "message": "Email address not found." }
invalidUser { "action": "setNewPassword", "status": "invalidUser", "message": "User not found." }
success { "action": "setNewPassword", "status": "success", "message": "Password updated successfully." }

MongoDB Users Collection Schema

Field Type Description
_id ObjectId Unique document ID
clientId string Unique client identifier
fullName string User full name
email string Unique email
password string Hashed password
confirmPassword string Hashed password (same as password)
roles array Assigned roles (e.g., ["Applicant","Auditor"])
status string Registration status (not_found, success)
profile object User profile data (avatar, first/last name, contact info)
createdAt Date Timestamp of account creation
updatedAt Date Last update timestamp

Sample document:

{
  "_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"
}
Enter fullscreen mode Exit fullscreen mode

1. getDashboard (Applicant) Flow

High-Level Flow:

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)
Enter fullscreen mode Exit fullscreen mode

Frontend getDashboard (Applicant)

   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')
        }
    });
Enter fullscreen mode Exit fullscreen mode
  • uibuilder.start() starts the communication channel with Node-RED via WebSocket.
  • It sets isLoading = true to show a loading indicator (e.g., spinner).
  • Then it sends a message to Node-RED requesting the dashboard data.
  • The request message looks like:

Sample Request Payload

{
  "type": "getDashboard",
  "auth": {},
  "userToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwidXNlclRva2VuIjoiU09NRV9SQU5ET01fVE9LRU5fMTc2MTU5OTExNzkxNCIsInByb2ZpbGUiOnsidXNlcklkIjoiNjhmZmNjMjFkNmM0Mzk4ZWE1ZjVjY2Y5IiwiaWQiOjEwLCJlbWFpbCI6ImhAZ21haWwuY29tIiwicm9sZXMiOlsiYXBwbGljYW50Il0sImZ1bGxOYW1lIjoiaGVkaXllaCJ9LCJhY3Rpb24iOiJsb2dpbiIsImlhdCI6MTc2MTU5OTExNywiZXhwIjoxNzYxNjAyNzE3fQ.mkvYqaZX1Y8m8gJdS3VAlQvDJ7zj3amk-Rc59rKkR8k",
  "clientId": "DucPqZtrHFQNgOnyiGV02",
  "_socketId": "X6ZKjzzFvV-ibjhwAEiI",
  "_msgid": "8bd0ae08cdfe06a9"
}

Enter fullscreen mode Exit fullscreen mode

Backend Node-RED Flow

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

Backend Flow Summary

Determine User Roles

  • Purpose: Identify the user’s role(s) based on data from MongoDB.
  • Logic:
    • Checks the roles array in the user object.
    • Maps combinations to one of four categories:
    • Applicant
    • ApplicantandAuditor
    • ApplicantandApprover
    • Admin
  • Output: Sets msg.payload to role type and attaches full user info in msg.user.

Route by Role Type

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

Fetch Requests (Role-Based)

  • Purpose: Retrieve relevant requests from MongoDB for the user.
  • Logic:
    • For Applicants: query Requests collection where createdBy.id = userId.

Note:
Applicant Dashboard
Can view requests in: Pending, Audited, Approved, Rejected

Prepare Dashboard Payload

  • Purpose: Format data for front-end consumption.
  • Logic:
    • Combines request data (applicantRequests, requests) with user profile info (id, email, name, roles, avatar, contact info).
    • Ensures front-end receives a standardized object regardless of role.
  • Output: msg.payload ready to send to UI via uibuilder.

Sending Data to Front-End

  • Link/Debug Nodes:
    • Link Out node passes data to the front-end flow.
    • Debug nodes monitor output for verification and troubleshooting.

Response Examples (uibuilder.onChange)

{
  "type": "getDashboard",
  "auth": {},
  "userToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwidXNlclRva2VuIjoiU09NRV9SQU5ET01fVE9LRU5fMTc2MTU5OTkyNTMyNCIsInByb2ZpbGUiOnsidXNlcklkIjoiNjhmZmUxOTZkNmM0Mzk4ZWE1ZjVjZDA2IiwiaWQiOjksImVtYWlsIjoibEBnbWFpbC5jb20iLCJyb2xlcyI6WyJBcHBsaWNhbnQiXSwiZnVsbE5hbWUiOiJsaWxpYSJ9LCJhY3Rpb24iOiJsb2dpbiIsImlhdCI6MTc2MTU5OTkyNSwiZXhwIjoxNzYxNjAzNTI1fQ.SJLPhRoJOVnLvUQLsk5ngvdw4d2MgFw28p5yG6Uh4wc",
  "clientId": "DucPqZtrHFQNgOnyiGV02",
  "_socketId": "2xxN12-ysdStG4sBAEj5",
  "_msgid": "09d2712e6aea20b0",
  "_archiveRequest": null,
  "_editCompanyDetails": null,
  "_waitingForResponse": null,
  "_editProfile": null,
  "_approveRequest": null,
  "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"
        }
      }
    ]
  }
}

Enter fullscreen mode Exit fullscreen mode

MongoDB Requests Collection Schema

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

Sample document:

{
  "_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"
}

Enter fullscreen mode Exit fullscreen mode

2. getDashboard(Applicant and Auditor) Flow

High-Level Flow:

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)
Enter fullscreen mode Exit fullscreen mode

Frontend getDashboard (Applicant and Auditor)

   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')
        }
    });
Enter fullscreen mode Exit fullscreen mode
  • uibuilder.start() starts the communication channel with Node-RED via WebSocket.
  • It sets isLoading = true to show a loading indicator (e.g., spinner).
  • Then it sends a message to Node-RED requesting the dashboard data.
  • The request message looks like:

Sample Request Payload

{
  "type": "getDashboard",
  "auth": {},
  "userToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwidXNlclRva2VuIjoiU09NRV9SQU5ET01fVE9LRU5fMTc2MTU5OTExNzkxNCIsInByb2ZpbGUiOnsidXNlcklkIjoiNjhmZmNjMjFkNmM0Mzk4ZWE1ZjVjY2Y5IiwiaWQiOjEwLCJlbWFpbCI6ImhAZ21haWwuY29tIiwicm9sZXMiOlsiYXBwbGljYW50Il0sImZ1bGxOYW1lIjoiaGVkaXllaCJ9LCJhY3Rpb24iOiJsb2dpbiIsImlhdCI6MTc2MTU5OTExNywiZXhwIjoxNzYxNjAyNzE3fQ.mkvYqaZX1Y8m8gJdS3VAlQvDJ7zj3amk-Rc59rKkR8k",
  "clientId": "DucPqZtrHFQNgOnyiGV02",
  "_socketId": "X6ZKjzzFvV-ibjhwAEiI",
  "_msgid": "8bd0ae08cdfe06a9"
}

Enter fullscreen mode Exit fullscreen mode

Backend Node-RED Flow

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

Backend Flow Summary

Purpose

This backend flow dynamically builds the Applicant and Auditor dashboard by retrieving and combining user-specific and role-specific data from MongoDB.

Process Overview

Identify User Role:

Extracts and interprets the user’s roles to determine access type (Applicant, Auditor, etc.).

Route by Role:

Directs the flow to the appropriate logic branch depending on the identified role.

Retrieve Requests:

  • Applicant Requests: Queries records created by the user.
  • Auditor Requests: Fetches items pending review or action based on role permissions.

Note:
Auditor Dashboard
Can view requests in: Pending, Audited, Rejected
Applicant Dashboard

Can view requests in: Pending, Audited, Approved, Rejected

Normalize Data:

Standardizes each record’s format for the front-end, enriching it with user and request metadata.

Prepare Final Dashboard Payload:

Merges both Applicant and Auditor data streams with the user’s full profile to produce a unified, front-end-ready response.

Send to Front-End (uibuilder):

The formatted payload is sent through a Link Out node, then displayed in the user’s dashboard interface.


Response Examples (uibuilder.onChange)

{
{
  "type": "getDashboard",
  "auth": {},
  "_socketId": "0KAO_QB8U2vpv5xDAElI",
  "_msgid": "b668b84c0ec154e7",
  "_archiveRequest": null,
  "_editCompanyDetails": null,
  "_waitingForResponse": null,
  "_editProfile": null,
  "_approveRequest": null,
  "collection": "Requests",
  "operation": "find",
  "payload": {
    "options": {},
    "userId": "68f830f9d6c4398ea5f5cbdf",
    "user": {},
    "_phase": "Auditor",
    "applicantRequests": [
      /* 13 request objects */
    ],
    "auditorRequests": [
      /* 16 request objects */
    ]
  }
}

Enter fullscreen mode Exit fullscreen mode

MongoDB Requests Collection Schema

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

Sample document:

{
  "_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"
}

Enter fullscreen mode Exit fullscreen mode

3. getDashboard(Applicant and Approver) Flow

High-Level Flow:

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)
Enter fullscreen mode Exit fullscreen mode

Frontend getDashboard (Applicant and Approver)

   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')
        }
    });
Enter fullscreen mode Exit fullscreen mode
  • uibuilder.start() starts the communication channel with Node-RED via WebSocket.
  • It sets isLoading = true to show a loading indicator (e.g., spinner).
  • Then it sends a message to Node-RED requesting the dashboard data.
  • The request message looks like:

Sample Request Payload

{
  "type": "getDashboard",
  "auth": {},
  "userToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwidXNlclRva2VuIjoiU09NRV9SQU5ET01fVE9LRU5fMTc2MTU5OTExNzkxNCIsInByb2ZpbGUiOnsidXNlcklkIjoiNjhmZmNjMjFkNmM0Mzk4ZWE1ZjVjY2Y5IiwiaWQiOjEwLCJlbWFpbCI6ImhAZ21haWwuY29tIiwicm9sZXMiOlsiYXBwbGljYW50Il0sImZ1bGxOYW1lIjoiaGVkaXllaCJ9LCJhY3Rpb24iOiJsb2dpbiIsImlhdCI6MTc2MTU5OTExNywiZXhwIjoxNzYxNjAyNzE3fQ.mkvYqaZX1Y8m8gJdS3VAlQvDJ7zj3amk-Rc59rKkR8k",
  "clientId": "DucPqZtrHFQNgOnyiGV02",
  "_socketId": "X6ZKjzzFvV-ibjhwAEiI",
  "_msgid": "8bd0ae08cdfe06a9"
}

Enter fullscreen mode Exit fullscreen mode

Backend Node-RED Flow

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

Backend Flow Summary

Purpose

The backend flow dynamically generates the Applicant and Approver dashboard by fetching and combining requests based on user role from MongoDB.

Workflow

Role Detection:

Extracts the user’s roles and categorizes them into one of four types. Sets msg.payload and msg.user.

Role-Based Routing:

Uses a switch node to send messages to different flow branches depending on the user role.

Fetch Requests:

Applicant Requests: Fetches all requests created by the logged-in user.

Approver Requests: Fetches requests with:

  • Status Audited or Approved.
  • Rejected requests, but only those rejected by Approvers, excluding any rejected by Auditors.

Normalize Data:

Formats requests to include essential user metadata for consistent front-end rendering.

Prepare Dashboard Payload:

Combines applicant and approver requests with full user profile to generate msg.payload for the front-end.

Send to Front-End:

Final payload is passed through a Link Out node to UI components (e.g., uibuilder).

Response Examples (uibuilder.onChange)

{
  ""type"": ""getDashboard"",
  ""auth"": {
    ""userToken"": ""eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwidXNlclRva2VuIjoiU09NRV9SQU5ET01fVE9LRU5fMTc2MTYxODg3NTczNSIsInByb2ZpbGUiOnsidXNlcklkIjoiNjhmODM2MzhkNmM0Mzk4ZWE1ZjVjYmU2IiwiaWQiOjIsImVtYWlsIjoibGVpbGEuaGFzc2FuQHNreW5ldC5zeXN0ZW1zIiwicm9sZXMiOlsiQXBwbGljYW50IiwiQXBwcm92ZXIiXSwiZnVsbE5hbWUiOiJMZWlsYSBIYXNzYW4ifSwiYWN0aW9uIjoibG9naW4iLCJpYXQiOjE3NjE2MTg4NzUsImV4cCI6MTc2MTYyMjQ3NX0.yC6fr76smTVPPr0kCrmTARcJQ5qiuGqYKvl8_16rcts""
  },
  ""clientId"": ""DucPqZtrHFQNgOnyiGV02"",
  ""_socketId"": ""l9Mu_3V_ZjsFAHcfAElj"",
  ""_msgid"": ""235919a3a70d095a"",
  ""_archiveRequest"": null,
  ""_editCompanyDetails"": null,
  ""_waitingForResponse"": null,
  ""_editProfile"": null,
  ""_approveRequest"": null,
  ""collection"": ""Requests"",
  ""operation"": ""find"",
  ""payload"": {},
  ""options"": {},
  ""userId"": ""68f83638d6c4398ea5f5cbe6"",
  ""user"": {},
  ""_phase"": ""Approver"",
  ""applicantRequests"": [],
  ""approverRequests"": [
    {},
    {},
    {},
    {}
  ]
}
Enter fullscreen mode Exit fullscreen mode

MongoDB Requests Collection Schema

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

Sample document:

{
  "_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"
}

Enter fullscreen mode Exit fullscreen mode

3. getDashboard(Admin) Flow

High-Level Flow:

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)
Enter fullscreen mode Exit fullscreen mode

Frontend getDashboard (Admin)

   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')
        }
    });
Enter fullscreen mode Exit fullscreen mode
  • uibuilder.start() starts the communication channel with Node-RED via WebSocket.
  • It sets isLoading = true to show a loading indicator (e.g., spinner).
  • Then it sends a message to Node-RED requesting the dashboard data.
  • The request message looks like:

Sample Request Payload

{
  "type": "getDashboard",
  "auth": {},
  "userToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwidXNlclRva2VuIjoiU09NRV9SQU5ET01fVE9LRU5fMTc2MTU5OTExNzkxNCIsInByb2ZpbGUiOnsidXNlcklkIjoiNjhmZmNjMjFkNmM0Mzk4ZWE1ZjVjY2Y5IiwiaWQiOjEwLCJlbWFpbCI6ImhAZ21haWwuY29tIiwicm9sZXMiOlsiYXBwbGljYW50Il0sImZ1bGxOYW1lIjoiaGVkaXllaCJ9LCJhY3Rpb24iOiJsb2dpbiIsImlhdCI6MTc2MTU5OTExNywiZXhwIjoxNzYxNjAyNzE3fQ.mkvYqaZX1Y8m8gJdS3VAlQvDJ7zj3amk-Rc59rKkR8k",
  "clientId": "DucPqZtrHFQNgOnyiGV02",
  "_socketId": "X6ZKjzzFvV-ibjhwAEiI",
  "_msgid": "8bd0ae08cdfe06a9"
}

Enter fullscreen mode Exit fullscreen mode

Backend Node-RED Flow

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

Backend Flow Summary

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

Response Examples (uibuilder.onChange)

{
"{
  ""type"": ""getDashboard"",
  ""auth"": {
    ""userToken"": ""eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IiJ9.eyJzdGF0dXMiOiJzdWNjZXNzIiwidXNlclRva2VuIjoiU09NRV9SQU5ET01fVE9LRU5fMTc2MTYxOTI0MjQ4MiIsInByb2ZpbGUiOnsidXNlcklkIjoiNjhmODQ0NDlkNmM0Mzk4ZWE1ZjVjYmVlIiwiaWQiOjQsImVtYWlsIjoiZmFyaWQubW9yYWRpQHF1YW50dW1lZGdlLmlvIiwicm9sZXMiOlsiQWRtaW4iXSwiZnVsbE5hbWUiOiJGYXJpZCBNb3JhZGkifSwiYWN0aW9uIjoibG9naW4iLCJpYXQiOjE3NjE2MTkyNDIsImV4cCI6MTc2MTYyMjg0Mn0.GhkUkVsHVYPN3HtrJ8dgnCggAdXGXP0KSQIJYWtPx_w""
  },
  ""clientId"": ""DucPqZtrHFQNgOnyiGV02"",
  ""_socketId"": ""pP_KxEJNyY96NbnHAEl1"",
  ""_msgid"": ""1f420fa785af463d"",
  ""_archiveRequest"": null,
  ""_editCompanyDetails"": null,
  ""_waitingForResponse"": null,
  ""_editProfile"": null,
  ""_approveRequest"": null,
  ""collection"": ""Requests"",
  ""operation"": ""find"",
  ""payload"": {
    ""type"": ""getDashboard"",
    ""requests"": [
      {},

    ],
    ""profile"": {},
    ""options"": {}
  },
  ""userId"": ""68f84449d6c4398ea5f5c""
}
"
Enter fullscreen mode Exit fullscreen mode

MongoDB Requests Collection Schema

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

Sample document:

{
  "_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"
}

Enter fullscreen mode Exit fullscreen mode


Collections Overview

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

Request and Response

Type Action Overview Flow Overview uibuilder.send (request) uibuilder.onChange (response)
signup Handles new user registration and account creation. Users — A new record is added with details such as fullName, email, password, and role. Validation ensures the email is unique before saving. {"auth": {},"clientId": "oD6i_WpIes8pBvWjNXy81","fullName": "hediyeh","email": "h@gmail.com","password": "111111","confirmPassword": "111111","type": "signup","_socketId": "kmN2iMG_VAMQ7WSFAEhJ","topic": "uibuilder","_msgid": "96c8e068f17bef90"} // 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"}
login Authenticates existing users and establishes a secure session. Users — Validates credentials (email, password). Tokens — Generates a new authentication token to manage the session and track expiration. {"auth": {},"clientId": "oD6i_WpIes8pBvWjNXy81","email": "h@gmail.com","password": "111111","rememberMe": false,"type": "login","_socketId": "70nLJLlIrgzsiFLpAEhQ","topic": "uibuilder","_msgid": "2e88832acfbcd402"} // Failure Response 1: Email not found {"action": "login","status": "invalidCredentials","message": "Email not found."} // Failure Response 2: Password does not match {"action": "login","status": "invalidCredentials","message": "Password does not match."} // Success Response: Logged in successfully {"action": "login","status": "success","message": "Logged In Successfully"}
logOut Ends the user session and removes authentication. Tokens — Invalidates the user token. {"type": "logOut","auth": {},"userToken": "<userToken>","clientId": "DucPqZtrHFQNgOnyiGV02","_socketId": "0TlVsj-P27gZSW9TAEhb","topic": "uibuilder","_msgid": "9cfd70eb231eb96c"} N/A
sendResetCode Initiates the password recovery process. PasswordResets — Creates a record with a verification code, userId, email, createdAt, and expiresAt. {"auth": {},"type": "resetPassword","email": "h@gmail.com","_socketId": "TQQZkMEJW3yr8AXbAEhi","topic": "uibuilder","_msgid": "563ae2fa2bd25a81"} // 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"}
resetPassword Finalizes password change after validation. Users — Commits the new password. PasswordResets — Confirms the reset process is completed and the code is invalidated. {"auth": {},"type": "resetPassword","email": "h@gmail.com","_socketId": "TQQZkMEJW3yr8AXbAEhi","topic": "uibuilder","_msgid": "563ae2fa2bd25a81"} // Failure Response {"action": "resetPassword","status": "invalidEmail","message": "Email address not found."} // Success Response {"action": "resetPassword","status": "validEmail","message": "Reset code sent to your email"}
resendResetPassword Resends a password reset code. PasswordResets — Updates or regenerates a reset code and resends it. {"auth": {},"email": "h@gmail.com","type": "resendResetPassword","_socketId": "TQQZkMEJW3yr8AXbAEhi","topic": "TrustedCloud Password Reset Code – Action Required","_msgid": "a8539873adf09c69"} // Failure Response {"action": "resetPassword","status": "invalidEmail","message": "Email address not found."} // Success Response {"action": "resetPassword","status": "validEmail","message": "Reset code sent to your email"}
setNewPassword Updates the password after reset code verification. Users — Updates the password field for the corresponding account. PasswordResets — Marks the code as “used.” {"auth": {},"type": "setNewPassword","email": "h@gmail.com","password": "123456","_socketId": "3hHNyKWUI-Khbn9cAEh0","topic": "TrustedCloud Password Reset Code – Action Required","_msgid": "4a86446e49c05025"} // Success Response {"action": "setNewPassword","status": "success","message": "Password updated successfully."}
archiveRequest Moves completed or inactive requests to an archived state. Requests — Sets the archive flag to true for historical tracking. {"type": "archiveRequest","auth": {"userToken": "<userToken>"},"clientId": "DucPqZtrHFQNgOnyiGV02","requestID": 13,"_socketId": "0KAO_QB8U2vpv5xDAElI","topic": "uibuilder","_msgid": "7c5fc73c0374d772"} N/A
editCompanyDetails Allows users to update company info in a request. Requests — Updates companyDetails for a specific requestId. {"type": "editCompanyDetails","auth": {"userToken": "<userToken>"},"clientId": "DucPqZtrHFQNgOnyiGV02","companyDetails": {},"_socketId": "0KAO_QB8U2vpv5xDAElI","topic": "uibuilder","_msgid": "318f5048ec2d"} N/A
editProfile Modifies personal user information. Users — Updates profile fields like name, email, and avatar. {"type": "editProfile","auth": {"userToken": "<userToken>"},"clientId": "DucPqZtrHFQNgOnyiGV02","profile": {"userId": "68f830f9d6c4398ea5f5cbdf","email": "david.kim@brightwave.co","role": "Applicant","roles": ["Applicant","Auditor"]}} N/A
auditRequest Marks a request as “Audited” by an Auditor. Requests — Updates status to “Audited” and logs auditor info. {"type": "auditRequest","auth": {"userToken": "<userToken>"},"clientId": "DucPqZtrHFQNgOnyiGV02","userId": "68f830f9d6c4398ea5f5cbdf","requestId": 18,"auditDecision": {"status": "Audited","auditDate": "2025-10-28","comment": "yes"},"_socketId": "0KAO_QB8U2vpv5xDAElI","topic": "uibuilder","_msgid": "196c7d70d5cc4"} N/A
approveRequest Approvers mark a request as “Approved.” Requests — Updates status to “Approved” and logs approver info. {"type": "approveRequest","auth": {"userToken": "<userToken>"},"clientId": "DucPqZtrHFQNgOnyiGV02","userId": "68f83638d6c4398ea5f5cbe6","requestId": 18,"approverDecision": {},"_socketId": "fVUzLOHQeYT96ZrqAEla","topic": "uibuilder","_msgid": "b26bc97d28188"} N/A
createRequest (Applicant) Initiates a new request submission. Requests — Creates a record with companyDetails, userId, status, and timestamps. {"type": "createRequest","auth": {"userToken": "<userToken>"},"clientId": "DucPqZtrHFQNgOnyiGV02","companyDetails": {},"_socketId": "0KAO_QB8U2vpv5xDAElI","topic": "uibuilder","_msgid": "46c1c3b28576"} {"status": "success","action": "createRequest","message": "Request created successfully."}
getDashboard (Applicant & Auditor) Retrieves user-specific dashboard data. Requests — Fetches data based on user role and status. Users — Determines role to tailor dashboard view. {"type": "getDashboard","auth": {},"userToken": "<userToken>","clientId": "DucPqZtrHFQNgOnyiGV02","_socketId": "X6ZKjzzFvV-ibjhwAEiI","_msgid": "8bd0ae08cdfe06a9"} {"type": "getDashboard","payload": {"applicantRequests": [/*...*/],"auditorRequests": [/*...*/]}}
getDashboard (Applicant & Approver) Retrieves user-specific dashboard data. Requests — Fetches data based on role. Users — Determines role to tailor dashboard view. {"type": "getDashboard","auth": {},"userToken": "<userToken>","clientId": "DucPqZtrHFQNgOnyiGV02","_socketId": "X6ZKjzzFvV-ibjhwAEiI","_msgid": "8bd0ae08cdfe06a9"} {"type": "getDashboard","payload": {"applicantRequests": [],"approverRequests": [{},{},{},{}]}}
getDashboard (Admin) Retrieves dashboard for Admin users. Requests — Fetches all requests. Users — Admin role gets full access. {"type": "getDashboard","auth": {},"userToken": "<userToken>","clientId": "DucPqZtrHFQNgOnyiGV02","_socketId": "X6ZKjzzFvV-ibjhwAEiI","_msgid": "8bd0ae08cdfe06a9"} {"type": "getDashboard","payload": {"requests": [{}],"profile": {}}}
getDashboard (Applicant) Retrieves dashboard for Applicant. Requests — Fetches only the applicant's requests. Users — Determines role to tailor view. {"type": "getDashboard","auth": {},"userToken": "<userToken>","clientId": "DucPqZtrHFQNgOnyiGV02","_socketId": "X6ZKjzzFvV-ibjhwAEiI","_msgid": "8bd0ae08cdfe06a9"} {"type": "getDashboard","payload": {"applicantRequests": [{"_id": "68ffe1e7d6c4398ea5f5cd08","status": "Pending","profile": {"userId": "68ffe196d6c4398ea5f5cd06","roles": ["Applicant"]}}]}}

Top comments (0)