@fui-org/fui-cli 1.3.2 → 2.0.0
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 +19 -3
- package/dist/fui-bmg5pnmq.js +379 -0
- package/dist/fui.js +1 -1
- package/package.json +3 -6
- package/skills/fui/SKILL.md +9 -41
- package/skills/fui-skill/SKILL.md +95 -225
- package/skills/fui-skill/assets/projectdefaultstyle-3.0.css +555 -0
- package/skills/fui-skill/assets/projectdefaultstyle.css +207 -235
- package/skills/fui-skill/references/INDEX.md +105 -137
- package/skills/fui-skill/references/advanced-techniques.md +76 -68
- package/skills/fui-skill/references/coding-standards.md +56 -56
- package/skills/fui-skill/references/component-design.md +166 -173
- package/skills/fui-skill/references/component-quickref.md +61 -60
- package/skills/fui-skill/references/component-table.md +128 -117
- package/skills/fui-skill/references/components-dialog.md +55 -56
- package/skills/fui-skill/references/components-display.md +24 -30
- package/skills/fui-skill/references/components-echart.md +186 -261
- package/skills/fui-skill/references/components-input.md +72 -96
- package/skills/fui-skill/references/controls-patterns.md +196 -342
- package/skills/fui-skill/references/controls-styling-vocabulary.md +130 -97
- package/skills/fui-skill/references/db-table-design.md +24 -28
- package/skills/fui-skill/references/db-workflow.md +191 -390
- package/skills/fui-skill/references/default-function.md +169 -128
- package/skills/fui-skill/references/design-modes.md +35 -63
- package/skills/fui-skill/references/echart-templates.md +204 -196
- package/skills/fui-skill/references/fastproject.md +62 -60
- package/skills/fui-skill/references/fsheet.md +109 -124
- package/skills/fui-skill/references/fullstack-workflow.md +90 -128
- package/skills/fui-skill/references/module-data-patterns.md +31 -40
- package/skills/fui-skill/references/module-json-anatomy.md +47 -52
- package/skills/fui-skill/references/module-structure.md +80 -196
- package/skills/fui-skill/references/new-session.md +49 -51
- package/skills/fui-skill/references/pdfmake.md +17 -17
- package/skills/fui-skill/references/permission-system.md +89 -108
- package/skills/fui-skill/references/platform-architecture.md +128 -153
- package/skills/fui-skill/references/project-config.md +102 -134
- package/skills/fui-skill/references/project-provisioning.md +139 -244
- package/skills/fui-skill/references/script-map.md +208 -242
- package/skills/fui-skill/references/sql-clr-functions.md +98 -97
- package/skills/fui-skill/references/system-design.md +63 -88
- package/skills/fui-skill/references/tapi-file-api.md +46 -52
- package/skills/fui-skill/references/tapi-permission-patterns.md +51 -53
- package/skills/fui-skill/references/tapi-reference.md +132 -207
- package/skills/fui-skill/references/tools-registry.md +84 -460
- package/skills/fui-skill/references/ui-crosswindow-patterns.md +79 -75
- package/skills/fui-skill/references/ui-dialog-patterns.md +98 -72
- package/skills/fui-skill/references/ui-layout-patterns.md +26 -26
- package/skills/fui-skill/references/ui-patterns.md +71 -83
- package/skills/fui-skill/references/ui-screenshot-review.md +63 -62
- package/skills/fui-skill/references/ui-table-cell-patterns.md +61 -59
- package/skills/fui-skill/references/ui-templates.md +16 -23
- package/skills/fui-skill/references/verification.md +236 -246
- package/skills/fui-skill/references/watcher-patterns.md +30 -63
- package/skills/fui-skill/references/websocket-realtime.md +83 -66
- package/skills/fui-skill/scripts/component-3.0.js +298 -131
- package/skills/fui-skill/scripts/component.js +277 -271
- package/skills/fui-skill/scripts/componentTable-3.0.js +182 -53
- package/skills/fui-skill/scripts/componentTable.js +171 -49
- package/skills/fui-skill/scripts/defaultfunction-3.0.js +88 -3
- package/skills/fui-skill/scripts/defaultfunction.js +88 -3
- package/skills/fui-skill/scripts/fsheet.js +38 -0
- package/dist/fui-y8an39cn.js +0 -420
- package/skills/fui-skill/README.md +0 -112
- package/skills/fui-skill/metadata.json +0 -75
- package/skills/fui-skill-cli/SKILL.md +0 -139
- package/skills/fui-skill-cli/references/INDEX.md +0 -110
- package/skills/fui-skill-cli/references/advanced-techniques.md +0 -168
- package/skills/fui-skill-cli/references/coding-standards.md +0 -112
- package/skills/fui-skill-cli/references/component-design.md +0 -448
- package/skills/fui-skill-cli/references/component-quickref.md +0 -78
- package/skills/fui-skill-cli/references/component-table.md +0 -248
- package/skills/fui-skill-cli/references/components-dialog.md +0 -191
- package/skills/fui-skill-cli/references/components-display.md +0 -141
- package/skills/fui-skill-cli/references/components-echart.md +0 -316
- package/skills/fui-skill-cli/references/components-input.md +0 -335
- package/skills/fui-skill-cli/references/controls-patterns.md +0 -701
- package/skills/fui-skill-cli/references/controls-styling-vocabulary.md +0 -137
- package/skills/fui-skill-cli/references/db-table-design.md +0 -73
- package/skills/fui-skill-cli/references/db-workflow.md +0 -288
- package/skills/fui-skill-cli/references/default-function.md +0 -425
- package/skills/fui-skill-cli/references/design-modes.md +0 -57
- package/skills/fui-skill-cli/references/echart-templates.md +0 -489
- package/skills/fui-skill-cli/references/fastproject.md +0 -99
- package/skills/fui-skill-cli/references/fsheet.md +0 -203
- package/skills/fui-skill-cli/references/fullstack-workflow.md +0 -313
- package/skills/fui-skill-cli/references/module-data-patterns.md +0 -117
- package/skills/fui-skill-cli/references/module-json-anatomy.md +0 -132
- package/skills/fui-skill-cli/references/module-structure.md +0 -141
- package/skills/fui-skill-cli/references/new-session.md +0 -85
- package/skills/fui-skill-cli/references/pdfmake.md +0 -60
- package/skills/fui-skill-cli/references/permission-system.md +0 -150
- package/skills/fui-skill-cli/references/platform-architecture.md +0 -269
- package/skills/fui-skill-cli/references/project-config.md +0 -303
- package/skills/fui-skill-cli/references/project-provisioning.md +0 -278
- package/skills/fui-skill-cli/references/script-map.md +0 -262
- package/skills/fui-skill-cli/references/sql-clr-functions.md +0 -225
- package/skills/fui-skill-cli/references/system-design.md +0 -89
- package/skills/fui-skill-cli/references/tapi-file-api.md +0 -185
- package/skills/fui-skill-cli/references/tapi-permission-patterns.md +0 -156
- package/skills/fui-skill-cli/references/tapi-reference.md +0 -474
- package/skills/fui-skill-cli/references/tools-registry.md +0 -84
- package/skills/fui-skill-cli/references/ui-crosswindow-patterns.md +0 -321
- package/skills/fui-skill-cli/references/ui-dialog-patterns.md +0 -255
- package/skills/fui-skill-cli/references/ui-layout-patterns.md +0 -176
- package/skills/fui-skill-cli/references/ui-patterns.md +0 -303
- package/skills/fui-skill-cli/references/ui-screenshot-review.md +0 -95
- package/skills/fui-skill-cli/references/ui-table-cell-patterns.md +0 -318
- package/skills/fui-skill-cli/references/ui-templates.md +0 -22
- package/skills/fui-skill-cli/references/verification.md +0 -236
- package/skills/fui-skill-cli/references/watcher-patterns.md +0 -163
- package/skills/fui-skill-cli/references/websocket-realtime.md +0 -271
|
@@ -1,37 +1,25 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Provisioning a New FUI Project
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Owns: **new-project infrastructure — SQL Server database, two SQL accounts (execute-only app vs db_owner dev), `acc` alias, FUI project, project admin rights**. Connection/schema/SP: [db-workflow.md](db-workflow.md); multi-module design: [system-design.md](system-design.md); table naming: [db-table-design.md](db-table-design.md); end-user rights: [permission-system.md](permission-system.md). Flags: `fui <command> --help`.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
[system-design.md](system-design.md) Bước 0 rơi vào nhánh *"dựng mới hoàn toàn"*. Đây là bước **trước**
|
|
7
|
-
mọi thứ trong `system-design.md`: chưa có database và chưa có project thì không có gì để thiết kế lên.
|
|
5
|
+
Use for **"new project"** / **"new DB + FUI project"**, or [system-design.md](system-design.md) Step 0 → _"build from scratch"_. Comes **before** all of `system-design.md`.
|
|
8
6
|
|
|
9
|
-
**
|
|
10
|
-
này **không tuỳ tiện**: có **hai** cổng quyền ở hai hệ thống khác nhau và cả hai phải được kiểm trước
|
|
11
|
-
khi tạo bất cứ thứ gì — xem mục ngay dưới.
|
|
7
|
+
**Do Step 0, then Steps 1–6 in order, skipping none** unless the user says otherwise. Two permission gates in two systems must both pass before anything is created.
|
|
12
8
|
|
|
13
9
|
---
|
|
14
10
|
|
|
15
|
-
## 🛑
|
|
11
|
+
## 🛑 Step 0 — Check BOTH gates first
|
|
16
12
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
| Gate | Needs | Check with |
|
|
14
|
+
| ------------------------ | --------------------------------- | -------------------------- |
|
|
15
|
+
| **A. FUI platform** | `SystemRight >= 3` on system `fp` | `fui project new` (Step 1) |
|
|
16
|
+
| **B. Target SQL Server** | create database + create login | read-only `SELECT` below |
|
|
20
17
|
|
|
21
|
-
|
|
22
|
-
|---|---|---|
|
|
23
|
-
| **A. Nền tảng FUI** | `SystemRight >= 3` trên hệ thống `fp` | gọi `project_new` (Bước 1) |
|
|
24
|
-
| **B. SQL Server đích** | quyền tạo database + tạo login | một câu `SELECT` chỉ đọc (ngay dưới) |
|
|
18
|
+
**Check B BEFORE A.** B has no side effects; A only answers by actually creating the project. Reverse order ⇒ orphan FUI project if the DB can't be created. Late discovery leaves garbage fui can't clean up.
|
|
25
19
|
|
|
26
|
-
|
|
27
|
-
thì phải *thật sự tạo project* mới biết. Làm ngược lại là tạo ra một project FUI mồ côi khi hoá ra
|
|
28
|
-
không có quyền tạo database.
|
|
20
|
+
### Gate B — target SQL Server
|
|
29
21
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
`CREATE DATABASE` và `CREATE LOGIN` là thao tác **cấp máy chủ**, tài khoản dev thường ngày (chỉ
|
|
33
|
-
`db_owner` trên vài database) **không làm được**. Chạy câu này qua `db_sql_execute` trên một kết nối
|
|
34
|
-
**tới đúng SQL Server sắp tạo DB** (`db_alias_list()` cho biết alias nào nằm trên server nào):
|
|
22
|
+
`CREATE DATABASE`/`CREATE LOGIN` are server-level; a normal dev account (`db_owner` on some DBs) can't. Run with `fui query` on a connection **to the exact target server** (`fui db alias list` shows alias → server):
|
|
35
23
|
|
|
36
24
|
```sql
|
|
37
25
|
SELECT SUSER_NAME() AS LoginHienTai,
|
|
@@ -42,30 +30,19 @@ SELECT SUSER_NAME() AS LoginHienTai,
|
|
|
42
30
|
HAS_PERMS_BY_NAME(NULL, NULL, 'ALTER ANY LOGIN') AS taoDuocLogin;
|
|
43
31
|
```
|
|
44
32
|
|
|
45
|
-
|
|
33
|
+
Pass: `sysadmin = 1`, **or** `taoDuocDB = 1` **and** `taoDuocLogin = 1`.
|
|
46
34
|
|
|
47
|
-
-
|
|
48
|
-
|
|
49
|
-
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
- `IS_SRVROLEMEMBER` trả `NULL` (không phải `0`) khi tên role sai hoặc login không hợp lệ — đọc `NULL`
|
|
53
|
-
thành "không có quyền" là kết luận sai; coi như **không biết** và hỏi user.
|
|
54
|
-
- **Kết nối phải đúng SQL Server đích.** Kết nối mượn của project anh em có thể trỏ sang máy chủ khác;
|
|
55
|
-
lúc đó câu trên trả quyền của máy chủ *sai*, và kết quả xanh là xanh nhầm chỗ.
|
|
56
|
-
- ⚠️ Ở đây `HAS_PERMS_BY_NAME` là **đúng công cụ** vì ta đang hỏi về *chính principal đang kết nối*.
|
|
57
|
-
Đừng đem cách này đi hỏi quyền của principal **khác** (ví dụ `[public]` có `EXECUTE` không) — nó trả
|
|
58
|
-
lời cho người đang hỏi, nên sẽ luôn xanh với login `db_owner` và cho một câu trả lời sai. Ca đó phải
|
|
59
|
-
đọc `sys.database_permissions`.
|
|
35
|
+
- `sa` not required — `dbcreator` + `securityadmin` also pass. Don't block a valid setup with "needs `sa`".
|
|
36
|
+
- Need BOTH: `dbcreator` alone creates the DB but not the Step 3 login ⇒ fails midway.
|
|
37
|
+
- `IS_SRVROLEMEMBER` returns `NULL` (not `0`) for a bad role name/invalid login ⇒ **unknown**, ask the user.
|
|
38
|
+
- A connection borrowed from a sibling project may point at another server ⇒ green for the wrong server.
|
|
39
|
+
- ⚠️ `HAS_PERMS_BY_NAME` answers only for the _connected principal_ — correct here. Never use it for another principal (e.g. `[public]` `EXECUTE`): always green for `db_owner`. Read `sys.database_permissions` instead.
|
|
60
40
|
|
|
61
|
-
|
|
62
|
-
có lỗi không" — và cũng đừng tự hạ tiêu chuẩn xuống bằng cách cấp `db_datareader` cho tài khoản ứng
|
|
63
|
-
dụng để né bước tạo login.
|
|
41
|
+
Fails ⇒ **stop; user must request rights on that server**. Never run `CREATE DATABASE` to probe; never grant `db_datareader` to the app account to avoid creating a login.
|
|
64
42
|
|
|
65
|
-
###
|
|
43
|
+
### Gate A — FUI platform
|
|
66
44
|
|
|
67
|
-
|
|
68
|
-
thân `spAPI_FUI_Dev_ProjectEdit` — không né được bằng cách gọi API trực tiếp:
|
|
45
|
+
Creating a project needs **`SystemRight >= 3`** on `fp`, enforced server-side in `spAPI_FUI_Dev_ProjectEdit` (direct API calls can't bypass):
|
|
69
46
|
|
|
70
47
|
```sql
|
|
71
48
|
if @jID is null -- không có id ⇒ đang TẠO MỚI
|
|
@@ -74,137 +51,98 @@ Begin
|
|
|
74
51
|
RAISERROR(N'Bạn không có quyền tạo dự án', 16, 1)
|
|
75
52
|
```
|
|
76
53
|
|
|
77
|
-
**
|
|
78
|
-
trước phần database: `INSERT INTO tblA_Project` chỉ cần
|
|
79
|
-
`ProjectID`/`ProjectName`/`GroupName`/`Framework`/`pDomain`/`Router`, **không tham chiếu database nào**
|
|
80
|
-
— nên tạo project *không* cần DB có trước. Làm DB trước rồi mới phát hiện bị từ chối là để lại một
|
|
81
|
-
database thật, hai SQL login và một bản ghi `acc` mồ côi; mà `DROP DATABASE` thì MCP chặn cứng, dọn
|
|
82
|
-
phải làm tay.
|
|
83
|
-
|
|
84
|
-
Gọi `project_new` chính là phép kiểm cổng A — vừa là việc phải làm, không tốn thêm lượt gọi nào. Bị từ
|
|
85
|
-
chối thì chưa có gì được tạo ra (với điều kiện cổng B đã kiểm trước, đúng thứ tự ở trên).
|
|
86
|
-
|
|
87
|
-
Ba mức quyền khác nhau cho ba thao tác, đừng nhầm (đọc từ thân SP thật):
|
|
54
|
+
**No right ⇒ STOP, report, do nothing else.** Project goes before the DB because `INSERT INTO tblA_Project` needs only `ProjectID`/`ProjectName`/`GroupName`/`Framework`/`pDomain`/`Router` — no database. DB-first then rejection leaves a real DB, two SQL logins and an orphan `acc` record; fui hard-blocks `DROP DATABASE`, so cleanup is manual. `fui project new` _is_ the gate A check (no extra call); rejected ⇒ nothing created (if B was checked first).
|
|
88
55
|
|
|
89
|
-
|
|
|
90
|
-
|
|
91
|
-
| **
|
|
92
|
-
| **
|
|
93
|
-
| Publish `project.json` (`
|
|
94
|
-
|
|
|
56
|
+
| Operation | SP | Condition |
|
|
57
|
+
| ----------------------------------------------------- | --------------------------------------------------------- | ------------------------------------------ |
|
|
58
|
+
| **Create** project (`fui project new`) | `spAPI_FUI_Dev_ProjectEdit` (empty `id`) | `SystemRight >= 3` |
|
|
59
|
+
| **Edit** project (`fui project update`) | `spAPI_FUI_Dev_ProjectEdit` (with `id`) | `SystemRight >= 2` **and** `UserRight > 2` |
|
|
60
|
+
| Publish `project.json` (`fui project publish-config`) | `spAPI_FUI_Dev_EditorUpdate` (`Mode = 'project'`) | `SystemRight >= 2` **and** `UserRight > 2` |
|
|
61
|
+
| Create/edit/publish **module** | `spAPI_FUI_Dev_ModuleEdit` · `spAPI_FUI_Dev_EditorUpdate` | `SystemRight >= 2` **and** `UserRight > 1` |
|
|
95
62
|
|
|
96
|
-
`SystemRight`
|
|
97
|
-
project đó) — hai trục AND với nhau. Chỉ riêng *tạo* project là không xét `UserRight`, vì project chưa
|
|
98
|
-
tồn tại thì chưa có dòng nào trong `tblA_UserProject`.
|
|
63
|
+
`SystemRight` (whole `fp`) is necessary, `UserRight` (that project) sufficient — ANDed. Only _create_ skips `UserRight` (no `tblA_UserProject` row yet).
|
|
99
64
|
|
|
100
|
-
> ⚠️ `pDomain`
|
|
101
|
-
> domain chứ không phải lỗi quyền. Đừng đọc nhầm thông báo rồi đi xin cấp quyền.
|
|
65
|
+
> ⚠️ `pDomain` is checked **before** the permission gate (`CheckDomain`): a duplicate domain gives a domain error, not a permission error. Don't go request rights over it.
|
|
102
66
|
|
|
103
67
|
---
|
|
104
68
|
|
|
105
|
-
##
|
|
69
|
+
## Index — phases of a new project
|
|
106
70
|
|
|
107
|
-
|
|
108
|
-
và đọc tiếp file nào, thay vì mò từng file một.
|
|
71
|
+
This file owns **phase 1 only**.
|
|
109
72
|
|
|
110
|
-
| #
|
|
111
|
-
|
|
112
|
-
| 0
|
|
113
|
-
| **1** | **
|
|
114
|
-
| 2
|
|
115
|
-
| 3
|
|
116
|
-
| 4
|
|
117
|
-
| 5
|
|
118
|
-
| 6
|
|
73
|
+
| # | Phase | Owner | Do |
|
|
74
|
+
| ----- | ------------------------- | -------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
|
|
75
|
+
| 0 | Clarify scope | [system-design.md](system-design.md) §Step 0 | Users, process, main entities |
|
|
76
|
+
| **1** | **Infrastructure ← HERE** | **this file** | 2 gates → `fui project new` → DB + 2 SQL accounts + `acc` alias → admin rights |
|
|
77
|
+
| 2 | Split into modules | [system-design.md](system-design.md) §Step 1 | Module list, access roles |
|
|
78
|
+
| 3 | Schema | [db-table-design.md](db-table-design.md) | Naming, PK/FK, audit columns. `CREATE TABLE` **run by the developer** |
|
|
79
|
+
| 4 | **End-user** rights | [permission-system.md](permission-system.md) + [system-design.md](system-design.md) §Step 4b | `fui right system new` / `fui right function new` — BEFORE any module gates on them |
|
|
80
|
+
| 5 | Runtime config | [project-config.md](project-config.md) | `project.json`: menu, menuLeft, navigation, domainSetting |
|
|
81
|
+
| 6 | First module | `fui module new` → [fullstack-workflow.md](fullstack-workflow.md) | 6-step UI-first flow |
|
|
119
82
|
|
|
120
|
-
|
|
121
|
-
quyền người dùng cuối · cách viết SP ([tapi-reference.md](tapi-reference.md)) · kết nối/schema/SP hằng
|
|
122
|
-
ngày ([db-workflow.md](db-workflow.md)).
|
|
83
|
+
Not in this file (don't look or copy here): table naming · menus · end-user rights · SP writing ([tapi-reference.md](tapi-reference.md)) · daily connection/schema/SP ([db-workflow.md](db-workflow.md)).
|
|
123
84
|
|
|
124
85
|
---
|
|
125
86
|
|
|
126
|
-
## 🔴
|
|
87
|
+
## 🔴 Two permission planes — don't mix
|
|
127
88
|
|
|
128
|
-
|
|
129
|
-
|
|
89
|
+
| | `SystemRight` (system `acc`) | `UserRight` (`tblA_UserProject`) |
|
|
90
|
+
| --------- | ------------------------------------------------------------------ | --------------------------------------- |
|
|
91
|
+
| Scope | **System-wide** — one number per user per app | **Per project** |
|
|
92
|
+
| Answers | "What can this user do in app X?" | "What can this user do with project Y?" |
|
|
93
|
+
| Stored in | `acc.tblSysRight` + `acc` assignment tables | `tblA_UserProject` (FUI platform DB) |
|
|
94
|
+
| Commands | `fui right ...` (8) → [permission-system.md](permission-system.md) | `fui user ...` (5) → Step 6 |
|
|
130
95
|
|
|
131
|
-
|
|
132
|
-
|---|---|---|
|
|
133
|
-
| Phạm vi | **Toàn hệ thống** — một con số cho một user trên một app | **Từng project một** |
|
|
134
|
-
| Trả lời câu hỏi | "User này làm được gì trong app X nói chung?" | "User này làm được gì với project Y cụ thể?" |
|
|
135
|
-
| Lưu ở | `acc.tblSysRight` + bảng gán quyền của `acc` | `tblA_UserProject` (DB nền tảng FUI) |
|
|
136
|
-
| Tool | 8 tool `right_*` → [permission-system.md](permission-system.md) | 5 tool `project_user_*` → Bước 6 dưới đây |
|
|
96
|
+
Mixing them = granting in the wrong place, then "granted but no effect". The FUI IDE _is itself a FUI app_ (project `fp`), so `SystemRight` on `fp` = developer rights in the IDE:
|
|
137
97
|
|
|
138
|
-
|
|
139
|
-
`
|
|
140
|
-
|
|
98
|
+
- `SystemRight` on `fp` = **may create projects** (≥ 3); necessary for every edit.
|
|
99
|
+
- `UserRight` on project Y = **may touch Y**; sufficient.
|
|
100
|
+
- ANDed: `UserRight = 3` with `SystemRight = 1` can't edit anything.
|
|
141
101
|
|
|
142
|
-
|
|
143
|
-
thao tác sửa.
|
|
144
|
-
- `UserRight` trên project Y = **được đụng vào project Y hay không**. Điều kiện *đủ*.
|
|
145
|
-
- Hai cái **AND với nhau**, xem bảng ba thao tác ở mục trên. Có `UserRight = 3` mà `SystemRight = 1`
|
|
146
|
-
thì vẫn không sửa được gì.
|
|
147
|
-
|
|
148
|
-
Còn `SystemRight`/`FunctionRight` trên **project nghiệp vụ của bạn** (không phải `fp`) thì đúng là quyền
|
|
149
|
-
của người dùng cuối trong app đó — việc đó làm sau, theo
|
|
150
|
-
[system-design.md](system-design.md) Bước 4b.
|
|
102
|
+
`SystemRight`/`FunctionRight` on **your business project** (not `fp`) are end-user rights — later, per [system-design.md](system-design.md) Step 4b.
|
|
151
103
|
|
|
152
104
|
---
|
|
153
105
|
|
|
154
|
-
##
|
|
106
|
+
## Step 1 — Create the FUI project (gate A, before the DB)
|
|
155
107
|
|
|
156
108
|
```
|
|
157
|
-
|
|
158
|
-
ProjectID: "...", ProjectName: "...", GroupName: "...", Framework: "V3",
|
|
159
|
-
pDomain: "...",
|
|
160
|
-
Router: ""
|
|
161
|
-
}
|
|
109
|
+
fui project new --data '{
|
|
110
|
+
"ProjectID": "...", "ProjectName": "...", "GroupName": "...", "Framework": "V3",
|
|
111
|
+
"pDomain": "...",
|
|
112
|
+
"Router": ""
|
|
113
|
+
}'
|
|
162
114
|
```
|
|
163
115
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
-
|
|
167
|
-
|
|
116
|
+
`pDomain` optional (project's own domain); `Router` optional, default `""`.
|
|
117
|
+
|
|
118
|
+
- **Only these SIX fields are read** from `@jsonObj`.
|
|
119
|
+
- 🔴 **`title`/`login`/`apiDomain`/`fileDomain`/`userInfo`/`menu` are silently IGNORED.** The SP writes `projectData` from a hardcoded constant:
|
|
168
120
|
```sql
|
|
169
121
|
declare @jProjectdata nvarchar(1000) = '{"title":"","apiDomain":"","login":"","menu":[]}'
|
|
170
122
|
```
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
component, và cả cú pháp grid — V2 là Vuetify 1.5 (`v-container/v-layout/v-flex`), V3 là Vuetify 3
|
|
180
|
-
(`v-container/v-row/v-col`), và ngưỡng `w` px của hai bên cũng khác nhau. Phần lớn ví dụ module.json
|
|
181
|
-
trong skill viết theo cú pháp **V2** (đa số project đang chạy), nên khi làm project V3 phải đối chiếu
|
|
182
|
-
→ [controls-patterns.md](controls-patterns.md) §6 (chủ sở hữu bảng khác biệt V2/V3). Nêu rõ lựa chọn
|
|
183
|
-
này với user, đừng để nó thành mặc định ngầm.
|
|
184
|
-
|
|
185
|
-
**Người gọi API tự động được `UserRight = 3` trên project vừa tạo — chỉ người tạo, không ai khác**
|
|
186
|
-
(SP tự `INSERT INTO tblA_UserProject ... 3`). Đó chính là lý do phải có Bước 6.
|
|
187
|
-
|
|
188
|
-
Bị từ chối `Bạn không có quyền tạo dự án` → **dừng hẳn, báo user xin `SystemRight >= 3` trên hệ thống
|
|
189
|
-
`fp`**. Không đi tiếp các bước dưới: lúc này chưa có gì được tạo ra, và nên giữ nguyên như vậy.
|
|
123
|
+
API still returns ✅, project created, config lost — silent failure.
|
|
124
|
+
- Runtime config: edit `{projectId}/project.json` then `fui project publish-config` ([project-config.md](project-config.md)) — the **only** way `menu`/`apiDomain`/`login` get in.
|
|
125
|
+
- `projectData` must be **FLAT** — not wrapped in `"data"`.
|
|
126
|
+
- **`Framework`: `V3` for new projects** unless the user has a reason (usually matching older projects in the group). Expensive to change: decides import layer, component vocabulary, grid syntax — V2 = Vuetify 1.5 (`v-container/v-layout/v-flex`), V3 = Vuetify 3 (`v-container/v-row/v-col`), and `w` px thresholds differ. Most skill module.json examples are **V2**; for V3 cross-check [controls-patterns.md](controls-patterns.md) §6 (V2/V3 diff owner). State the choice to the user; never implicit.
|
|
127
|
+
|
|
128
|
+
**Only the caller gets `UserRight = 3` on the new project** (SP `INSERT INTO tblA_UserProject ... 3`) — hence Step 6.
|
|
129
|
+
|
|
130
|
+
Rejected with `Bạn không có quyền tạo dự án` ⇒ **stop; user must request `SystemRight >= 3` on `fp`**. Nothing created yet — keep it so.
|
|
190
131
|
|
|
191
132
|
---
|
|
192
133
|
|
|
193
|
-
##
|
|
134
|
+
## Step 2 — Create the database
|
|
194
135
|
|
|
195
|
-
>
|
|
196
|
-
> `ALTER ANY LOGIN`). Chưa kiểm thì quay lại kiểm — đừng chạy `CREATE DATABASE` để dò xem có lỗi không.
|
|
136
|
+
> Prerequisite: gate B green. Never run `CREATE DATABASE` to probe.
|
|
197
137
|
|
|
198
|
-
**
|
|
199
|
-
Mỗi server một quy ước; đoán sai thì file nằm lạc chỗ và không ai phát hiện cho tới lúc backup.
|
|
138
|
+
**Query where the server keeps other DB files; never hardcode paths** (wrong guess = misplaced files, unnoticed until backup):
|
|
200
139
|
|
|
201
140
|
```sql
|
|
202
141
|
SELECT DISTINCT LEFT(physical_name, LEN(physical_name) - CHARINDEX('\', REVERSE(physical_name)))
|
|
203
142
|
FROM sys.master_files WHERE database_id > 4;
|
|
204
143
|
```
|
|
205
144
|
|
|
206
|
-
`database_id > 4`
|
|
207
|
-
phải nơi đặt DB nghiệp vụ. Kết quả thường gặp: `C:\Application\Database\`. Dùng chung đúng quy ước đó:
|
|
145
|
+
`database_id > 4` skips `master`/`model`/`msdb`/`tempdb` (install dir). Typical: `C:\Application\Database\`. Follow it:
|
|
208
146
|
|
|
209
147
|
```sql
|
|
210
148
|
CREATE DATABASE [TenDB]
|
|
@@ -212,15 +150,13 @@ ON PRIMARY (NAME = N'TenDB', FILENAME = N'C:\Application\Database\TenDB.mdf'
|
|
|
212
150
|
LOG ON (NAME = N'TenDB_log', FILENAME = N'C:\Application\Database\TenDB_log.ldf');
|
|
213
151
|
```
|
|
214
152
|
|
|
215
|
-
|
|
216
|
-
SQL Server đó** — `db_alias_list()` cho biết alias nào đang nằm trên server nào, rồi
|
|
217
|
-
`db_connect_by_name({ apiName })` để mượn. Chạy bằng `db_sql_execute_nonquery({ confirmWrite: true })`.
|
|
153
|
+
Chicken-and-egg: the new DB has no connection — borrow an **existing connection on the same server** (`fui db alias list`, then `fui db add-by-name <apiName>`) and run `fui exec "<sql>" --confirm-write`.
|
|
218
154
|
|
|
219
155
|
---
|
|
220
156
|
|
|
221
|
-
##
|
|
157
|
+
## Step 3 — APP account (execute-only)
|
|
222
158
|
|
|
223
|
-
Login **
|
|
159
|
+
Login **named after the DB**, strong random password:
|
|
224
160
|
|
|
225
161
|
```bash
|
|
226
162
|
openssl rand -base64 12
|
|
@@ -234,19 +170,15 @@ CREATE USER [TenDB] FOR LOGIN [TenDB];
|
|
|
234
170
|
GRANT EXECUTE ON SCHEMA::dbo TO [TenDB];
|
|
235
171
|
```
|
|
236
172
|
|
|
237
|
-
**
|
|
238
|
-
cấp quyền trên bảng.** Lý do: tAPI chỉ chạy stored procedure, nên execute-only là **đủ dùng** — mọi SP
|
|
239
|
-
mới tự động nằm trong `SCHEMA::dbo` nên không phải cấp lại từng cái. Cấp thêm quyền bảng không giúp app
|
|
240
|
-
chạy tốt hơn, nó chỉ mở sẵn đường đọc/ghi thẳng bảng cho một lời gọi bị lợi dụng.
|
|
173
|
+
**Only `public` + `GRANT EXECUTE ON SCHEMA::dbo`. NO `db_datareader`, NO `db_datawriter`, NO table grants.** tAPI only runs SPs; new SPs fall under `SCHEMA::dbo` automatically. Table rights don't help the app — they only open direct table access to an abused call.
|
|
241
174
|
|
|
242
|
-
|
|
175
|
+
The **only** account loaded into `acc` (Step 5).
|
|
243
176
|
|
|
244
177
|
---
|
|
245
178
|
|
|
246
|
-
##
|
|
179
|
+
## Step 4 — DEV account (db_owner)
|
|
247
180
|
|
|
248
|
-
**
|
|
249
|
-
cấp server, chỉ cần cấp vào database mới:
|
|
181
|
+
**Default: reuse the existing shared dev login** (e.g. `xTuan`) — just add it to the new DB:
|
|
250
182
|
|
|
251
183
|
```sql
|
|
252
184
|
USE [TenDB];
|
|
@@ -254,130 +186,93 @@ CREATE USER [xTuan] FOR LOGIN [xTuan];
|
|
|
254
186
|
ALTER ROLE db_owner ADD MEMBER [xTuan];
|
|
255
187
|
```
|
|
256
188
|
|
|
257
|
-
**
|
|
258
|
-
cho mỗi project là đẻ thêm một mật khẩu phải quản lý, trong khi tài khoản dùng chung đã có sẵn ở mọi
|
|
259
|
-
DB anh em — và chính nó là cặp credential mà `db_connect_by_name` mượn được.
|
|
189
|
+
**NO new `CREATE LOGIN`** unless the user asks for a project-specific dev account — each extra login is another password, while the shared one exists in every sibling DB and is the credential `fui db add-by-name` borrows.
|
|
260
190
|
|
|
261
191
|
---
|
|
262
192
|
|
|
263
|
-
##
|
|
193
|
+
## Step 5 — Register the DB as a tAPI alias
|
|
264
194
|
|
|
265
195
|
```
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
password: "<mật khẩu Bước 3>"
|
|
273
|
-
})
|
|
196
|
+
fui db alias new tenalias \
|
|
197
|
+
--module-name "Tên hệ thống" \
|
|
198
|
+
--sql-server "..." \
|
|
199
|
+
--database TenDB \
|
|
200
|
+
--username TenDB \
|
|
201
|
+
--password-env TENDB_PASSWORD
|
|
274
202
|
```
|
|
275
203
|
|
|
276
|
-
|
|
277
|
-
|
|
204
|
+
`tenalias` → module.json calls `"/tenalias/TenAPI"`. Password only via `--password -` (stdin) or `--password-env VAR`.
|
|
205
|
+
|
|
206
|
+
fui calls `SM_Modules_Update` **twice**: `UpdateConnection=0` creates the record, `UpdateConnection=1` sets the connection (record must exist first).
|
|
278
207
|
|
|
279
|
-
- 🔴
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
- `ModuleID` mới = `MAX(ModuleID)+1` trên **toàn bộ** `acc.tblModules` → tool cần một kết nối alias
|
|
283
|
-
`acc` (`db_connect_by_name({ apiName: "acc" })`). Không suy từ `db_alias_list` được: danh sách đó chỉ
|
|
284
|
-
gồm module **bạn** được quản lý, MAX trên tập con có thể đụng ID của người khác.
|
|
285
|
-
- Alias đã tồn tại ⇒ lỗi cứng, tool không ghi đè.
|
|
208
|
+
- 🔴 **Credentials = Step 3 APP account, NEVER the dev account.** Dev account ⇒ every app API call runs as `db_owner`, with no visible error.
|
|
209
|
+
- New `ModuleID` = `MAX(ModuleID)+1` over **all** `acc.tblModules` ⇒ needs an `acc` connection (`fui db add-by-name acc`). Can't use `fui db alias list`: it lists only modules **you** manage; MAX over a subset may collide.
|
|
210
|
+
- Existing alias ⇒ hard error, no overwrite.
|
|
286
211
|
|
|
287
|
-
|
|
288
|
-
[db-workflow.md](db-workflow.md) §2b.
|
|
212
|
+
Then `fui db add-by-name tenalias` works — [db-workflow.md](db-workflow.md) §2b.
|
|
289
213
|
|
|
290
214
|
---
|
|
291
215
|
|
|
292
|
-
##
|
|
216
|
+
## Step 6 — Grant project admin to others
|
|
293
217
|
|
|
294
|
-
|
|
218
|
+
Order is **mandatory**:
|
|
295
219
|
|
|
296
220
|
```
|
|
297
|
-
1.
|
|
298
|
-
2.
|
|
299
|
-
3.
|
|
221
|
+
1. fui user list → who has rights now
|
|
222
|
+
2. fui user search "tên/username" → get the real UserID
|
|
223
|
+
3. fui user add DEV001 --right 3
|
|
300
224
|
```
|
|
301
225
|
|
|
302
|
-
**`
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
`_update`), và ngược lại. Không tool nào upsert ngầm.
|
|
316
|
-
- Thu hồi quyền là `project_user_delete` — 🔴 tóm tắt hậu quả và chờ user xác nhận trước khi gọi.
|
|
317
|
-
- **Quyền LUÔN là cấp project — không có biến thể cấp module.** Chữ ký SP có `@MID` và module
|
|
318
|
-
`fp/permission` của IDE cũng truyền nó, nhưng **thân SP không bao giờ đọc**: mọi thao tác lọc theo
|
|
319
|
-
`ProjectID`. Đừng suy ra một phạm vi không tồn tại từ việc thấy tham số đó.
|
|
320
|
-
|
|
321
|
-
**Điều kiện để CHÍNH BẠN cấp được quyền** (thân `spAPI_FUI_Dev_UserRight_Update`):
|
|
322
|
-
`SystemRight >= 2` **và** (`UserRight > 2` trên project đó **hoặc** `SystemRight >= 4`) — tức
|
|
323
|
-
`SystemRight >= 4` cấp được cho mọi project mà không cần là admin của project đó. Chỉ *xem* danh sách
|
|
324
|
-
(`project_user_list`) thì nhẹ hơn: `SystemRight >= 2` và (`UserRight > 1` hoặc `SystemRight >= 3`).
|
|
226
|
+
**`fui user add`/`set`/`remove` take only the exact `UserID`** — a structural identity gate: you must run `fui user search` and see `UserID | Username | Họ tên`. **Show that table and let the user pick before granting** — duplicate names are common; a wrong Admin grant can't be undone in one call.
|
|
227
|
+
|
|
228
|
+
| Level | Meaning |
|
|
229
|
+
| ----- | -------------------------------------------------------------------------------------- |
|
|
230
|
+
| 1 | View only |
|
|
231
|
+
| 2 | Develop |
|
|
232
|
+
| 3 | **Admin** — needed to manage the project (`fui project publish-config` requires `> 2`) |
|
|
233
|
+
|
|
234
|
+
- Create and edit are separate: `fui user add` hard-errors if rights exist (use `set`), and vice versa. No silent upsert.
|
|
235
|
+
- Revoke = `fui user remove` — 🔴 summarize the consequence, wait for confirmation.
|
|
236
|
+
- **Rights are ALWAYS project-level.** The SP has `@MID` and IDE module `fp/permission` passes it, but the body never reads it — all filtering is by `ProjectID`. Don't infer a module scope.
|
|
237
|
+
|
|
238
|
+
**For YOU to grant** (`spAPI_FUI_Dev_UserRight_Update`): `SystemRight >= 2` **and** (`UserRight > 2` on the project **or** `SystemRight >= 4`) — `SystemRight >= 4` grants on any project. _Listing_ (`fui user list`): `SystemRight >= 2` and (`UserRight > 1` or `SystemRight >= 3`).
|
|
325
239
|
|
|
326
240
|
---
|
|
327
241
|
|
|
328
|
-
##
|
|
242
|
+
## After infrastructure
|
|
329
243
|
|
|
330
|
-
|
|
331
|
-
runtime** (`menu`/`apiDomain`/`login` vẫn là chuỗi rỗng do SP seed — xem Bước 1), chưa có bảng, chưa có
|
|
332
|
-
module, chưa có mã quyền nào. Đừng dừng ở đây và báo "đã xong", cũng đừng nhảy thẳng vào viết module.json.
|
|
244
|
+
Step 6 ends **phase 1 only**: the project is empty, runtime config still SP-seeded empty strings, no tables/modules/right codes. Don't report "done"; don't jump into module.json.
|
|
333
245
|
|
|
334
|
-
1. `
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
không phải tuỳ chọn: `project_new` không nhận những khoá này, nên bỏ qua bước này là project không
|
|
339
|
-
gọi được API nào.
|
|
340
|
-
3. `db_connect_by_name({ apiName })` — kết nối alias vừa tạo ([db-workflow.md](db-workflow.md) §2c).
|
|
341
|
-
Đây cũng là **phép thử** rằng Bước 3 và Bước 5 đã đúng: nó chạy được nghĩa là tài khoản ứng dụng và
|
|
342
|
-
bản ghi `acc` đều ổn.
|
|
343
|
-
4. Quay lại [system-design.md](system-design.md) từ **Bước 1** và đi tiếp theo thứ tự ở chỉ mục trên.
|
|
246
|
+
1. `fui project sync` + `fui use <projectId>` — pull into workspace, set as target.
|
|
247
|
+
2. **Runtime config (mandatory)**: edit `{projectId}/project.json` (`apiDomain` → new alias, `title`, `login`, `menu`), then `fui project publish-config` — [project-config.md](project-config.md). Skipped ⇒ the project can't call any API.
|
|
248
|
+
3. `fui db add-by-name <apiName>` ([db-workflow.md](db-workflow.md) §2c) — also **proves** Steps 3 and 5 (app account + `acc` record OK).
|
|
249
|
+
4. Resume [system-design.md](system-design.md) at **Step 1**, following the index.
|
|
344
250
|
|
|
345
|
-
|
|
346
|
-
thẳng `module_new` → [fullstack-workflow.md](fullstack-workflow.md).
|
|
251
|
+
Only **one** simple module ⇒ skip `system-design.md`: `fui module new` → [fullstack-workflow.md](fullstack-workflow.md).
|
|
347
252
|
|
|
348
253
|
---
|
|
349
254
|
|
|
350
255
|
## Checklist
|
|
351
256
|
|
|
352
|
-
- [ ]
|
|
353
|
-
- [ ]
|
|
354
|
-
- [ ] `projectData`
|
|
355
|
-
- [ ]
|
|
356
|
-
- [ ]
|
|
357
|
-
- [ ]
|
|
358
|
-
- [ ]
|
|
359
|
-
- [ ] `
|
|
360
|
-
- [ ] `
|
|
361
|
-
- [ ] `
|
|
362
|
-
- [ ]
|
|
363
|
-
- [ ]
|
|
364
|
-
- [ ] **Kiểm chứng bảo mật**: đăng nhập bằng tài khoản ứng dụng, `SELECT TOP 1 * FROM <bảng bất kỳ>` phải
|
|
365
|
-
**bị từ chối** còn `EXEC` một SP thì chạy. Không kiểm thì không biết `GRANT` đã đúng hay chưa
|
|
257
|
+
- [ ] Gate B: read-only `SELECT` on the **target server** — `sysadmin = 1`, or `CREATE ANY DATABASE` **and** `ALTER ANY LOGIN` = 1
|
|
258
|
+
- [ ] Gate A: `fui project new` ran BEFORE the DB and succeeded — else stop, no DB
|
|
259
|
+
- [ ] `projectData` FLAT, **only 6 fields**; `Framework` agreed with user
|
|
260
|
+
- [ ] Physical folder from `sys.master_files`, not hardcoded; `CREATE DATABASE` `FILENAME` follows it
|
|
261
|
+
- [ ] App account: login = DB name, random password, **only** `GRANT EXECUTE ON SCHEMA::dbo`
|
|
262
|
+
- [ ] Dev account: **shared login reused**, only `CREATE USER` + `db_owner`
|
|
263
|
+
- [ ] `fui db alias new` loaded the **app account**
|
|
264
|
+
- [ ] `fui db add-by-name <apiName>` works
|
|
265
|
+
- [ ] `fui user list` shows exactly the right people
|
|
266
|
+
- [ ] `fui project sync` + `fui use` + **`fui project publish-config`** done
|
|
267
|
+
- [ ] Told the user **what phase 2 is**
|
|
268
|
+
- [ ] **Security check**: as the app account, `SELECT TOP 1 * FROM <any table>` is **denied** and `EXEC` of an SP works — otherwise the `GRANT` is unverified
|
|
366
269
|
|
|
367
270
|
---
|
|
368
271
|
|
|
369
|
-
##
|
|
272
|
+
## Three common misreadings
|
|
370
273
|
|
|
371
|
-
**
|
|
372
|
-
**cấp server và đăng nhập**, chạy qua `db_sql_execute_nonquery({ confirmWrite: true })` như mô tả ở
|
|
373
|
-
trên. Luật *"`CREATE TABLE`/`ALTER TABLE` do lập trình viên tự chạy"* của
|
|
374
|
-
[system-design.md](system-design.md) Bước 2 vẫn nguyên vẹn và chỉ nói về **schema nghiệp vụ** — hai luật
|
|
375
|
-
không mâu thuẫn, chúng nói về hai loại đối tượng khác nhau.
|
|
274
|
+
**Server-level DDL ≠ business-schema DDL.** `CREATE DATABASE` / `CREATE LOGIN` / `GRANT` run via `fui exec "<sql>" --confirm-write`. The _"`CREATE TABLE`/`ALTER TABLE` run by the developer"_ rule ([system-design.md](system-design.md) Step 2) still stands for the **business schema** only — no conflict.
|
|
376
275
|
|
|
377
|
-
**
|
|
378
|
-
tham số tool. Đó là sự thật của quy trình, không giấu được: coi transcript của phiên dựng hạ tầng là
|
|
379
|
-
nhạy cảm. Từ Bước 5 trở đi không tool nào in lại mật khẩu đó nữa (`db_alias_new` và `db_alias_list` đều cố
|
|
380
|
-
ý không in trường `Password`).
|
|
276
|
+
**The app password is in the transcript verbatim** (Step 3 `CREATE LOGIN` goes through the fui command) — treat the provisioning transcript as sensitive. From Step 5 on nothing prints it (`fui db alias new`/`fui db alias list` omit `Password`).
|
|
381
277
|
|
|
382
|
-
|
|
383
|
-
cho một người **không** cho họ quyền gì trong app đang chạy, và ngược lại.
|
|
278
|
+
**Step 6 `UserRight` ≠ `SystemRight` on the business project.** `UserRight=3` grants **nothing** in the running app, and vice versa.
|