namirasoft-account-react 1.4.413 → 1.4.414
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/SKILLS.md +514 -0
- package/dist/components/NSBoxSecret.d.ts +1 -0
- package/dist/components/NSBoxSecret.js +15 -13
- package/dist/components/NSBoxSecret.js.map +1 -1
- package/dist/components/NSBoxSecret.module.css +5 -0
- package/package.json +7 -7
- package/src/components/NSBoxSecret.module.css +5 -0
- package/src/components/NSBoxSecret.tsx +34 -29
package/SKILLS.md
ADDED
|
@@ -0,0 +1,514 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: namirasoft-account-react
|
|
3
|
+
description: Use when working with the namirasoft-account-react npm package — a React UI library providing auth flows, workspace/access/product dialogs, CRUD layouts (list/view/edit), secret field components, and an auth-gated router for Namirasoft Console frontends.
|
|
4
|
+
triggers:
|
|
5
|
+
- namirasoft-account-react
|
|
6
|
+
- NSARouterMaker
|
|
7
|
+
- NSALayout
|
|
8
|
+
- NSASectionList
|
|
9
|
+
- NSASectionEdit
|
|
10
|
+
- NSASectionView
|
|
11
|
+
- NSBoxSecret
|
|
12
|
+
- account react
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# namirasoft-account-react
|
|
16
|
+
|
|
17
|
+
**Package:** `namirasoft-account-react` v1.4.413
|
|
18
|
+
**Purpose:** Enterprise React UI library for Namirasoft products. Provides the complete authentication flow (login, verification, consent), workspace/access/product management dialogs, generic CRUD layouts (list/view/edit), secret field components, and a router framework that gates pages behind authentication state.
|
|
19
|
+
**Stack:** React 18, TypeScript, React Router 7, Bootstrap 5, CSS Modules.
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## When to use this package
|
|
24
|
+
|
|
25
|
+
Use `namirasoft-account-react` in every **frontend Console** (React SPA) that needs to:
|
|
26
|
+
- Authenticate users via the Namirasoft Account service
|
|
27
|
+
- Enforce email and phone verification before access
|
|
28
|
+
- Show a consent/terms page when policies change
|
|
29
|
+
- Provide workspace switching, access (impersonation), and product navigation
|
|
30
|
+
- Render generic entity list / view / edit pages
|
|
31
|
+
- Store and display sensitive secrets (encrypted fields)
|
|
32
|
+
- Poll and display in-app messages
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Environment Variables
|
|
37
|
+
|
|
38
|
+
Copy `.env.template` and fill in all values before running:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
REACT_APP_BASE_PATH="" # sub-path if not at root
|
|
42
|
+
REACT_APP_BASE_URL_ACCESS="https://access.namirasoft.com/api/v1"
|
|
43
|
+
REACT_APP_BASE_URL_ACCOUNT="https://account.namirasoft.com/api/v1"
|
|
44
|
+
REACT_APP_BASE_URL_ACCOUNT_CONSOLE="https://account.namirasoft.com"
|
|
45
|
+
REACT_APP_BASE_URL_API_LINK="https://namirasoft.com/api/link/v1"
|
|
46
|
+
REACT_APP_BASE_URL_API_PRODUCT="https://namirasoft.com/api/product/v1"
|
|
47
|
+
REACT_APP_BASE_URL_FIELD="https://field.namirasoft.com/api/v1"
|
|
48
|
+
REACT_APP_BASE_URL_HISTORY="https://history.namirasoft.com/api/v1"
|
|
49
|
+
REACT_APP_BASE_URL_HISTORY_CONSOLE="https://history.namirasoft.com"
|
|
50
|
+
REACT_APP_BASE_URL_MESSAGE="https://message.namirasoft.com/api/v1"
|
|
51
|
+
REACT_APP_BASE_URL_MESSAGE_CONSOLE="https://message.namirasoft.com"
|
|
52
|
+
REACT_APP_BASE_URL_SECRET="https://secret.namirasoft.com/api/v1"
|
|
53
|
+
REACT_APP_BASE_URL_WORKSPACE="https://workspace.namirasoft.com/api/v1"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Exports (`main.ts`)
|
|
59
|
+
|
|
60
|
+
### Components
|
|
61
|
+
|
|
62
|
+
| Export | File | Description |
|
|
63
|
+
|--------|------|-------------|
|
|
64
|
+
| `NSAAccessListDialog` | `components/NSAAccessListDialog.tsx` | Incoming permissions / impersonation switcher |
|
|
65
|
+
| `NSAMessageListDialog` | `components/NSAMessageListDialog.tsx` | Unread message center (max 4, mark-all-seen) |
|
|
66
|
+
| `NSAProductListDialog` | `components/NSAProductListDialog.tsx` | Searchable product list |
|
|
67
|
+
| `NSAWorkspaceListDialog` | `components/NSAWorkspaceListDialog.tsx` | Workspace switcher |
|
|
68
|
+
| `NSAUserDialog` | `components/NSAUserDialog.tsx` | User profile and settings dialog |
|
|
69
|
+
| `NSAMasterMenu` | `components/NSAMasterMenu.tsx` | Sidebar navigation with search and collapse |
|
|
70
|
+
| `NSAMasterMenuItem` | `components/NSAMasterMenuItem.tsx` | Individual menu item |
|
|
71
|
+
| `NSBoxSecret` | `components/NSBoxSecret.tsx` | Secret/encrypted value input |
|
|
72
|
+
| `NSLabelSecret` | `components/NSLabelSecret.tsx` | Secret/encrypted value display label |
|
|
73
|
+
|
|
74
|
+
### Layouts
|
|
75
|
+
|
|
76
|
+
| Export | File | Description |
|
|
77
|
+
|--------|------|-------------|
|
|
78
|
+
| `NSALayout` | `layouts/NSALayout.tsx` | Root layout: header, master menu, all dialogs, delete confirm |
|
|
79
|
+
| `NSASectionList` | `layouts/NSASectionList.tsx` | Entity table with filter/sort/select |
|
|
80
|
+
| `NSASectionEdit` | `layouts/NSASectionEdit.tsx` | Entity create/update form (tabbed) |
|
|
81
|
+
| `NSASectionView` | `layouts/NSASectionView.tsx` | Entity read-only detail view (tabbed) |
|
|
82
|
+
| `NSASectionViewTabPage` | `layouts/NSASectionViewTabPage.tsx` | Single tab inside `NSASectionView` |
|
|
83
|
+
| `NSASectionEditTabPage` | `layouts/NSASectionEditTabPage.tsx` | Single tab inside `NSASectionEdit` |
|
|
84
|
+
|
|
85
|
+
### Pages
|
|
86
|
+
|
|
87
|
+
| Export | File | Description |
|
|
88
|
+
|--------|------|-------------|
|
|
89
|
+
| `NSALoginPage` | `pages/NSALoginPage.tsx` | Login page — opens OAuth flow |
|
|
90
|
+
| `NSAConsentPage` | `pages/NSAConsentPage.tsx` | Terms/privacy acceptance |
|
|
91
|
+
| `NSAEmailVerificationPage` | `pages/NSAEmailVerificationPage.tsx` | Email verification (send + verify code) |
|
|
92
|
+
| `NSAPhoneVerificationPage` | `pages/NSAPhoneVerificationPage.tsx` | Phone verification (enter number + SMS code) |
|
|
93
|
+
| `NSAVerificationPage` | `pages/NSAVerificationPage.tsx` | Generic verification base component |
|
|
94
|
+
| `NSAHomePage` | `pages/NSAHomePage.tsx` | Product grid home page |
|
|
95
|
+
| `PaymentRequired` | `pages/PaymentRequired.tsx` | Subscription gate wrapper |
|
|
96
|
+
|
|
97
|
+
### Formatters
|
|
98
|
+
|
|
99
|
+
| Export | File | Description |
|
|
100
|
+
|--------|------|-------------|
|
|
101
|
+
| `SecretFormatter` | `formatters/SecretFormatter.tsx` | Table cell formatter for encrypted secret values |
|
|
102
|
+
|
|
103
|
+
### Router & Config
|
|
104
|
+
|
|
105
|
+
| Export | File | Description |
|
|
106
|
+
|--------|------|-------------|
|
|
107
|
+
| `NSARouterMaker` | `NSARouterMaker.tsx` | Auth-aware router — gates pages by login/verification state |
|
|
108
|
+
| `NSARouterMakerProps` | `NSARouterMakerProps.ts` | Props injected into routed components |
|
|
109
|
+
| `NSARouterMakerConfig` | `NSARouterMakerConfig.ts` | Config callbacks for `NSARouterMaker` |
|
|
110
|
+
|
|
111
|
+
### Utilities
|
|
112
|
+
|
|
113
|
+
| Export | File | Description |
|
|
114
|
+
|--------|------|-------------|
|
|
115
|
+
| `IEntityInfo` | `IEntityInfo.ts` | Entity definition interface for CRUD pages |
|
|
116
|
+
| `Actions` | `layouts/Actions.ts` | Menu action builder (new, view, edit, delete, …) |
|
|
117
|
+
| `CFTUtil` | `layouts/CFTUtil.ts` | Custom Table Fields get/set helpers |
|
|
118
|
+
| `UseParams` | `UseParams.tsx` | Hook wrapper for URL params |
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Key Types & Interfaces
|
|
123
|
+
|
|
124
|
+
### `NSARouterMakerConfig`
|
|
125
|
+
|
|
126
|
+
Callbacks that configure the router's rendering behaviour:
|
|
127
|
+
|
|
128
|
+
```typescript
|
|
129
|
+
interface NSARouterMakerConfig {
|
|
130
|
+
// Called when user is authenticated and all verifications pass
|
|
131
|
+
onRenderOnLogin(props: NSARouterMakerProps): ReactNode;
|
|
132
|
+
|
|
133
|
+
// Called when user is not authenticated (banned = account suspended)
|
|
134
|
+
onRenderOnLogout(props: NSARouterMakerProps, banned: boolean): ReactNode;
|
|
135
|
+
|
|
136
|
+
// Wraps any page in NSALayout (called for all authenticated renders)
|
|
137
|
+
renderOnNSALayout(props: NSARouterMakerProps, children: ReactNode): ReactNode;
|
|
138
|
+
|
|
139
|
+
// Optional: custom render override
|
|
140
|
+
getCustomRender?(props: NSARouterMakerProps): ReactNode | null;
|
|
141
|
+
|
|
142
|
+
// Which verifications are required before granting access
|
|
143
|
+
requirement: {
|
|
144
|
+
verification: {
|
|
145
|
+
email: boolean;
|
|
146
|
+
phone: boolean;
|
|
147
|
+
};
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### `NSARouterMakerProps`
|
|
153
|
+
|
|
154
|
+
Injected into every routed component. Extends `NSRouterMakerProps` from `namirasoft-site-react`.
|
|
155
|
+
|
|
156
|
+
```typescript
|
|
157
|
+
interface NSARouterMakerProps {
|
|
158
|
+
product_id: string;
|
|
159
|
+
account: {
|
|
160
|
+
token_manager: TokenManager;
|
|
161
|
+
server: NamirasoftAccountServer;
|
|
162
|
+
};
|
|
163
|
+
url: {
|
|
164
|
+
getQueryStrings(): Record<string, string>;
|
|
165
|
+
getQuery(key: string): string | null;
|
|
166
|
+
getLink(path: string): string;
|
|
167
|
+
redirect(path: string): void;
|
|
168
|
+
};
|
|
169
|
+
renderer: {
|
|
170
|
+
renderOnNSALayout(children: ReactNode): ReactNode;
|
|
171
|
+
};
|
|
172
|
+
// ... inherited from NSRouterMakerProps
|
|
173
|
+
}
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### `IEntityInfo<EntityType, EntityTypeInput>`
|
|
177
|
+
|
|
178
|
+
Defines everything needed to build a list/view/edit page for an entity:
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
interface IEntityInfo<EntityType, EntityTypeInput> {
|
|
182
|
+
product_id: string;
|
|
183
|
+
name: string;
|
|
184
|
+
tables: { table: BaseMetaTable; required: boolean }[];
|
|
185
|
+
|
|
186
|
+
server: {
|
|
187
|
+
value_list(column: string, table: string, ...): Promise<string[]>;
|
|
188
|
+
get(id: string): Promise<EntityType>;
|
|
189
|
+
list(query: any): Promise<EntityType[]>;
|
|
190
|
+
create(input: EntityTypeInput): Promise<EntityType>;
|
|
191
|
+
update(id: string, input: EntityTypeInput): Promise<EntityType>;
|
|
192
|
+
delete(id: string): Promise<EntityType>;
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
client: {
|
|
196
|
+
getListURL(): string;
|
|
197
|
+
getNewURL(): string;
|
|
198
|
+
getCopyURL(row: EntityType): string;
|
|
199
|
+
getEditURL(row: EntityType): string;
|
|
200
|
+
getViewURL(row: EntityType): string;
|
|
201
|
+
getColumns(): ColumnDefinition[];
|
|
202
|
+
onCreate?(row: EntityType): void;
|
|
203
|
+
onUpdate?(row: EntityType): void;
|
|
204
|
+
onSuccess?(row: EntityType): void;
|
|
205
|
+
getMenus?(row: EntityType): MenuItem[];
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### `CTFRow`
|
|
211
|
+
|
|
212
|
+
Custom Table Fields structure attached to entities that support dynamic field definitions:
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
interface CTFRow {
|
|
216
|
+
categories: EntityCategoryInputRow[];
|
|
217
|
+
fields: EntityFieldInputRow[];
|
|
218
|
+
tags: EntityTagInputRow[];
|
|
219
|
+
}
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
---
|
|
223
|
+
|
|
224
|
+
## Router Authentication Flow
|
|
225
|
+
|
|
226
|
+
`NSARouterMaker` automatically routes the user through these states in order:
|
|
227
|
+
|
|
228
|
+
1. **Not authenticated** → renders `NSALoginPage` (opens OAuth popup via `NamirasoftAccountClient`)
|
|
229
|
+
2. **Banned** → renders error; `onRenderOnLogout(props, true)` is called
|
|
230
|
+
3. **Consent outdated** → renders `NSAConsentPage`
|
|
231
|
+
4. **Email not verified** (if `requirement.verification.email`) → renders `NSAEmailVerificationPage`
|
|
232
|
+
5. **Phone not verified** (if `requirement.verification.phone`) → renders `NSAPhoneVerificationPage`
|
|
233
|
+
6. **All checks pass** → calls `onRenderOnLogin(props)`
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Components — Details
|
|
238
|
+
|
|
239
|
+
### `NSALayout`
|
|
240
|
+
|
|
241
|
+
Root layout for all authenticated pages. Wraps content and mounts:
|
|
242
|
+
- Top header with icon buttons for messages, access, workspaces, products, and user
|
|
243
|
+
- `NSAMasterMenu` sidebar
|
|
244
|
+
- `NSAAccessListDialog`, `NSAMessageListDialog`, `NSAProductListDialog`, `NSAWorkspaceListDialog`, `NSAUserDialog`
|
|
245
|
+
- Delete confirmation dialog
|
|
246
|
+
- Message count polling
|
|
247
|
+
|
|
248
|
+
Props include the full `NSARouterMakerProps` plus section state managers for list/edit/view.
|
|
249
|
+
|
|
250
|
+
### `NSASectionList`
|
|
251
|
+
|
|
252
|
+
Table-based listing with:
|
|
253
|
+
- Server-driven column schema
|
|
254
|
+
- Client-side column override (custom renderers, formatters)
|
|
255
|
+
- Multi-select checkboxes
|
|
256
|
+
- Filter/sort query params
|
|
257
|
+
- Action menus per row
|
|
258
|
+
- Custom mode rendering (e.g. search-and-select mode)
|
|
259
|
+
|
|
260
|
+
### `NSASectionEdit`
|
|
261
|
+
|
|
262
|
+
Form for create and update:
|
|
263
|
+
- Tab-based field groups (`NSASectionEditTabPage` per tab)
|
|
264
|
+
- Validation from server schema
|
|
265
|
+
- Handles create vs update automatically
|
|
266
|
+
|
|
267
|
+
### `NSASectionView`
|
|
268
|
+
|
|
269
|
+
Read-only detail page:
|
|
270
|
+
- Tab-based layout (`NSASectionViewTabPage` per tab)
|
|
271
|
+
- `NSASectionViewTabMore` for overflow tabs
|
|
272
|
+
- Optional hooks before/after render
|
|
273
|
+
|
|
274
|
+
### `NSBoxSecret`
|
|
275
|
+
|
|
276
|
+
Encrypted input for passwords, API keys, or tokens:
|
|
277
|
+
- Toggle between masked and plain text
|
|
278
|
+
- Save value to Secret service (returns an ID)
|
|
279
|
+
- Reference existing secret by ID
|
|
280
|
+
- Handles encryption/decryption automatically
|
|
281
|
+
|
|
282
|
+
### `NSLabelSecret`
|
|
283
|
+
|
|
284
|
+
Display label for encrypted secrets:
|
|
285
|
+
- Shows masked value by default
|
|
286
|
+
- Decrypts and reveals on toggle
|
|
287
|
+
- Reads from Secret service by ID
|
|
288
|
+
|
|
289
|
+
### `NSAMasterMenu`
|
|
290
|
+
|
|
291
|
+
Sidebar navigation:
|
|
292
|
+
- Hierarchical menu items from `namirasoft-api-link`
|
|
293
|
+
- Debounced search filter
|
|
294
|
+
- Collapse/expand toggle (state persisted in `NSACacheService`)
|
|
295
|
+
|
|
296
|
+
### `NSAMessageListDialog`
|
|
297
|
+
|
|
298
|
+
- Fetches up to 4 unread messages
|
|
299
|
+
- Mark all as seen button
|
|
300
|
+
- Opens full message in new window
|
|
301
|
+
- Integrates with message count badge in header
|
|
302
|
+
|
|
303
|
+
### `NSAAccessListDialog`
|
|
304
|
+
|
|
305
|
+
- Lists incoming permissions (accounts that can act as the user)
|
|
306
|
+
- Switch to an impersonated account
|
|
307
|
+
- Shows who is currently being impersonated
|
|
308
|
+
|
|
309
|
+
### `NSAWorkspaceListDialog`
|
|
310
|
+
|
|
311
|
+
- Lists all workspaces for the current product
|
|
312
|
+
- Highlights default and current workspace
|
|
313
|
+
- Switching workspace triggers page reload
|
|
314
|
+
|
|
315
|
+
### `PaymentRequired`
|
|
316
|
+
|
|
317
|
+
Wraps content and checks subscription status. If not subscribed:
|
|
318
|
+
- Shows payment offer
|
|
319
|
+
- Opens payment URL with return callback
|
|
320
|
+
- Blocks child content until subscription confirmed
|
|
321
|
+
|
|
322
|
+
### `SecretFormatter`
|
|
323
|
+
|
|
324
|
+
A table column formatter factory:
|
|
325
|
+
|
|
326
|
+
```typescript
|
|
327
|
+
SecretFormatter(width?: number): ColumnFormatter
|
|
328
|
+
// Returns a formatter that decrypts and masks secret cell values.
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## Utilities
|
|
334
|
+
|
|
335
|
+
### `Actions` — static menu item builders
|
|
336
|
+
|
|
337
|
+
```typescript
|
|
338
|
+
Actions.apply(onClick: () => void): MenuItem // Apply button
|
|
339
|
+
Actions._new(): MenuItem // "New" — navigate to create page
|
|
340
|
+
Actions.list(): MenuItem // "List" — navigate to list page
|
|
341
|
+
Actions.view(): MenuItem // "View" — view selected entity
|
|
342
|
+
Actions.viewHistory(): MenuItem // "History" — view entity history
|
|
343
|
+
Actions.copy(): MenuItem // "Copy" — copy selected entity
|
|
344
|
+
Actions.edit(): MenuItem // "Edit" — edit selected entity
|
|
345
|
+
Actions.delete(): MenuItem // "Delete" — trigger delete confirm dialog
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### `CFTUtil` — custom field helpers
|
|
349
|
+
|
|
350
|
+
```typescript
|
|
351
|
+
CFTUtil.get(name: string, row: any): CTFRow
|
|
352
|
+
// Extract CTF data from an entity row.
|
|
353
|
+
|
|
354
|
+
CFTUtil.set(name: string, row: any, ctf: CTFRow): void
|
|
355
|
+
// Store CTF data back into a row.
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### `NSACacheService` — cached API calls
|
|
359
|
+
|
|
360
|
+
All caches use `namirasoft-core` storage. These are called internally by components but can be used directly:
|
|
361
|
+
|
|
362
|
+
```typescript
|
|
363
|
+
NSACacheService.getProducts(server, current_product_id)
|
|
364
|
+
// Cache: 7 days. Fetches all products, excludes current.
|
|
365
|
+
|
|
366
|
+
NSACacheService.getConsent(server, product_id, user_id)
|
|
367
|
+
// Cache: 7 days. Fetches user consent for a product.
|
|
368
|
+
|
|
369
|
+
NSACacheService.getFilterLinks(server, product_id, search?)
|
|
370
|
+
// Cache: 7 days. Fetches navigation links for sidebar.
|
|
371
|
+
|
|
372
|
+
NSACacheService.getMasterMenuStatus()
|
|
373
|
+
// Cache: 30 days. Persists sidebar open/closed state.
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
---
|
|
377
|
+
|
|
378
|
+
## Usage Pattern — Setting up a Console
|
|
379
|
+
|
|
380
|
+
### 1 — Configure the router
|
|
381
|
+
|
|
382
|
+
```tsx
|
|
383
|
+
// src/index.tsx
|
|
384
|
+
import { BrowserRouter } from 'react-router-dom';
|
|
385
|
+
import { NSARouterMaker, NSARouterMakerConfig } from 'namirasoft-account-react';
|
|
386
|
+
|
|
387
|
+
const config: NSARouterMakerConfig = {
|
|
388
|
+
requirement: { verification: { email: true, phone: false } },
|
|
389
|
+
onRenderOnLogout: (props, banned) => <div>Please log in</div>,
|
|
390
|
+
renderOnNSALayout: (props, children) => (
|
|
391
|
+
<NSALayout {...props}>{children}</NSALayout>
|
|
392
|
+
),
|
|
393
|
+
onRenderOnLogin: (props) => <MyAppRoutes {...props} />,
|
|
394
|
+
};
|
|
395
|
+
|
|
396
|
+
const router = new NSARouterMaker('my-product-id', config);
|
|
397
|
+
|
|
398
|
+
ReactDOM.createRoot(document.getElementById('root')!).render(
|
|
399
|
+
<BrowserRouter>
|
|
400
|
+
<router.Component />
|
|
401
|
+
</BrowserRouter>
|
|
402
|
+
);
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
### 2 — Define an entity
|
|
406
|
+
|
|
407
|
+
```typescript
|
|
408
|
+
import { IEntityInfo } from 'namirasoft-account-react';
|
|
409
|
+
|
|
410
|
+
const ProjectEntity: IEntityInfo<ProjectRow, ProjectInputRow> = {
|
|
411
|
+
product_id: 'my-product-id',
|
|
412
|
+
name: 'Project',
|
|
413
|
+
tables: [{ table: ProjectTable, required: true }],
|
|
414
|
+
server: {
|
|
415
|
+
get: (id) => projectServer.get(id),
|
|
416
|
+
list: (query) => projectServer.list(query),
|
|
417
|
+
create: (input) => projectServer.create(input),
|
|
418
|
+
update: (id, input) => projectServer.update(id, input),
|
|
419
|
+
delete: (id) => projectServer.delete(id),
|
|
420
|
+
value_list: (col, table, ...) => projectServer.valueList(col, table),
|
|
421
|
+
},
|
|
422
|
+
client: {
|
|
423
|
+
getListURL: () => '/projects',
|
|
424
|
+
getNewURL: () => '/projects/new',
|
|
425
|
+
getEditURL: (row) => `/projects/${row.id}/edit`,
|
|
426
|
+
getViewURL: (row) => `/projects/${row.id}`,
|
|
427
|
+
getCopyURL: (row) => `/projects/${row.id}/copy`,
|
|
428
|
+
getColumns: () => [ /* column definitions */ ],
|
|
429
|
+
},
|
|
430
|
+
};
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### 3 — Use layout sections
|
|
434
|
+
|
|
435
|
+
```tsx
|
|
436
|
+
// List page
|
|
437
|
+
<NSASectionList entity={ProjectEntity} props={routerProps} />
|
|
438
|
+
|
|
439
|
+
// Edit page
|
|
440
|
+
<NSASectionEdit entity={ProjectEntity} props={routerProps} id={params.id} />
|
|
441
|
+
|
|
442
|
+
// View page
|
|
443
|
+
<NSASectionView entity={ProjectEntity} props={routerProps} id={params.id} />
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### 4 — Use secret fields
|
|
447
|
+
|
|
448
|
+
```tsx
|
|
449
|
+
// In a form
|
|
450
|
+
<NSBoxSecret
|
|
451
|
+
label="API Key"
|
|
452
|
+
value={form.api_key}
|
|
453
|
+
onChange={(val) => setForm({ ...form, api_key: val })}
|
|
454
|
+
server={secretServer}
|
|
455
|
+
/>
|
|
456
|
+
|
|
457
|
+
// In a detail view
|
|
458
|
+
<NSLabelSecret value={row.api_key} server={secretServer} />
|
|
459
|
+
|
|
460
|
+
// In a table column
|
|
461
|
+
columns.push({
|
|
462
|
+
field: 'api_key',
|
|
463
|
+
formatter: SecretFormatter(200),
|
|
464
|
+
});
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
### 5 — Subscription gate
|
|
468
|
+
|
|
469
|
+
```tsx
|
|
470
|
+
<PaymentRequired product_id="my-product-id" props={routerProps}>
|
|
471
|
+
<PremiumFeatureComponent />
|
|
472
|
+
</PaymentRequired>
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
---
|
|
476
|
+
|
|
477
|
+
## Source Files
|
|
478
|
+
|
|
479
|
+
| File | Responsibility |
|
|
480
|
+
|------|---------------|
|
|
481
|
+
| `src/main.ts` | All public exports |
|
|
482
|
+
| `src/NSARouterMaker.tsx` | Auth-state router |
|
|
483
|
+
| `src/NSARouterMakerConfig.ts` | Router config interface |
|
|
484
|
+
| `src/NSARouterMakerProps.ts` | Injected props interface |
|
|
485
|
+
| `src/IEntityInfo.ts` | Entity definition interface |
|
|
486
|
+
| `src/NSACacheService.ts` | Cached API calls |
|
|
487
|
+
| `src/CTFRow.ts` | CTF data structure |
|
|
488
|
+
| `src/UseParams.tsx` | URL params hook wrapper |
|
|
489
|
+
| `src/components/NSALayout.tsx` | Root layout |
|
|
490
|
+
| `src/components/NSAMasterMenu.tsx` | Sidebar navigation |
|
|
491
|
+
| `src/components/NSAAccessListDialog.tsx` | Access/impersonation dialog |
|
|
492
|
+
| `src/components/NSAMessageListDialog.tsx` | Message center dialog |
|
|
493
|
+
| `src/components/NSAProductListDialog.tsx` | Product picker dialog |
|
|
494
|
+
| `src/components/NSAWorkspaceListDialog.tsx` | Workspace switcher dialog |
|
|
495
|
+
| `src/components/NSAUserDialog.tsx` | User profile dialog |
|
|
496
|
+
| `src/components/NSBoxSecret.tsx` | Secret input |
|
|
497
|
+
| `src/components/NSLabelSecret.tsx` | Secret display label |
|
|
498
|
+
| `src/layouts/NSALayout.tsx` | Layout with all dialogs |
|
|
499
|
+
| `src/layouts/NSASectionList.tsx` | Entity list section |
|
|
500
|
+
| `src/layouts/NSASectionEdit.tsx` | Entity edit section |
|
|
501
|
+
| `src/layouts/NSASectionView.tsx` | Entity view section |
|
|
502
|
+
| `src/layouts/NSASectionViewTabPage.tsx` | View tab |
|
|
503
|
+
| `src/layouts/NSASectionEditTabPage.tsx` | Edit tab |
|
|
504
|
+
| `src/layouts/Actions.ts` | Menu action builders |
|
|
505
|
+
| `src/layouts/CFTUtil.ts` | CTF get/set helpers |
|
|
506
|
+
| `src/formatters/SecretFormatter.tsx` | Table column secret formatter |
|
|
507
|
+
| `src/pages/NSALoginPage.tsx` | Login page |
|
|
508
|
+
| `src/pages/NSAConsentPage.tsx` | Consent page |
|
|
509
|
+
| `src/pages/NSAEmailVerificationPage.tsx` | Email verification |
|
|
510
|
+
| `src/pages/NSAPhoneVerificationPage.tsx` | Phone verification |
|
|
511
|
+
| `src/pages/NSAVerificationPage.tsx` | Verification base |
|
|
512
|
+
| `src/pages/NSAHomePage.tsx` | Home/product grid |
|
|
513
|
+
| `src/pages/PaymentRequired.tsx` | Payment gate |
|
|
514
|
+
| `.env.template` | Required environment variables |
|
|
@@ -14,6 +14,7 @@ interface NSBoxSecretState {
|
|
|
14
14
|
secret_id: string | null;
|
|
15
15
|
value: string | null;
|
|
16
16
|
is_sensitive: boolean;
|
|
17
|
+
is_loading: boolean;
|
|
17
18
|
}
|
|
18
19
|
export declare class NSBoxSecret extends React.Component<NSBoxSecretProps, NSBoxSecretState> implements INSBox {
|
|
19
20
|
private NSBoxSensitive_Main;
|
|
@@ -23,6 +23,7 @@ export class NSBoxSecret extends React.Component {
|
|
|
23
23
|
secret_id: null,
|
|
24
24
|
value: null,
|
|
25
25
|
is_sensitive: true,
|
|
26
|
+
is_loading: false,
|
|
26
27
|
};
|
|
27
28
|
this.isEmpty = this.isEmpty.bind(this);
|
|
28
29
|
this.getError = this.getError.bind(this);
|
|
@@ -57,14 +58,12 @@ export class NSBoxSecret extends React.Component {
|
|
|
57
58
|
}
|
|
58
59
|
handleSensitiveChange(enabled) {
|
|
59
60
|
return __awaiter(this, void 0, void 0, function* () {
|
|
60
|
-
if (!enabled) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
61
|
+
if (!enabled && this.state.secret_id && !this.state.value) {
|
|
62
|
+
this.setState({ is_loading: true });
|
|
63
|
+
const value = yield this.getSecretValue();
|
|
64
|
+
this.setState(() => ({ value, secret_id: null, is_loading: false, is_sensitive: false }), () => { var _a; return (_a = this.NSBoxString_Main.current) === null || _a === void 0 ? void 0 : _a.setValue(value); });
|
|
65
|
+
return;
|
|
65
66
|
}
|
|
66
|
-
else if (this.state.value)
|
|
67
|
-
this.setState({ secret_id: null });
|
|
68
67
|
this.setState({ is_sensitive: enabled });
|
|
69
68
|
});
|
|
70
69
|
}
|
|
@@ -163,14 +162,16 @@ export class NSBoxSecret extends React.Component {
|
|
|
163
162
|
}
|
|
164
163
|
let secret_enabled = this.state.secret_id && !this.state.value;
|
|
165
164
|
let menu = safeMenuMenuItem(this.props, (items) => {
|
|
166
|
-
if (secret_enabled)
|
|
165
|
+
if (secret_enabled && !this.state.is_loading)
|
|
167
166
|
if (this.isSensitive())
|
|
168
167
|
items.push({
|
|
169
168
|
title: "Load From Secret",
|
|
170
169
|
icon: "https://static.namirasoft.com/image/namirasoft/secret/logo/base.png",
|
|
171
170
|
onClick: () => __awaiter(this, void 0, void 0, function* () {
|
|
172
171
|
var _a;
|
|
172
|
+
this.setState({ is_loading: true });
|
|
173
173
|
let res = yield this.getSecretValue();
|
|
174
|
+
this.setState({ is_loading: false });
|
|
174
175
|
if (res)
|
|
175
176
|
(_a = this.NSBoxSensitive_Main.current) === null || _a === void 0 ? void 0 : _a.setValue(res);
|
|
176
177
|
})
|
|
@@ -182,11 +183,12 @@ export class NSBoxSecret extends React.Component {
|
|
|
182
183
|
enabled: !secret_enabled
|
|
183
184
|
} }) }) }))
|
|
184
185
|
:
|
|
185
|
-
_jsx(NSBoxString, Object.assign({}, this.props, { ref: this.NSBoxString_Main, defaultValue: (_b = this.state.value) !== null && _b !== void 0 ? _b : "", onChanged: this.onChanged })), this.
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
186
|
+
_jsx(NSBoxString, Object.assign({}, this.props, { ref: this.NSBoxString_Main, defaultValue: (_b = this.state.value) !== null && _b !== void 0 ? _b : "", onChanged: this.onChanged })), _jsxs("div", { className: "d-flex gap-2", children: [this.state.is_loading &&
|
|
187
|
+
_jsx("div", { className: "spinner-border spinner-border-sm text-primary" }), this.props.sensitive_enabled &&
|
|
188
|
+
_jsx(NSBoxBoolean, { ref: this.NSBoxBoolean_Sensitive, title: "Sensitive", required: false, hideHeader: true, onChanged: (box) => __awaiter(this, void 0, void 0, function* () {
|
|
189
|
+
var _a;
|
|
190
|
+
yield this.handleSensitiveChange((_a = box.getValue()) !== null && _a !== void 0 ? _a : false);
|
|
191
|
+
}), classList: [Styles.ns_checkbox, this.state.is_loading ? Styles.disabled : ""] })] })] }));
|
|
190
192
|
}
|
|
191
193
|
}
|
|
192
194
|
//# sourceMappingURL=NSBoxSecret.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NSBoxSecret.js","sourceRoot":"","sources":["../../src/components/NSBoxSecret.tsx"],"names":[],"mappings":";;;;;;;;;;AAAA,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,4BAA4B,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAC;AACzF,OAAO,EAAgG,YAAY,EAAE,cAAc,EAAE,WAAW,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC5M,OAAO,KAAK,EAAE,EAAE,SAAS,EAAkC,MAAM,OAAO,CAAC;AAEzE,OAAO,MAAM,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"NSBoxSecret.js","sourceRoot":"","sources":["../../src/components/NSBoxSecret.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"framework": "npm",
|
|
9
9
|
"application": "package",
|
|
10
10
|
"private": false,
|
|
11
|
-
"version": "1.4.
|
|
11
|
+
"version": "1.4.414",
|
|
12
12
|
"author": "Amir Abolhasani",
|
|
13
13
|
"license": "MIT",
|
|
14
14
|
"main": "./dist/main.js",
|
|
@@ -22,24 +22,24 @@
|
|
|
22
22
|
},
|
|
23
23
|
"dependencies": {
|
|
24
24
|
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
|
25
|
-
"@babel/plugin-transform-private-property-in-object": "^7.
|
|
25
|
+
"@babel/plugin-transform-private-property-in-object": "^7.29.7",
|
|
26
26
|
"@types/react": "^18.3.13",
|
|
27
27
|
"@types/react-helmet": "^6.1.11",
|
|
28
28
|
"bootstrap": "^5.3.8",
|
|
29
29
|
"namirasoft-access": "^1.4.75",
|
|
30
|
-
"namirasoft-account": "^1.4.
|
|
30
|
+
"namirasoft-account": "^1.4.108",
|
|
31
31
|
"namirasoft-account-client": "^1.4.9",
|
|
32
32
|
"namirasoft-api-link": "^1.4.22",
|
|
33
33
|
"namirasoft-api-product": "^1.4.52",
|
|
34
34
|
"namirasoft-core": "^1.4.114",
|
|
35
35
|
"namirasoft-field": "^1.4.29",
|
|
36
36
|
"namirasoft-history": "^1.4.18",
|
|
37
|
-
"namirasoft-message": "^1.4.
|
|
37
|
+
"namirasoft-message": "^1.4.25",
|
|
38
38
|
"namirasoft-payment": "^1.4.137",
|
|
39
39
|
"namirasoft-schema": "^1.4.29",
|
|
40
|
-
"namirasoft-secret": "^1.4.
|
|
40
|
+
"namirasoft-secret": "^1.4.46",
|
|
41
41
|
"namirasoft-site-map": "^1.4.46",
|
|
42
|
-
"namirasoft-site-react": "^1.4.
|
|
42
|
+
"namirasoft-site-react": "^1.4.530",
|
|
43
43
|
"namirasoft-workspace": "^1.4.28",
|
|
44
44
|
"os-browserify": "^0.3.0",
|
|
45
45
|
"path-browserify": "^1.0.1",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"react-helmet": "^6.1.0",
|
|
52
52
|
"react-router-dom": "7.9.1",
|
|
53
53
|
"react-scripts": "5.0.1",
|
|
54
|
-
"webpack": "^5.
|
|
54
|
+
"webpack": "^5.107.2"
|
|
55
55
|
},
|
|
56
56
|
"eslintConfig": {
|
|
57
57
|
"extends": [
|
|
@@ -14,11 +14,12 @@ export interface NSBoxSecretProps extends IBaseComponentProps, IValidationProps,
|
|
|
14
14
|
decryptor: (value: string) => Promise<string>;
|
|
15
15
|
}
|
|
16
16
|
}
|
|
17
|
-
interface NSBoxSecretState
|
|
17
|
+
interface NSBoxSecretState
|
|
18
18
|
{
|
|
19
19
|
secret_id: string | null;
|
|
20
20
|
value: string | null;
|
|
21
21
|
is_sensitive: boolean;
|
|
22
|
+
is_loading: boolean;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
export class NSBoxSecret extends React.Component<NSBoxSecretProps, NSBoxSecretState> implements INSBox
|
|
@@ -34,6 +35,7 @@ export class NSBoxSecret extends React.Component<NSBoxSecretProps, NSBoxSecretSt
|
|
|
34
35
|
secret_id: null,
|
|
35
36
|
value: null,
|
|
36
37
|
is_sensitive: true,
|
|
38
|
+
is_loading: false,
|
|
37
39
|
};
|
|
38
40
|
this.isEmpty = this.isEmpty.bind(this);
|
|
39
41
|
this.getError = this.getError.bind(this);
|
|
@@ -67,21 +69,16 @@ export class NSBoxSecret extends React.Component<NSBoxSecretProps, NSBoxSecretSt
|
|
|
67
69
|
}
|
|
68
70
|
private async handleSensitiveChange(enabled: boolean)
|
|
69
71
|
{
|
|
70
|
-
if (!enabled)
|
|
72
|
+
if (!enabled && this.state.secret_id && !this.state.value)
|
|
71
73
|
{
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
74
|
+
this.setState({ is_loading: true });
|
|
75
|
+
const value = await this.getSecretValue();
|
|
76
|
+
this.setState(
|
|
77
|
+
() => ({ value, secret_id: null, is_loading: false, is_sensitive: false }),
|
|
78
|
+
() => this.NSBoxString_Main.current?.setValue(value)
|
|
79
|
+
);
|
|
80
|
+
return;
|
|
80
81
|
}
|
|
81
|
-
else
|
|
82
|
-
if (this.state.value)
|
|
83
|
-
this.setState({ secret_id: null });
|
|
84
|
-
|
|
85
82
|
this.setState({ is_sensitive: enabled });
|
|
86
83
|
}
|
|
87
84
|
getValue(checkError: boolean = true): string | null
|
|
@@ -189,14 +186,16 @@ export class NSBoxSecret extends React.Component<NSBoxSecretProps, NSBoxSecretSt
|
|
|
189
186
|
let secret_enabled = this.state.secret_id && !this.state.value;
|
|
190
187
|
let menu = safeMenuMenuItem(this.props, (items) =>
|
|
191
188
|
{
|
|
192
|
-
if (secret_enabled)
|
|
189
|
+
if (secret_enabled && !this.state.is_loading)
|
|
193
190
|
if (this.isSensitive())
|
|
194
191
|
items.push({
|
|
195
192
|
title: "Load From Secret",
|
|
196
193
|
icon: "https://static.namirasoft.com/image/namirasoft/secret/logo/base.png",
|
|
197
194
|
onClick: async () =>
|
|
198
195
|
{
|
|
196
|
+
this.setState({ is_loading: true });
|
|
199
197
|
let res = await this.getSecretValue();
|
|
198
|
+
this.setState({ is_loading: false });
|
|
200
199
|
if (res)
|
|
201
200
|
this.NSBoxSensitive_Main.current?.setValue(res);
|
|
202
201
|
}
|
|
@@ -234,20 +233,26 @@ export class NSBoxSecret extends React.Component<NSBoxSecretProps, NSBoxSecretSt
|
|
|
234
233
|
onChanged={this.onChanged}
|
|
235
234
|
/>
|
|
236
235
|
}
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
236
|
+
<div className="d-flex gap-2">
|
|
237
|
+
{
|
|
238
|
+
this.state.is_loading &&
|
|
239
|
+
<div className="spinner-border spinner-border-sm text-primary"></div>
|
|
240
|
+
}
|
|
241
|
+
{
|
|
242
|
+
this.props.sensitive_enabled &&
|
|
243
|
+
<NSBoxBoolean
|
|
244
|
+
ref={this.NSBoxBoolean_Sensitive}
|
|
245
|
+
title="Sensitive"
|
|
246
|
+
required={false}
|
|
247
|
+
hideHeader
|
|
248
|
+
onChanged={async (box) =>
|
|
249
|
+
{
|
|
250
|
+
await this.handleSensitiveChange(box.getValue() ?? false);
|
|
251
|
+
}}
|
|
252
|
+
classList={[Styles.ns_checkbox, this.state.is_loading ? Styles.disabled : ""]}
|
|
253
|
+
/>
|
|
254
|
+
}
|
|
255
|
+
</div>
|
|
251
256
|
</NSColumn>
|
|
252
257
|
);
|
|
253
258
|
}
|