exguard-backend 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +201 -0
- package/dist/index.cjs +154 -0
- package/dist/index.d.cts +87 -0
- package/dist/index.d.ts +87 -0
- package/dist/index.js +117 -0
- package/package.json +48 -0
package/README.md
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
# ExGuard Backend SDK
|
|
2
|
+
|
|
3
|
+
A simple and lightweight backend SDK for integrating with EmpowerX Guard API to validate user roles and permissions.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install exguard-backend
|
|
9
|
+
# or
|
|
10
|
+
yarn add exguard-backend
|
|
11
|
+
# or
|
|
12
|
+
pnpm add exguard-backend
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quick Start
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
import { ExGuardBackend } from 'exguard-backend';
|
|
19
|
+
|
|
20
|
+
// Initialize the SDK
|
|
21
|
+
const exGuard = new ExGuardBackend({
|
|
22
|
+
apiUrl: 'https://your-guard-api-url.com'
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
// Get user access information
|
|
26
|
+
async function checkUserAccess(token: string) {
|
|
27
|
+
try {
|
|
28
|
+
const userAccess = await exGuard.getUserAccess(token);
|
|
29
|
+
console.log('User roles:', userAccess.roles);
|
|
30
|
+
console.log('User permissions:', userAccess.modules);
|
|
31
|
+
} catch (error) {
|
|
32
|
+
console.error('Error:', error.message);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## API Reference
|
|
38
|
+
|
|
39
|
+
### Constructor
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
new ExGuardBackend(config: ExGuardConfig)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Config:**
|
|
46
|
+
- `apiUrl` (string): Base URL of your Guard API
|
|
47
|
+
- `timeout` (number, optional): Request timeout in milliseconds (default: 10000)
|
|
48
|
+
|
|
49
|
+
### Methods
|
|
50
|
+
|
|
51
|
+
#### `getUserAccess(token: string): Promise<UserAccessResponse>`
|
|
52
|
+
|
|
53
|
+
Get complete user access information including roles, permissions, and field offices.
|
|
54
|
+
|
|
55
|
+
**Returns:**
|
|
56
|
+
```typescript
|
|
57
|
+
{
|
|
58
|
+
user: User,
|
|
59
|
+
groups: string[],
|
|
60
|
+
roles: string[],
|
|
61
|
+
module: string[],
|
|
62
|
+
modules: ModulePermission[],
|
|
63
|
+
fieldOffices: string[]
|
|
64
|
+
}
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
#### `hasPermission(token: string, permission: string): Promise<boolean>`
|
|
68
|
+
|
|
69
|
+
Check if user has a specific permission.
|
|
70
|
+
|
|
71
|
+
**Example:**
|
|
72
|
+
```typescript
|
|
73
|
+
const canCreateEvent = await exGuard.hasPermission(token, 'events:create');
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
#### `hasRole(token: string, role: string): Promise<boolean>`
|
|
77
|
+
|
|
78
|
+
Check if user has a specific role.
|
|
79
|
+
|
|
80
|
+
**Example:**
|
|
81
|
+
```typescript
|
|
82
|
+
const isEventManager = await exGuard.hasRole(token, 'Event Manager');
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
#### `getModulePermissions(token: string, moduleKey: string): Promise<string[]>`
|
|
86
|
+
|
|
87
|
+
Get all permissions for a specific module.
|
|
88
|
+
|
|
89
|
+
**Example:**
|
|
90
|
+
```typescript
|
|
91
|
+
const eventPermissions = await exGuard.getModulePermissions(token, 'events');
|
|
92
|
+
// Returns: ['events:create', 'events:read', 'events:update', 'events:delete']
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
#### `getUserRoles(token: string): Promise<string[]>`
|
|
96
|
+
|
|
97
|
+
Get all user roles.
|
|
98
|
+
|
|
99
|
+
**Example:**
|
|
100
|
+
```typescript
|
|
101
|
+
const roles = await exGuard.getUserRoles(token);
|
|
102
|
+
// Returns: ['Event Manager', 'Viewer']
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
#### `getUserFieldOffices(token: string): Promise<string[]>`
|
|
106
|
+
|
|
107
|
+
Get all user field offices.
|
|
108
|
+
|
|
109
|
+
**Example:**
|
|
110
|
+
```typescript
|
|
111
|
+
const fieldOffices = await exGuard.getUserFieldOffices(token);
|
|
112
|
+
// Returns: ['FO-MIMAROPA', 'FO-NCR']
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## Usage Examples
|
|
116
|
+
|
|
117
|
+
### Express.js Middleware
|
|
118
|
+
|
|
119
|
+
```typescript
|
|
120
|
+
import express from 'express';
|
|
121
|
+
import { ExGuardBackend } from 'exguard-backend';
|
|
122
|
+
|
|
123
|
+
const app = express();
|
|
124
|
+
const exGuard = new ExGuardBackend({
|
|
125
|
+
apiUrl: process.env.GUARD_API_URL || 'http://localhost:3001'
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// Middleware to check permissions
|
|
129
|
+
const requirePermission = (permission: string) => {
|
|
130
|
+
return async (req: express.Request, res: express.Response, next: express.NextFunction) => {
|
|
131
|
+
const token = req.headers.authorization?.replace('Bearer ', '');
|
|
132
|
+
|
|
133
|
+
if (!token) {
|
|
134
|
+
return res.status(401).json({ error: 'No token provided' });
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
const hasPermission = await exGuard.hasPermission(token, permission);
|
|
139
|
+
if (!hasPermission) {
|
|
140
|
+
return res.status(403).json({ error: 'Insufficient permissions' });
|
|
141
|
+
}
|
|
142
|
+
next();
|
|
143
|
+
} catch (error) {
|
|
144
|
+
return res.status(401).json({ error: 'Invalid token' });
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
// Use in routes
|
|
150
|
+
app.post('/events', requirePermission('events:create'), (req, res) => {
|
|
151
|
+
// Your route logic here
|
|
152
|
+
});
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
### NestJS Guard
|
|
156
|
+
|
|
157
|
+
```typescript
|
|
158
|
+
import { Injectable, CanActivate, ExecutionContext } from '@nestjs/common';
|
|
159
|
+
import { ExGuardBackend } from 'exguard-backend';
|
|
160
|
+
|
|
161
|
+
@Injectable()
|
|
162
|
+
export class PermissionGuard implements CanActivate {
|
|
163
|
+
private exGuard = new ExGuardBackend({
|
|
164
|
+
apiUrl: process.env.GUARD_API_URL
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
constructor(private requiredPermission: string) {}
|
|
168
|
+
|
|
169
|
+
async canActivate(context: ExecutionContext): Promise<boolean> {
|
|
170
|
+
const request = context.switchToHttp().getRequest();
|
|
171
|
+
const token = request.headers.authorization?.replace('Bearer ', '');
|
|
172
|
+
|
|
173
|
+
if (!token) {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return await this.exGuard.hasPermission(token, this.requiredPermission);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Usage in controller
|
|
182
|
+
@Get('events')
|
|
183
|
+
@UseGuards(new PermissionGuard('events:read'))
|
|
184
|
+
async getEvents() {
|
|
185
|
+
// Your logic here
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Error Handling
|
|
190
|
+
|
|
191
|
+
The SDK throws specific errors for different scenarios:
|
|
192
|
+
|
|
193
|
+
- **Unauthorized**: Invalid or expired token (401)
|
|
194
|
+
- **API Error**: General API errors with detailed messages
|
|
195
|
+
- **Network Error**: Connection issues
|
|
196
|
+
|
|
197
|
+
Always wrap SDK calls in try-catch blocks for proper error handling.
|
|
198
|
+
|
|
199
|
+
## License
|
|
200
|
+
|
|
201
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/index.ts
|
|
31
|
+
var index_exports = {};
|
|
32
|
+
__export(index_exports, {
|
|
33
|
+
ExGuardBackend: () => ExGuardBackend
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(index_exports);
|
|
36
|
+
|
|
37
|
+
// src/exguard-backend.ts
|
|
38
|
+
var import_axios = __toESM(require("axios"), 1);
|
|
39
|
+
var ExGuardBackend = class {
|
|
40
|
+
constructor(config) {
|
|
41
|
+
this.config = {
|
|
42
|
+
timeout: 1e4,
|
|
43
|
+
...config
|
|
44
|
+
};
|
|
45
|
+
this.client = import_axios.default.create({
|
|
46
|
+
baseURL: this.config.apiUrl,
|
|
47
|
+
timeout: this.config.timeout,
|
|
48
|
+
headers: {
|
|
49
|
+
"Content-Type": "application/json"
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get user roles and permissions from the /guard/me endpoint
|
|
55
|
+
* @param token - JWT access token
|
|
56
|
+
* @returns Promise<UserAccessResponse>
|
|
57
|
+
*/
|
|
58
|
+
async getUserAccess(token) {
|
|
59
|
+
try {
|
|
60
|
+
const response = await this.client.get("/guard/me", {
|
|
61
|
+
headers: {
|
|
62
|
+
"Authorization": `Bearer ${token}`
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
if (!response.data.success) {
|
|
66
|
+
throw new Error("Failed to fetch user access information");
|
|
67
|
+
}
|
|
68
|
+
return response.data.data;
|
|
69
|
+
} catch (error) {
|
|
70
|
+
if (import_axios.default.isAxiosError(error)) {
|
|
71
|
+
if (error.response?.status === 401) {
|
|
72
|
+
throw new Error("Unauthorized: Invalid or expired token");
|
|
73
|
+
}
|
|
74
|
+
throw new Error(`API Error: ${error.response?.data?.message || error.message}`);
|
|
75
|
+
}
|
|
76
|
+
throw error;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Check if user has specific permission
|
|
81
|
+
* @param token - JWT access token
|
|
82
|
+
* @param permission - Permission to check (e.g., 'events:create')
|
|
83
|
+
* @returns Promise<boolean>
|
|
84
|
+
*/
|
|
85
|
+
async hasPermission(token, permission) {
|
|
86
|
+
try {
|
|
87
|
+
const userAccess = await this.getUserAccess(token);
|
|
88
|
+
return userAccess.modules.some(
|
|
89
|
+
(module2) => module2.permissions.includes(permission)
|
|
90
|
+
);
|
|
91
|
+
} catch (error) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Check if user has specific role
|
|
97
|
+
* @param token - JWT access token
|
|
98
|
+
* @param role - Role to check (e.g., 'Event Manager')
|
|
99
|
+
* @returns Promise<boolean>
|
|
100
|
+
*/
|
|
101
|
+
async hasRole(token, role) {
|
|
102
|
+
try {
|
|
103
|
+
const userAccess = await this.getUserAccess(token);
|
|
104
|
+
return userAccess.roles.includes(role);
|
|
105
|
+
} catch (error) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Get all permissions for a specific module
|
|
111
|
+
* @param token - JWT access token
|
|
112
|
+
* @param moduleKey - Module key (e.g., 'events')
|
|
113
|
+
* @returns Promise<string[]>
|
|
114
|
+
*/
|
|
115
|
+
async getModulePermissions(token, moduleKey) {
|
|
116
|
+
try {
|
|
117
|
+
const userAccess = await this.getUserAccess(token);
|
|
118
|
+
const module2 = userAccess.modules.find((m) => m.key === moduleKey);
|
|
119
|
+
return module2?.permissions || [];
|
|
120
|
+
} catch (error) {
|
|
121
|
+
return [];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Get user roles
|
|
126
|
+
* @param token - JWT access token
|
|
127
|
+
* @returns Promise<string[]>
|
|
128
|
+
*/
|
|
129
|
+
async getUserRoles(token) {
|
|
130
|
+
try {
|
|
131
|
+
const userAccess = await this.getUserAccess(token);
|
|
132
|
+
return userAccess.roles;
|
|
133
|
+
} catch (error) {
|
|
134
|
+
return [];
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Get user field offices
|
|
139
|
+
* @param token - JWT access token
|
|
140
|
+
* @returns Promise<string[]>
|
|
141
|
+
*/
|
|
142
|
+
async getUserFieldOffices(token) {
|
|
143
|
+
try {
|
|
144
|
+
const userAccess = await this.getUserAccess(token);
|
|
145
|
+
return userAccess.fieldOffices;
|
|
146
|
+
} catch (error) {
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
};
|
|
151
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
152
|
+
0 && (module.exports = {
|
|
153
|
+
ExGuardBackend
|
|
154
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
interface User {
|
|
2
|
+
id: string;
|
|
3
|
+
cognitoSubId: string;
|
|
4
|
+
username: string;
|
|
5
|
+
email: string;
|
|
6
|
+
emailVerified: boolean;
|
|
7
|
+
givenName: string;
|
|
8
|
+
familyName: string;
|
|
9
|
+
employeeNumber: string;
|
|
10
|
+
regionId: string;
|
|
11
|
+
createdAt: string;
|
|
12
|
+
updatedAt: string;
|
|
13
|
+
lastLoginAt: string;
|
|
14
|
+
fieldOffice: {
|
|
15
|
+
id: string;
|
|
16
|
+
code: string;
|
|
17
|
+
name: string;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
interface ModulePermission {
|
|
21
|
+
key: string;
|
|
22
|
+
name: string;
|
|
23
|
+
permissions: string[];
|
|
24
|
+
}
|
|
25
|
+
interface UserAccessResponse {
|
|
26
|
+
user: User;
|
|
27
|
+
groups: string[];
|
|
28
|
+
roles: string[];
|
|
29
|
+
module: string[];
|
|
30
|
+
modules: ModulePermission[];
|
|
31
|
+
fieldOffices: string[];
|
|
32
|
+
}
|
|
33
|
+
interface ApiResponse<T> {
|
|
34
|
+
success: boolean;
|
|
35
|
+
data: T;
|
|
36
|
+
}
|
|
37
|
+
interface ExGuardConfig {
|
|
38
|
+
apiUrl: string;
|
|
39
|
+
timeout?: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
declare class ExGuardBackend {
|
|
43
|
+
private client;
|
|
44
|
+
private config;
|
|
45
|
+
constructor(config: ExGuardConfig);
|
|
46
|
+
/**
|
|
47
|
+
* Get user roles and permissions from the /guard/me endpoint
|
|
48
|
+
* @param token - JWT access token
|
|
49
|
+
* @returns Promise<UserAccessResponse>
|
|
50
|
+
*/
|
|
51
|
+
getUserAccess(token: string): Promise<UserAccessResponse>;
|
|
52
|
+
/**
|
|
53
|
+
* Check if user has specific permission
|
|
54
|
+
* @param token - JWT access token
|
|
55
|
+
* @param permission - Permission to check (e.g., 'events:create')
|
|
56
|
+
* @returns Promise<boolean>
|
|
57
|
+
*/
|
|
58
|
+
hasPermission(token: string, permission: string): Promise<boolean>;
|
|
59
|
+
/**
|
|
60
|
+
* Check if user has specific role
|
|
61
|
+
* @param token - JWT access token
|
|
62
|
+
* @param role - Role to check (e.g., 'Event Manager')
|
|
63
|
+
* @returns Promise<boolean>
|
|
64
|
+
*/
|
|
65
|
+
hasRole(token: string, role: string): Promise<boolean>;
|
|
66
|
+
/**
|
|
67
|
+
* Get all permissions for a specific module
|
|
68
|
+
* @param token - JWT access token
|
|
69
|
+
* @param moduleKey - Module key (e.g., 'events')
|
|
70
|
+
* @returns Promise<string[]>
|
|
71
|
+
*/
|
|
72
|
+
getModulePermissions(token: string, moduleKey: string): Promise<string[]>;
|
|
73
|
+
/**
|
|
74
|
+
* Get user roles
|
|
75
|
+
* @param token - JWT access token
|
|
76
|
+
* @returns Promise<string[]>
|
|
77
|
+
*/
|
|
78
|
+
getUserRoles(token: string): Promise<string[]>;
|
|
79
|
+
/**
|
|
80
|
+
* Get user field offices
|
|
81
|
+
* @param token - JWT access token
|
|
82
|
+
* @returns Promise<string[]>
|
|
83
|
+
*/
|
|
84
|
+
getUserFieldOffices(token: string): Promise<string[]>;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export { type ApiResponse, ExGuardBackend, type ExGuardConfig, type ModulePermission, type User, type UserAccessResponse };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
interface User {
|
|
2
|
+
id: string;
|
|
3
|
+
cognitoSubId: string;
|
|
4
|
+
username: string;
|
|
5
|
+
email: string;
|
|
6
|
+
emailVerified: boolean;
|
|
7
|
+
givenName: string;
|
|
8
|
+
familyName: string;
|
|
9
|
+
employeeNumber: string;
|
|
10
|
+
regionId: string;
|
|
11
|
+
createdAt: string;
|
|
12
|
+
updatedAt: string;
|
|
13
|
+
lastLoginAt: string;
|
|
14
|
+
fieldOffice: {
|
|
15
|
+
id: string;
|
|
16
|
+
code: string;
|
|
17
|
+
name: string;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
interface ModulePermission {
|
|
21
|
+
key: string;
|
|
22
|
+
name: string;
|
|
23
|
+
permissions: string[];
|
|
24
|
+
}
|
|
25
|
+
interface UserAccessResponse {
|
|
26
|
+
user: User;
|
|
27
|
+
groups: string[];
|
|
28
|
+
roles: string[];
|
|
29
|
+
module: string[];
|
|
30
|
+
modules: ModulePermission[];
|
|
31
|
+
fieldOffices: string[];
|
|
32
|
+
}
|
|
33
|
+
interface ApiResponse<T> {
|
|
34
|
+
success: boolean;
|
|
35
|
+
data: T;
|
|
36
|
+
}
|
|
37
|
+
interface ExGuardConfig {
|
|
38
|
+
apiUrl: string;
|
|
39
|
+
timeout?: number;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
declare class ExGuardBackend {
|
|
43
|
+
private client;
|
|
44
|
+
private config;
|
|
45
|
+
constructor(config: ExGuardConfig);
|
|
46
|
+
/**
|
|
47
|
+
* Get user roles and permissions from the /guard/me endpoint
|
|
48
|
+
* @param token - JWT access token
|
|
49
|
+
* @returns Promise<UserAccessResponse>
|
|
50
|
+
*/
|
|
51
|
+
getUserAccess(token: string): Promise<UserAccessResponse>;
|
|
52
|
+
/**
|
|
53
|
+
* Check if user has specific permission
|
|
54
|
+
* @param token - JWT access token
|
|
55
|
+
* @param permission - Permission to check (e.g., 'events:create')
|
|
56
|
+
* @returns Promise<boolean>
|
|
57
|
+
*/
|
|
58
|
+
hasPermission(token: string, permission: string): Promise<boolean>;
|
|
59
|
+
/**
|
|
60
|
+
* Check if user has specific role
|
|
61
|
+
* @param token - JWT access token
|
|
62
|
+
* @param role - Role to check (e.g., 'Event Manager')
|
|
63
|
+
* @returns Promise<boolean>
|
|
64
|
+
*/
|
|
65
|
+
hasRole(token: string, role: string): Promise<boolean>;
|
|
66
|
+
/**
|
|
67
|
+
* Get all permissions for a specific module
|
|
68
|
+
* @param token - JWT access token
|
|
69
|
+
* @param moduleKey - Module key (e.g., 'events')
|
|
70
|
+
* @returns Promise<string[]>
|
|
71
|
+
*/
|
|
72
|
+
getModulePermissions(token: string, moduleKey: string): Promise<string[]>;
|
|
73
|
+
/**
|
|
74
|
+
* Get user roles
|
|
75
|
+
* @param token - JWT access token
|
|
76
|
+
* @returns Promise<string[]>
|
|
77
|
+
*/
|
|
78
|
+
getUserRoles(token: string): Promise<string[]>;
|
|
79
|
+
/**
|
|
80
|
+
* Get user field offices
|
|
81
|
+
* @param token - JWT access token
|
|
82
|
+
* @returns Promise<string[]>
|
|
83
|
+
*/
|
|
84
|
+
getUserFieldOffices(token: string): Promise<string[]>;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export { type ApiResponse, ExGuardBackend, type ExGuardConfig, type ModulePermission, type User, type UserAccessResponse };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// src/exguard-backend.ts
|
|
2
|
+
import axios from "axios";
|
|
3
|
+
var ExGuardBackend = class {
|
|
4
|
+
constructor(config) {
|
|
5
|
+
this.config = {
|
|
6
|
+
timeout: 1e4,
|
|
7
|
+
...config
|
|
8
|
+
};
|
|
9
|
+
this.client = axios.create({
|
|
10
|
+
baseURL: this.config.apiUrl,
|
|
11
|
+
timeout: this.config.timeout,
|
|
12
|
+
headers: {
|
|
13
|
+
"Content-Type": "application/json"
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Get user roles and permissions from the /guard/me endpoint
|
|
19
|
+
* @param token - JWT access token
|
|
20
|
+
* @returns Promise<UserAccessResponse>
|
|
21
|
+
*/
|
|
22
|
+
async getUserAccess(token) {
|
|
23
|
+
try {
|
|
24
|
+
const response = await this.client.get("/guard/me", {
|
|
25
|
+
headers: {
|
|
26
|
+
"Authorization": `Bearer ${token}`
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
if (!response.data.success) {
|
|
30
|
+
throw new Error("Failed to fetch user access information");
|
|
31
|
+
}
|
|
32
|
+
return response.data.data;
|
|
33
|
+
} catch (error) {
|
|
34
|
+
if (axios.isAxiosError(error)) {
|
|
35
|
+
if (error.response?.status === 401) {
|
|
36
|
+
throw new Error("Unauthorized: Invalid or expired token");
|
|
37
|
+
}
|
|
38
|
+
throw new Error(`API Error: ${error.response?.data?.message || error.message}`);
|
|
39
|
+
}
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Check if user has specific permission
|
|
45
|
+
* @param token - JWT access token
|
|
46
|
+
* @param permission - Permission to check (e.g., 'events:create')
|
|
47
|
+
* @returns Promise<boolean>
|
|
48
|
+
*/
|
|
49
|
+
async hasPermission(token, permission) {
|
|
50
|
+
try {
|
|
51
|
+
const userAccess = await this.getUserAccess(token);
|
|
52
|
+
return userAccess.modules.some(
|
|
53
|
+
(module) => module.permissions.includes(permission)
|
|
54
|
+
);
|
|
55
|
+
} catch (error) {
|
|
56
|
+
return false;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Check if user has specific role
|
|
61
|
+
* @param token - JWT access token
|
|
62
|
+
* @param role - Role to check (e.g., 'Event Manager')
|
|
63
|
+
* @returns Promise<boolean>
|
|
64
|
+
*/
|
|
65
|
+
async hasRole(token, role) {
|
|
66
|
+
try {
|
|
67
|
+
const userAccess = await this.getUserAccess(token);
|
|
68
|
+
return userAccess.roles.includes(role);
|
|
69
|
+
} catch (error) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Get all permissions for a specific module
|
|
75
|
+
* @param token - JWT access token
|
|
76
|
+
* @param moduleKey - Module key (e.g., 'events')
|
|
77
|
+
* @returns Promise<string[]>
|
|
78
|
+
*/
|
|
79
|
+
async getModulePermissions(token, moduleKey) {
|
|
80
|
+
try {
|
|
81
|
+
const userAccess = await this.getUserAccess(token);
|
|
82
|
+
const module = userAccess.modules.find((m) => m.key === moduleKey);
|
|
83
|
+
return module?.permissions || [];
|
|
84
|
+
} catch (error) {
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Get user roles
|
|
90
|
+
* @param token - JWT access token
|
|
91
|
+
* @returns Promise<string[]>
|
|
92
|
+
*/
|
|
93
|
+
async getUserRoles(token) {
|
|
94
|
+
try {
|
|
95
|
+
const userAccess = await this.getUserAccess(token);
|
|
96
|
+
return userAccess.roles;
|
|
97
|
+
} catch (error) {
|
|
98
|
+
return [];
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Get user field offices
|
|
103
|
+
* @param token - JWT access token
|
|
104
|
+
* @returns Promise<string[]>
|
|
105
|
+
*/
|
|
106
|
+
async getUserFieldOffices(token) {
|
|
107
|
+
try {
|
|
108
|
+
const userAccess = await this.getUserAccess(token);
|
|
109
|
+
return userAccess.fieldOffices;
|
|
110
|
+
} catch (error) {
|
|
111
|
+
return [];
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
export {
|
|
116
|
+
ExGuardBackend
|
|
117
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "exguard-backend",
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"private": false,
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"type": "module",
|
|
9
|
+
"description": "ExGuard backend SDK for user role and permission validation",
|
|
10
|
+
"main": "./dist/index.cjs",
|
|
11
|
+
"module": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"exports": {
|
|
14
|
+
".": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.js",
|
|
17
|
+
"require": "./dist/index.cjs"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"README.md"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsup",
|
|
26
|
+
"dev": "tsup --watch",
|
|
27
|
+
"type-check": "tsc --noEmit",
|
|
28
|
+
"prepublishOnly": "pnpm build"
|
|
29
|
+
},
|
|
30
|
+
"keywords": [
|
|
31
|
+
"exguard",
|
|
32
|
+
"rbac",
|
|
33
|
+
"backend",
|
|
34
|
+
"typescript",
|
|
35
|
+
"permissions",
|
|
36
|
+
"roles"
|
|
37
|
+
],
|
|
38
|
+
"author": "EmpowerX",
|
|
39
|
+
"license": "MIT",
|
|
40
|
+
"dependencies": {
|
|
41
|
+
"axios": "^1.0.0"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/node": "^22.10.5",
|
|
45
|
+
"tsup": "^8.3.5",
|
|
46
|
+
"typescript": "^5.7.3"
|
|
47
|
+
}
|
|
48
|
+
}
|