@deep-systems/user-management
v1.0.3
Published
Framework-agnostic Web Component package for User, Group, and Permission Management with Spring Boot REST Backend integration.
Readme
🚀 User Management NPM Package
A lightweight, framework-agnostic Web Component & SDK package for User, Group, Permission Management, and Authentication (Login & Signup) with Spring Boot REST API integration. Built with Lit Element 3 and Vite.
📌 Features
- 🌐 Framework Agnostic: Works natively in React, Vue, Angular, Svelte, or Vanilla HTML/JS.
- 👤 Full User Entity Support: Integrates
name(Full Name),username,email, andpassword. - 🔐 Authentication Components: Pre-built
<um-login>and<um-signup>components integrated with Spring Boot/api/auth/*endpoints. - 🌍 RTL & LTR Localization: Arabic (
ar) and English (en) support out-of-the-box. - 🔑 JWT Auth Integration: Automatic token injection,
401session refresh retries, and localized403permission handling. - ⚙️ Fully Customizable Endpoints: Overridable API paths, HTTP methods, pagination parameters, and response transformers.
📦 Installation
npm install @deep-systems/user-managementOption 1: Via Git Repository (Recommended for Team Collaboration)
npm install git+https://github.com/your-org/user-management.gitOption 2: Via Local Path (During Local Development)
npm install file:../user-management⚡ Quick Start
1. Full User Management App (SDK)
import { UserManagement } from '@deep-systems/user-management';
// 1. Initialize the SDK
const um = new UserManagement({
baseApi: 'http://localhost:8080', // Full URL of your Spring Boot backend
lang: 'ar', // 'ar' for Arabic (RTL) or 'en' for English (LTR)
redirectUrl: '/dashboard', // Optional: URL to redirect user after successful login
});
// 2. Mount to your container element or CSS selector
// - If user has NO JWT token: automatically renders centered Login screen
// - If user IS authenticated: renders User Management Dashboard with Logout button
um.mount('#user-mgmt-container');
// 3. Unmount / cleanup when navigating away
// um.unmount();2. Standalone Authentication Components (<um-login> & <um-signup>)
You can embed the Login and Signup components directly into any view:
HTML / Web Component Usage
<!-- Login Component -->
<um-login id="login-form" lang="en"></um-login>
<!-- Signup Component -->
<um-signup id="signup-form" lang="en"></um-signup>
<script type="module">
import '@deep-systems/user-management';
const loginEl = document.getElementById('login-form');
loginEl.config = {
baseApi: 'http://localhost:8080',
auth: { redirectUrl: '/dashboard' } // Optional custom redirect URL
};
loginEl.addEventListener('um-login-success', (e) => {
console.log('Logged in successfully!', e.detail.token);
});
loginEl.addEventListener('um-switch-to-signup', () => {
// Navigate to signup screen
});
</script>3. React Integration (useRef & useEffect)
import React, { useEffect, useRef } from 'react';
import { UserManagement } from '@deep-systems/user-management';
export function UserManagementPage() {
const containerRef = useRef(null);
useEffect(() => {
const um = new UserManagement({
baseApi: 'http://localhost:8080',
lang: 'ar',
redirectUrl: '/dashboard',
});
if (containerRef.current) {
um.mount(containerRef.current);
}
// Cleanup on component unmount
return () => um.unmount();
}, []);
return <div ref={containerRef} style={{ minHeight: '600px' }}></div>;
}⚙️ Configuration Options
| Option | Type | Default | Description |
| --- | --- | --- | --- |
| baseApi | string | '' | Backend server URL (e.g. 'http://localhost:8080'). |
| lang | string | 'en' | Interface language: 'ar' (Arabic RTL) or 'en' (English LTR). |
| initialView | string | null | Force specific startup view: 'login', 'signup', 'users', 'groups', 'permissions'. |
| auth.redirectUrl | string | null | Custom URL to redirect the browser after successful login (e.g. '/dashboard'). If omitted, package loads the internal User Management dashboard. |
| auth.tokenKey | string | 'access_token' | Key name used to read/write the JWT token in localStorage. |
| endpoints | object | {} | Custom endpoint path overrides, methods, pagination, and response transformers. |
🛠️ Customizing Endpoint Paths & Handlers (Complete Reference)
If your API endpoints, HTTP methods, pagination keys, or payload structures differ from the standard defaults, you can completely override them. Below is the full reference of all available endpoints and field mappings:
import { UserManagement } from '@deep-systems/user-management';
const um = new UserManagement({
baseApi: 'http://localhost:8080',
lang: 'ar',
endpoints: {
// ─────────────────────────────────────────────────────────
// 1️⃣ AUTHENTICATION ENDPOINTS
// ─────────────────────────────────────────────────────────
auth: {
// POST /api/auth/login — User authentication
login: {
url: '/api/auth/login',
method: 'POST',
// Outgoing body: { username, password }
// Expected response: { token: '...' } or { accessToken: '...' }
transformResponse: (res) => res,
},
// POST /api/auth/signup — User registration (default USER group assignment)
signup: {
url: '/api/auth/signup',
method: 'POST',
// Outgoing body: { name, username, email, password }
// Expected response: UserResponseDto object
transformResponse: (res) => res,
},
},
// ─────────────────────────────────────────────────────────
// 2️⃣ USERS ENDPOINTS
// ─────────────────────────────────────────────────────────
users: {
// GET /api/users — Fetch paginated user list
list: {
url: '/api/users',
method: 'GET',
// Transform incoming backend response to expected package structure
transformResponse: (res) => {
const rawItems = res.data || res.content || res;
return {
items: Array.isArray(rawItems) ? rawItems.map(user => ({
...user,
id: user.userId || user.id, // Override ID field
name: user.name || user.fullName, // Full name field
username: user.username, // Username field
email: user.emailAddress || user.email, // Email field
})) : [],
total: res.total || res.totalElements || (Array.isArray(rawItems) ? rawItems.length : 0),
};
},
pagination: {
pageSize: 10,
pageParam: 'page',
sizeParam: 'size',
},
},
// GET /api/users/:id — Fetch single user details
get: {
url: '/api/users/:id',
method: 'GET',
transformResponse: (user) => ({
...user,
id: user.userId || user.id,
name: user.name || user.fullName,
username: user.username,
email: user.emailAddress || user.email,
}),
},
// GET /api/users/:userId/groups — Fetch user's assigned groups
getGroups: {
url: '/api/users/:userId/groups',
method: 'GET',
transformResponse: (res) => {
const rawGroups = res.data || res.content || res;
return (Array.isArray(rawGroups) ? rawGroups : []).map(group => ({
...group,
id: group.groupId || group.id,
name: group.groupName || group.name,
}));
},
},
// POST /api/users — Create a new user
create: {
url: '/api/users',
method: 'POST',
// Outgoing body: { name, username, email, password }
transformRequest: (payload) => ({
...payload,
name: payload.name,
username: payload.username,
emailAddress: payload.email,
}),
},
// PUT /api/users/:id — Update an existing user
update: {
url: '/api/users/:id',
method: 'PUT',
// Outgoing body: { name, username, email, password (optional) }
transformRequest: (payload) => ({
...payload,
name: payload.name,
username: payload.username,
emailAddress: payload.email,
}),
},
// DELETE /api/users/:id — Delete a user
delete: {
url: '/api/users/:id',
method: 'DELETE',
},
// POST /api/users/:userId/groups/:groupId — Assign group to user
assignGroup: {
url: '/api/users/:userId/groups/:groupId',
method: 'POST',
},
// DELETE /api/users/:userId/groups/:groupId — Remove group from user
removeGroup: {
url: '/api/users/:userId/groups/:groupId',
method: 'DELETE',
},
},
// ─────────────────────────────────────────────────────────
// 3️⃣ GROUPS ENDPOINTS
// ─────────────────────────────────────────────────────────
groups: {
// GET /api/groups — Fetch group list
list: {
url: '/api/groups',
method: 'GET',
transformResponse: (res) => {
const rawItems = res.data || res.content || res;
return {
items: Array.isArray(rawItems) ? rawItems.map(group => ({
...group,
id: group.groupId || group.id, // Group ID
name: group.groupTitle || group.name, // Group display name
description: group.desc || group.description, // Group description
})) : [],
total: res.total || res.totalElements || (Array.isArray(rawItems) ? rawItems.length : 0),
};
},
},
// GET /api/groups/:id — Fetch single group
get: {
url: '/api/groups/:id',
method: 'GET',
transformResponse: (group) => ({
...group,
id: group.groupId || group.id,
name: group.groupTitle || group.name,
}),
},
// GET /api/groups/:groupId/permissions — Fetch permissions assigned to a group
getPermissions: {
url: '/api/groups/:groupId/permissions',
method: 'GET',
transformResponse: (res) => {
const rawPerms = res.data || res.content || res;
return (Array.isArray(rawPerms) ? rawPerms : []).map(perm => ({
...perm,
id: perm.permissionId || perm.id,
name: perm.code || perm.permissionName || perm.name,
}));
},
},
// POST /api/groups — Create group
create: {
url: '/api/groups',
method: 'POST',
transformRequest: (payload) => ({
...payload,
groupTitle: payload.name, // Map component 'name' -> backend 'groupTitle'
desc: payload.description, // Map component 'description' -> backend 'desc'
}),
},
// PUT /api/groups/:id — Update group
update: {
url: '/api/groups/:id',
method: 'PUT',
transformRequest: (payload) => ({
...payload,
groupTitle: payload.name,
desc: payload.description,
}),
},
// DELETE /api/groups/:id — Delete group
delete: {
url: '/api/groups/:id',
method: 'DELETE',
},
// POST /api/groups/:groupId/permissions/:permissionId — Assign permission to group
assignPermission: {
url: '/api/groups/:groupId/permissions/:permissionId',
method: 'POST',
},
// DELETE /api/groups/:groupId/permissions/:permissionId — Remove permission from group
removePermission: {
url: '/api/groups/:groupId/permissions/:permissionId',
method: 'DELETE',
},
},
// ─────────────────────────────────────────────────────────
// 4️⃣ PERMISSIONS ENDPOINTS
// ─────────────────────────────────────────────────────────
permissions: {
// GET /api/permissions — Fetch permission list
list: {
url: '/api/permissions',
method: 'GET',
transformResponse: (res) => {
const rawItems = res.data || res.content || res;
return {
items: Array.isArray(rawItems) ? rawItems.map(perm => ({
...perm,
id: perm.permissionId || perm.id, // Permission ID
name: perm.code || perm.permissionName || perm.name, // Permission code/name
description: perm.details || perm.description, // Description
})) : [],
total: res.total || res.totalElements || (Array.isArray(rawItems) ? rawItems.length : 0),
};
},
},
},
},
});🛠️ Development & Building
# Install dependencies
npm install
# Start local dev preview
npm run dev
# Build production bundle (ES & UMD in /dist)
npm run build