Skip to main content
Version: MarketPulse

User Management

Author(s)

  • Ashik

Last Updated Date

2026-03-04


SRS References

  • SRS Document: MarketPulse-SRS-v1.0
  • Section: User Management & Authentication
  • Document Link: User Management SRS

Version History

VersionDateAuthorChanges
1.02026-02-23AshikInitial user management document
2.02026-03-04AshikAdd role and scopes

Feature Overview

The User Management feature provides comprehensive user administration and authentication capabilities for the MarketPulse platform. This feature manages multiple user types including Admins, Resellers, and Dealers with role-based access control (RBAC) and secure authentication mechanisms.

Key Features

  • Multi-Entity Authentication: Separate login flows for Admin, Reseller, and Dealer users
  • Role-Based Access Control (RBAC): Dynamic role and scope management with granular permissions
  • User Lifecycle Management: Complete user registration, activation, deactivation, and profile management
  • JWT-Based Authentication: Secure token-based authentication with configurable expiration
  • Session Management: Track active sessions and maintain session history for audit purposes
  • Token Refresh: Automatic token renewal using refresh tokens for seamless user experience
  • Logout Functionality: Secure logout with session invalidation
  • Entity Hierarchy: Support for Admin → Reseller → Dealer organizational structure
  • Scope-Based Authorization: Fine-grained permission control through scope and role mapping
  • Profile Management: User profile CRUD operations with role-specific data
  • Audit Trail: Track user activities, login history, and permission changes

User Types

  1. Admin: Platform administrators with full system access
  2. Reseller: Organization-level users managing multiple dealers
  3. Dealer: Individual dealer users with location-specific access

Requirements

Functional Requirements

IDRequirementPriority
FR-1Admin user authentication with email/passwordHigh
FR-2Reseller user authentication with email/passwordHigh
FR-3Dealer user authentication with email/passwordHigh
FR-4User logout with session invalidationHigh
FR-5Token refresh using refresh tokensHigh
FR-6Role-based access control (RBAC)High
FR-7Scope-based authorization systemHigh
FR-8User profile management (CRUD operations)High
FR-9JWT token generation with configurable expiryHigh
FR-10Password encryption and validationHigh
FR-11Active session tracking and managementHigh
FR-12Login history and session audit trailMedium
FR-13User status management (Active/Inactive)Medium
FR-14Role and scope mapping managementMedium
FR-15Entity-based user isolationMedium
FR-16Primary role assignmentLow

Non-Functional Requirements

IDRequirementPriority
NFR-1System must handle 10,000+ concurrent usersHigh
NFR-2Authentication response time < 500msHigh
NFR-3Password encryption using industry standardsHigh
NFR-4JWT token validation latency < 100msHigh
NFR-599.9% uptime for authentication serviceHigh
NFR-6Support for timezone-based operationsMedium

Database Schema

AdminMaster Table

CREATE TABLE IF NOT EXISTS adminmaster (
adminid UUID PRIMARY KEY DEFAULT gen_random_uuid(),
name VARCHAR(255) NOT NULL,
primaryemail VARCHAR(255) NOT NULL UNIQUE,
primaryphone VARCHAR(20),
status VARCHAR(20) NOT NULL DEFAULT 'Active',
createdat TIMESTAMPTZ NOT NULL DEFAULT now(),
createdby UUID,
updatedat TIMESTAMPTZ NOT NULL DEFAULT now(),
updatedby UUID,

CONSTRAINT chkadminstatus CHECK (status IN ('Active', 'Disable', 'PendingActivation'))
);

CREATE INDEX IF NOT EXISTS idxadminemail ON adminmaster(primaryemail);
CREATE INDEX IF NOT EXISTS idxadminstatus ON adminmaster(status);

ResellerMaster Table

CREATE TABLE IF NOT EXISTS resellermaster (
resellerid UUID PRIMARY KEY DEFAULT gen_random_uuid(),
resellername VARCHAR(255) NOT NULL,
primaryemail VARCHAR(255) NOT NULL UNIQUE,
primaryphone VARCHAR(20),
status VARCHAR(20) NOT NULL DEFAULT 'Active',
createdat TIMESTAMPTZ NOT NULL DEFAULT now(),
createdby UUID NOT NULL,
updatedat TIMESTAMPTZ NOT NULL DEFAULT now(),
updatedby UUID,

CONSTRAINT fkcreatedbyadmin FOREIGN KEY (createdby) REFERENCES adminmaster(adminid),
CONSTRAINT chkresellerstatus CHECK (status IN ('Active', 'Disable', 'PendingActivation'))
);

CREATE INDEX IF NOT EXISTS idxreselleremail ON resellermaster(primaryemail);
CREATE INDEX IF NOT EXISTS idxresellerstatus ON resellermaster(status);
CREATE INDEX IF NOT EXISTS idxresellercreatedby ON resellermaster(createdby);

DealerMaster Table

CREATE TABLE DealerMaster (
dealerid UUID PRIMARY KEY,
dealername VARCHAR(255) NOT NULL,
timezone VARCHAR(50),
groupheaderid UUID,
createdat TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
updatedat TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_groupheader FOREIGN KEY (groupheaderid)
REFERENCES DealerMaster(dealerid)
);

UserDetails Table

CREATE TABLE IF NOT EXISTS userdetails (
userid UUID PRIMARY KEY DEFAULT gen_random_uuid(),
firstname VARCHAR(100) NOT NULL,
lastname VARCHAR(100) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE,
phone VARCHAR(20),
password VARCHAR(255) NOT NULL,
status VARCHAR(20) DEFAULT 'Active',
usertype VARCHAR(20) NOT NULL,
entityid UUID NOT NULL,
roleid UUID,
profileimageurl VARCHAR(500),
createdat TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
updatedat TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT fk_role FOREIGN KEY (roleid)
REFERENCES role(roleid)
);

Scope Table

CREATE TABLE IF NOT EXISTS scope (
scopeid UUID PRIMARY KEY DEFAULT gen_random_uuid(),
scopename VARCHAR(100) NOT NULL,
accesstype INTEGER NOT NULL,
displayname VARCHAR(100),
groupname VARCHAR(100),
groupsortorder INTEGER,
scopesortorder INTEGER,
description VARCHAR(255),
createdat TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);

Role Table

CREATE TABLE IF NOT EXISTS role (
roleid UUID PRIMARY KEY DEFAULT gen_random_uuid(),
rolename VARCHAR(50) NOT NULL,
description VARCHAR(255),
usertype VARCHAR(20) NOT NULL,
entityid UUID NOT NULL,
logusername VARCHAR(50),
logdts TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
status VARCHAR(20) DEFAULT 'Active',
createdat TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
updatedat TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
isprimary BOOLEAN DEFAULT false
);

RoleScopeMapping Table

CREATE TABLE IF NOT EXISTS rolescopemapping (
mappingid UUID PRIMARY KEY DEFAULT gen_random_uuid(),
roleid UUID NOT NULL,
scopeid UUID NOT NULL,
createdat TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT rolescopemapping_roleid_fkey FOREIGN KEY (roleid)
REFERENCES role(roleid),
CONSTRAINT rolescopemapping_scopeid_fkey FOREIGN KEY (scopeid)
REFERENCES scope(scopeid),
CONSTRAINT unique_role_scope UNIQUE (roleid, scopeid)
);

LoginHistory Table

CREATE TABLE IF NOT EXISTS loginhistory (
loginid UUID PRIMARY KEY DEFAULT gen_random_uuid(),
userid UUID NOT NULL,
attempttime TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
logintime TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
logouttime TIMESTAMPTZ,
issuccess BOOLEAN NOT NULL,
ipaddress VARCHAR(45),
devicetype TEXT,
useragent TEXT,
CONSTRAINT fk_user FOREIGN KEY (userid)
REFERENCES userdetails(userid)
);

ActiveSessions Table

CREATE TABLE IF NOT EXISTS activesessions (
sessionid UUID PRIMARY KEY DEFAULT gen_random_uuid(),
userid UUID NOT NULL,
loginid UUID NOT NULL,
refreshtoken TEXT NOT NULL,
devicetype TEXT,
useragent TEXT,
ipaddress VARCHAR(45),
logintime TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
lastrefreshedat TIMESTAMPTZ,
expiresat TIMESTAMPTZ,
CONSTRAINT activesessions_loginid_fkey FOREIGN KEY (loginid)
REFERENCES loginhistory(loginid),
CONSTRAINT activesessions_userid_fkey FOREIGN KEY (userid)
REFERENCES userdetails(userid)
);

SessionHistory Table

CREATE TABLE IF NOT EXISTS sessionhistory (
sessionid UUID PRIMARY KEY DEFAULT gen_random_uuid(),
userid UUID NOT NULL,
loginid UUID NOT NULL,
refreshtoken TEXT NOT NULL,
devicetype TEXT,
useragent TEXT,
ipaddress VARCHAR(45),
logintime TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
lastrefreshedat TIMESTAMPTZ,
logouttime TIMESTAMPTZ,
expiresat TIMESTAMPTZ,
isactive BOOLEAN DEFAULT true,
CONSTRAINT sessionhistory_loginid_fkey FOREIGN KEY (loginid)
REFERENCES loginhistory(loginid),
CONSTRAINT sessionhistory_userid_fkey FOREIGN KEY (userid)
REFERENCES userdetails(userid)
);

Data Models

AdminMaster

Stores administrator user information.

Fields:

  • adminid: Unique identifier for admin (auto-generated UUID)
  • name: Full name of administrator
  • primaryemail: Primary email address (unique, indexed)
  • primaryphone: Primary phone number
  • status: Active/Disable/PendingActivation status (indexed, default: 'Active')
  • createdat: Record creation timestamp (default: now())
  • createdby: User ID who created the record
  • updatedat: Last update timestamp (default: now())
  • updatedby: User ID who last updated the record

ResellerMaster

Stores reseller organization information.

Fields:

  • resellerid: Unique identifier for reseller (auto-generated UUID)
  • resellername: Reseller organization name
  • primaryemail: Primary email address (unique, indexed)
  • primaryphone: Primary phone number
  • status: Active/Disable/PendingActivation status (indexed, default: 'Active')
  • createdat: Record creation timestamp (default: now())
  • createdby: Admin ID who created the reseller (required, foreign key to adminmaster)
  • updatedat: Last update timestamp (default: now())
  • updatedby: User ID who last updated the record

DealerMaster

Stores dealer information with timezone and group hierarchy.

Fields:

  • dealerid: Unique identifier for dealer
  • dealername: Dealer name
  • timezone: Dealer's timezone (e.g., "America/New_York")
  • groupheaderid: Reference to parent dealer (for hierarchy)

UserDetails

Stores detailed user information for all user types.

Fields:

  • userid: Unique identifier for user
  • firstname: User's first name
  • lastname: User's last name
  • email: User email address (unique)
  • phone: Phone number
  • password: Hashed password
  • status: Active/Inactive status
  • usertype: Type of user (Admin/Reseller/Dealer)
  • entityid: Reference to entity (adminid/resellerid/dealerid)
  • roleid: Reference to user's role
  • profileimageurl: URL to profile image

Scope

Defines permission scopes for the system.

Fields:

  • scopeid: Unique identifier for scope
  • scopename: Technical name of scope
  • accesstype: Access level (0=None, 1=Read, 2=Write, 3=Full)
  • displayname: User-friendly display name
  • groupname: Logical grouping of scopes
  • groupsortorder: Sort order for groups
  • scopesortorder: Sort order within group
  • description: Scope description

Role

Defines user roles with entity-based isolation.

Fields:

  • roleid: Unique identifier for role
  • rolename: Role name
  • description: Role description
  • usertype: User type this role applies to (Admin/Reseller/Dealer)
  • entityid: Entity this role belongs to
  • logusername: User who created/modified the role
  • logdts: Log timestamp
  • status: Active/Inactive status
  • isprimary: Whether this is a primary role

RoleScopeMapping

Maps roles to scopes for permission management.

Fields:

  • mappingid: Unique identifier for mapping
  • roleid: Reference to role
  • scopeid: Reference to scope
  • createdat: Mapping creation timestamp

LoginHistory

Tracks all login attempts and sessions for audit purposes.

Fields:

  • loginid: Unique identifier for login attempt
  • userid: Reference to user
  • attempttime: When the login attempt was made
  • logintime: When login was successful
  • logouttime: When user logged out (if applicable)
  • issuccess: Whether login attempt was successful
  • ipaddress: IP address of login attempt
  • devicetype: Type of device (mobile, desktop, tablet)
  • useragent: Browser/client user agent string

ActiveSessions

Stores currently active user sessions with refresh tokens.

Fields:

  • sessionid: Unique identifier for session
  • userid: Reference to user
  • loginid: Reference to login history record
  • refreshtoken: Refresh token for session renewal
  • devicetype: Type of device
  • useragent: Browser/client user agent string
  • ipaddress: IP address of session
  • logintime: When session was created
  • lastrefreshedat: Last time token was refreshed
  • expiresat: When session expires

SessionHistory

Historical record of all user sessions for audit and compliance.

Fields:

  • sessionid: Unique identifier for session
  • userid: Reference to user
  • loginid: Reference to login history record
  • refreshtoken: Refresh token used in session
  • devicetype: Type of device
  • useragent: Browser/client user agent string
  • ipaddress: IP address of session
  • logintime: When session was created
  • lastrefreshedat: Last time token was refreshed
  • logouttime: When user logged out
  • expiresat: When session expired
  • isactive: Whether session is currently active

Request and Response Models

LoginRequest

public record LoginRequest
{
[Required(ErrorMessage = "Email is required")]
public required string Email { get; init; }

[Required(ErrorMessage = "Password is required")]
[DataType(DataType.Password)]
public required string Password { get; init; }
}

LoginResponse

public record LoginResponse
{
public string? AccessToken { get; set; }
public double? ExpiresIn { get; set; }
public string? TokenType { get; set; } = "Bearer";
}

CommonResponse

public record CommonResponse
{
public int Status { get; init; }
public string? Message { get; init; }
}

User

public record User
{
public Guid UserId { get; set; }
public string FirstName { get; set; } = string.Empty;
public string LastName { get; set; } = string.Empty;
public string? Email { get; set; }
public string? Phone { get; set; }
public string Password { get; set; } = string.Empty;
public Guid RoleId { get; set; } = Guid.Empty;
public Guid EntityId { get; set; }
public UserType UserType { get; set; }
public UserStatus? Status { get; set; }
public string? ProfileImageUrl { get; set; }
public DateTime? CreatedAt { get; set; }
public DateTime? UpdatedAt { get; set; }
public string? Designation { get; init; }
}

UserDetails

public record UserDetails
{
public Guid UserId { get; init; }
public string? FirstName { get; init; }
public string? LastName { get; init; }
public string? Email { get; init; }
public string? Phone { get; init; }
public DateTime CreatedAt { get; init; }
public DateTime UpdatedAt { get; init; }
public UserType UserType { get; init; }
public UserStatus Status { get; init; }
public string? EntityName { get; set; }
public string? RoleName { get; init; }
public Guid RoleId { get; init; }
public string? RoleDescription { get; init; }
public Guid EntityId { get; init; }
public bool IsPrimaryUser { get; init; } = false;
public string? Designation { get; set; }
}

Role

public record Role
{
public Guid RoleId { get; set; }
public string? RoleName { get; init; }
public string? Description { get; init; }
public UserType UserType { get; set; }
public Guid EntityId { get; set; }
public Status? Status { get; set; }
public string? LogUsername { get; set; }
public DateTime? LogDts { get; set; } = DateTime.UtcNow;
public DateTime? CreatedAt { get; set; } = DateTime.UtcNow;
public DateTime? UpdatedAt { get; set; } = DateTime.UtcNow;
public bool IsPrimary { get; set; } = false;
}

Scope

public record Scope
{
public Guid ScopeId { get; init; }
public required string ScopeName { get; init; }
public int AccessType { get; init; }
public required string DisplayName { get; init; }
public required string GroupName { get; init; }
public int GroupSortOrder { get; init; }
public int ScopeSortOrder { get; init; }
public string? Description { get; init; }
}

RoleWithScopeIds

public record RoleWithScopeIds : Role
{
public List<Guid> ScopeIds { get; set; } = new();
}

UserType Enum

public enum UserType
{
Admin = 1,
Reseller = 2,
Dealer = 4
}

UserStatus Enum

public enum UserStatus
{
Active = 1,
Disable = 2,
PendingActivation = 3
}

UserSortBy Enum

public enum UserSortBy
{
FirstName = 1,
LastName = 2,
Email = 3,
Phone = 4,
CreatedAt = 5,
UpdatedAt = 6
}

SortOrder Enum

public enum SortOrder
{
Ascending = 1,
Descending = 2
}

UserFilter

public record UserFilter
{
public string? FirstName { get; init; }
public string? LastName { get; init; }
public string? Email { get; init; }
public string? Phone { get; init; }
public UserStatus? Status { get; init; }
public UserType? UserType { get; set; }
public Guid? EntityId { get; set; }
public Guid? RoleId { get; init; }
public int RowsPerPage { get; set; } = 10;
public int PageNumber { get; set; } = 1;
public string? SearchKeyword { get; set; }
public UserSortBy SortBy { get; set; } = UserSortBy.CreatedAt;
public SortOrder SortOrder { get; set; } = SortOrder.Descending;
}

ServerPaginatedData<T>

public class ServerPaginatedData<T>
{
public List<T> Data { get; set; } = [];
public int TotalNumber { get; set; }
public bool HasPreviousPage { get; set; }
public bool HasNextPage { get; set; }
public int TotalPages { get; set; }
public int PageNumber { get; set; }
public int RowsPerPage { get; set; }
}

UserDetailsWithProfileImage

public record UserDetailsWithProfileImage : UserDetails
{
public string? ProfileImageUrl { get; init; }
}

API Interfaces

EndpointMethodPurposeParametersRequest ModelResponse ModelStatus Codes
/auth/admin-loginPOSTAuthenticate admin users and return JWT access token-LoginRequestLoginResponse200, 400, 401, 500
/auth/reseller-loginPOSTAuthenticate reseller users and return JWT access token-LoginRequestLoginResponse200, 400, 401, 500
/auth/dealer-loginPOSTAuthenticate dealer users and return JWT access token-LoginRequestLoginResponse200, 400, 401, 500
/auth/logoutPOSTLogout user and invalidate sessionJWT in header-CommonResponse200, 401, 500
/auth/refresh-tokenGETRefresh access token using refresh tokenJWT in header, Refresh token in cookie/header-LoginResponse200, 401, 500
/auth/usersPOSTCreate a new user in the systemJWT in headerUserCommonResponse200, 400, 401, 500
/auth/users/{userId}PUTUpdate an existing userJWT in header, userId (path)UserCommonResponse200, 400, 401, 404, 500
/auth/usersGETRetrieve paginated list of users with filtering and sortingJWT in headerUserFilterServerPaginatedData<UserDetails>200, 400, 401, 500
/auth/users/{userId}GETGet user details by user IDJWT in header, userId (path)-UserDetailsWithProfileImage200, 401, 404, 500
/auth/role-suggestionGETGet list of role suggestionsJWT in header-List<Role>200, 401, 500
/auth/scope-suggestionGETGet list of scope suggestionsJWT in header-List<Scope>200, 401, 500
/auth/rolePOSTCreate a new role with associated scopesJWT in headerRoleWithScopeIdsCommonResponse200, 400, 401, 500

API Examples

Admin Login Example

Request:

POST /auth/admin-login 
Host: marketpulse.inworkglobal.com/api
Content-Type: application/json

{
"email": "admin@marketpulse.com",
"password": "SecurePass123!"
}

Success Response (200 OK):

{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI1NTBlODQwMC1lMjliLTQxZDQtYTcxNi00NDY2NTU0NDAwMDAiLCJlbWFpbCI6ImFkbWluQG1hcmtldHB1bHNlLmNvbSIsInVzZXJUeXBlIjoiQWRtaW4iLCJlbnRpdHlJZCI6IjExMGU4NDAwLWUyOWItNDFkNC1hNzE2LTQ0NjY1NTQ0MDAwMCIsInJvbGVJZCI6IjIyMGU4NDAwLWUyOWItNDFkNC1hNzE2LTQ0NjY1NTQ0MDAwMCIsImlhdCI6MTcwODcwNDAwMCwiZXhwIjoxNzA4NzA3NjAwfQ.8yJvK5TmQa5L3xN2PX9h4R6tY7uV8wZ9aB1cD3eF4gH",
"expiresIn": 3600,
"tokenType": "Bearer"
}

Error Response (401 Unauthorized):

{
"error": "Unauthorized",
"message": "Invalid email or password"
}

Error Response (400 Bad Request):

{
"error": "ValidationError",
"message": "Email is required",
"details": {
"email": ["Email is required"]
}
}

Reseller Login Example

Request:

POST /auth/reseller-login 
Host: marketpulse.inworkglobal.com/api
Content-Type: application/json

{
"email": "reseller@acmecorp.com",
"password": "ResellerPass456!"
}

Success Response (200 OK):

{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2NjBmOTUwMC1mM2FjLTUyZTUtYjgyNy01NTc3NjY1NTExMTEiLCJlbWFpbCI6InJlc2VsbGVyQGFjbWVjb3JwLmNvbSIsInVzZXJUeXBlIjoiUmVzZWxsZXIiLCJlbnRpdHlJZCI6IjMzMGY5NTAwLWYzYWMtNTJlNS1iODI3LTU1Nzc2NjU1MTExMSIsInJvbGVJZCI6IjQ0MGY5NTAwLWYzYWMtNTJlNS1iODI3LTU1Nzc2NjU1MTExMSIsImlhdCI6MTcwODcwNDAwMCwiZXhwIjoxNzA4NzA3NjAwfQ.9zKwM6UnRb6M4yO3QY0i5S7uW9xA0a2bC4dE5fG6hJ",
"expiresIn": 3600,
"tokenType": "Bearer"
}

Dealer Login Example

Request:

POST /auth/dealer-login 
Host: marketpulse.inworkglobal.com/api
Content-Type: application/json

{
"email": "dealer@downtown.com",
"password": "DealerPass789!"
}

Success Response (200 OK):

{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI3NzBnMDYwMC1nNGJkLTYzZjYtYzkzOC02Njg4Nzc2NjIyMjIiLCJlbWFpbCI6ImRlYWxlckBkb3dudG93bi5jb20iLCJ1c2VyVHlwZSI6IkRlYWxlciIsImVudGl0eUlkIjoiNTUwZzA2MDAtZzRiZC02M2Y2LWM5MzgtNjY4ODc3NjYyMjIyIiwicm9sZUlkIjoiNjYwZzA2MDAtZzRiZC02M2Y2LWM5MzgtNjY4ODc3NjYyMjIyIiwidGltZXpvbmUiOiJBbWVyaWNhL05ld19Zb3JrIiwiaWF0IjoxNzA4NzA0MDAwLCJleHAiOjE3MDg3MDc2MDB9.0aLxN7VoSc7N5zP4RZ1j6T8vX0yB1b3cD5eF6gG7iK",
"expiresIn": 3600,
"tokenType": "Bearer"
}

Logout Example

Request:

POST /auth/logout 
Host: marketpulse.inworkglobal.com/api
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json

Success Response (200 OK):

{
"status": 200,
"message": "Logged out successfully"
}

Error Response (401 Unauthorized):

{
"status": 401,
"message": "Invalid or expired token"
}

Refresh Token Example

Request:

GET /auth/refresh-token 
Host: marketpulse.inworkglobal.com/api
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Cookie: refreshToken=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Success Response (200 OK):

{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI1NTBlODQwMC1lMjliLTQxZDQtYTcxNi00NDY2NTU0NDAwMDAiLCJlbWFpbCI6ImFkbWluQG1hcmtldHB1bHNlLmNvbSIsInVzZXJUeXBlIjoiQWRtaW4iLCJpYXQiOjE3MDg3MDc2MDAsImV4cCI6MTcwODcxMTIwMH0.9zKwM6UnRb6M4yO3QY0i5S7uW9xA0a2bC4dE5fG6hJ",
"expiresIn": 3600,
"tokenType": "Bearer"
}

Error Response (401 Unauthorized):

{
"status": 401,
"message": "Invalid or expired refresh token"
}

Create User Example

Request:

POST /auth/users 
Host: marketpulse.inworkglobal.com/api
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json

{
"userId": "00000000-0000-0000-0000-000000000000",
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"phone": "+1234567890",
"password": "SecurePassword123!",
"roleId": "440f9500-f3ac-52e5-b827-557766551111",
"entityId": "330f9500-f3ac-52e5-b827-557766551111",
"userType": "Dealer",
"status": "Active",
"profileImageUrl": "https://example.com/profile/johndoe.jpg",
"designation": "Sales Manager"
}

Success Response (200 OK):

{
"status": 200,
"message": "User created successfully"
}

Error Response (400 Bad Request):

{
"status": 400,
"message": "Validation failed: Email already exists"
}

Error Response (401 Unauthorized):

{
"status": 401,
"message": "Unauthorized: Invalid or expired token"
}

Error Response (500 Internal Server Error):

{
"status": 500,
"message": "An error occurred while creating the user"
}

Update User Example

Request:

PUT /auth/users/770g0600-g4bd-63f6-c938-668877662222
Host: marketpulse.inworkglobal.com/api
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json

{
"userId": "770g0600-g4bd-63f6-c938-668877662222",
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"phone": "+1234567890",
"password": "SecurePassword123!",
"roleId": "440f9500-f3ac-52e5-b827-557766551111",
"entityId": "330f9500-f3ac-52e5-b827-557766551111",
"userType": 4,
"status": 1,
"profileImageUrl": "https://example.com/profile/johndoe.jpg",
"designation": "Senior Sales Manager"
}

Success Response (200 OK):

{
"status": 200,
"message": "User updated successfully"
}

Error Response (400 Bad Request):

{
"status": 400,
"message": "Validation failed: Invalid email format"
}

Error Response (401 Unauthorized):

{
"status": 401,
"message": "Unauthorized: Invalid or expired token"
}

Error Response (404 Not Found):

{
"status": 404,
"message": "User not found"
}

Error Response (500 Internal Server Error):

{
"status": 500,
"message": "An error occurred while updating the user"
}

Get Paginated Users Example

Request:

GET /auth/users
Host: marketpulse.inworkglobal.com/api
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json

{
"firstName": null,
"lastName": null,
"email": null,
"phone": null,
"status": 1,
"userType": 4,
"entityId": "330f9500-f3ac-52e5-b827-557766551111",
"roleId": null,
"rowsPerPage": 10,
"pageNumber": 1,
"searchKeyword": "john",
"sortBy": 5,
"sortOrder": 2
}

Success Response (200 OK):

{
"data": [
{
"userId": "770g0600-g4bd-63f6-c938-668877662222",
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"phone": "+1234567890",
"createdAt": "2026-02-20T10:30:00Z",
"updatedAt": "2026-02-23T14:15:00Z",
"userType": 4,
"status": 1,
"entityName": "Downtown Dealership",
"roleName": "Sales Manager",
"roleId": "440f9500-f3ac-52e5-b827-557766551111",
"roleDescription": "Manages sales operations and team",
"entityId": "330f9500-f3ac-52e5-b827-557766551111",
"isPrimaryUser": false,
"designation": "Sales Manager"
},
{
"userId": "880h0700-h5ce-74g7-d049-779988773333",
"firstName": "Johnny",
"lastName": "Smith",
"email": "johnny.smith@example.com",
"phone": "+1987654321",
"createdAt": "2026-02-18T09:15:00Z",
"updatedAt": "2026-02-22T16:30:00Z",
"userType": 4,
"status": 1,
"entityName": "Downtown Dealership",
"roleName": "Sales Associate",
"roleId": "550f9600-f4bd-63f7-c939-668877664444",
"roleDescription": "Handles customer sales and inquiries",
"entityId": "330f9500-f3ac-52e5-b827-557766551111",
"isPrimaryUser": false,
"designation": "Associate"
}
],
"totalNumber": 25,
"hasPreviousPage": false,
"hasNextPage": true,
"totalPages": 3,
"pageNumber": 1,
"rowsPerPage": 10
}

Success Response - No Results (200 OK):

{
"data": [],
"totalNumber": 0,
"hasPreviousPage": false,
"hasNextPage": false,
"totalPages": 0,
"pageNumber": 1,
"rowsPerPage": 10
}

Error Response (400 Bad Request):

{
"status": 400,
"message": "Invalid filter parameters: PageNumber must be greater than 0"
}

Error Response (401 Unauthorized):

{
"status": 401,
"message": "Unauthorized: Invalid or expired token"
}

Error Response (500 Internal Server Error):

{
"status": 500,
"message": "An error occurred while retrieving users"
}

Get User Details By ID Example

Request:

GET /auth/users/770g0600-g4bd-63f6-c938-668877662222 
Host: marketpulse.inworkglobal.com/api
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Success Response (200 OK):

{
"userId": "770g0600-g4bd-63f6-c938-668877662222",
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@example.com",
"phone": "+1234567890",
"createdAt": "2026-02-20T10:30:00Z",
"updatedAt": "2026-02-23T14:15:00Z",
"userType": 4,
"status": 1,
"entityName": "Downtown Dealership",
"roleName": "Sales Manager",
"roleId": "440f9500-f3ac-52e5-b827-557766551111",
"roleDescription": "Manages sales operations and team",
"entityId": "330f9500-f3ac-52e5-b827-557766551111",
"isPrimaryUser": false,
"designation": "Sales Manager",
"profileImageUrl": "https://example.com/profile/johndoe.jpg"
}

Error Response (404 Not Found):

{
"status": 404,
"message": "User not found"
}

Error Response (401 Unauthorized):

{
"status": 401,
"message": "Unauthorized: Invalid or expired token"
}

Error Response (500 Internal Server Error):

{
"status": 500,
"message": "An error occurred while retrieving user details"
}

Get Role Suggestions

Request:

GET /auth/role-suggestion
Host: marketpulse.inworkglobal.com/api
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Success Response (200 OK):

[
{
"roleId": "440f9500-f3ac-52e5-b827-557766551111",
"roleName": "Sales Manager",
"description": "Manages sales operations and team",
"userType": 4,
"entityId": "330f9500-f3ac-52e5-b827-557766551111",
"status": 1,
"logUsername": "admin@marketpulse.com",
"logDts": "2026-02-23T14:15:00Z",
"createdAt": "2026-02-23T14:15:00Z",
"updatedAt": "2026-02-23T14:15:00Z",
"isPrimary": false
}
]

Get Scope Suggestions

Request:

GET /auth/scope-suggestion
Host: marketpulse.inworkglobal.com/api
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...

Success Response (200 OK):

[
{
"scopeId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"scopeName": "user.read",
"accessType": 1,
"displayName": "Read Users",
"groupName": "User Management",
"groupSortOrder": 1,
"scopeSortOrder": 1,
"description": "Allows reading user information"
}
]

Create Role

Request:

POST /auth/role
Host: marketpulse.inworkglobal.com/api
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Content-Type: application/json

{
"roleId": "00000000-0000-0000-0000-000000000000",
"roleName": "Sales Manager",
"description": "Manages sales operations and team",
"userType": 4,
"entityId": "330f9500-f3ac-52e5-b827-557766551111",
"status": 1,
"logUsername": "admin@marketpulse.com",
"logDts": "2026-02-23T14:15:00Z",
"createdAt": "2026-02-23T14:15:00Z",
"updatedAt": "2026-02-23T14:15:00Z",
"isPrimary": false,
"scopeIds": [
"a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"b2c3d4e5-f678-90ab-cdef-234567890abc"
]
}

Success Response (200 OK):

{
"status": 200,
"message": "Role created successfully"
}

Error Response (400 Bad Request):

{
"status": 400,
"message": "Validation failed: Role name already exists"
}

Error Response (401 Unauthorized):

{
"status": 401,
"message": "Unauthorized: Invalid or expired token"
}

Error Response (500 Internal Server Error):

{
"status": 500,
"message": "An error occurred while creating the role"
}

Development Tasks & Estimates

Task IDTask DescriptionEstimated HoursPriority
UM-001Create database schema (all 10 tables with relationships)5High
UM-002Implement password hashing and JWT utilities3High
UM-003Implement user authentication service4High
UM-004Create Admin Login API endpoint2High
UM-005Create Reseller Login API endpoint2High
UM-006Create Dealer Login API endpoint2High
UM-007Create Logout API endpoint1High
UM-008Create Refresh Token API endpoint2High
UM-009Implement session management (active & history)3High
UM-010Implement input validation and error handling2High
UM-011Write unit and integration tests3High
UM-012Code review and security audit1High
UM-013Deployment and configuration1High
Total31 hours

Review & Approval

  • Reviewer(s):

    • Sanket Mal
    • Ayan Ghosh
    • Ribhu Gautam
  • Approval Date: [To be completed after reviews]


Additional Notes

Security Considerations

  • All passwords must be hashed using bcrypt with a minimum of 12 rounds
  • JWT tokens should include user claims: userId, email, userType, entityId, roleId
  • Implement token refresh mechanism for long-lived sessions
  • Add rate limiting: 5 login attempts per 15 minutes per email/IP
  • Implement HTTPS-only communication in production
  • Store JWT secret in secure environment variables
  • Implement proper CORS policies

Performance Considerations

  • Index on email field in UserDetails table
  • Index on entityid field for faster entity-based queries
  • Cache role and scope mappings to reduce database queries
  • Implement connection pooling for database connections
  • Use Redis for session management if needed

Future Enhancements

  1. Multi-factor authentication (MFA)
  2. Password reset functionality
  3. Email verification for new users
  4. OAuth2/OpenID Connect integration
  5. Single Sign-On (SSO) support
  6. User activity audit logs
  7. Session management and concurrent login control
  8. Password policy enforcement (complexity, expiration)