@fui-org/fui-cli 0.1.1 → 0.3.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.
Files changed (212) hide show
  1. package/README.md +18 -3
  2. package/dist/fui.js +160 -43
  3. package/package.json +4 -2
  4. package/skills/fui/SKILL.md +131 -66
  5. package/skills/fui-skill/README.md +112 -0
  6. package/skills/fui-skill/SKILL.md +269 -0
  7. package/skills/fui-skill/assets/projectdefaultstyle.css +518 -0
  8. package/skills/fui-skill/design-md/airbnb/DESIGN.md +545 -0
  9. package/skills/fui-skill/design-md/airbnb/README.md +5 -0
  10. package/skills/fui-skill/design-md/airtable/DESIGN.md +554 -0
  11. package/skills/fui-skill/design-md/airtable/README.md +5 -0
  12. package/skills/fui-skill/design-md/apple/DESIGN.md +562 -0
  13. package/skills/fui-skill/design-md/apple/README.md +5 -0
  14. package/skills/fui-skill/design-md/asu/DESIGN.md +179 -0
  15. package/skills/fui-skill/design-md/asu/README.md +107 -0
  16. package/skills/fui-skill/design-md/binance/DESIGN.md +634 -0
  17. package/skills/fui-skill/design-md/binance/README.md +5 -0
  18. package/skills/fui-skill/design-md/bmw/DESIGN.md +544 -0
  19. package/skills/fui-skill/design-md/bmw/README.md +5 -0
  20. package/skills/fui-skill/design-md/bmw-m/DESIGN.md +503 -0
  21. package/skills/fui-skill/design-md/bmw-m/README.md +5 -0
  22. package/skills/fui-skill/design-md/bugatti/DESIGN.md +454 -0
  23. package/skills/fui-skill/design-md/bugatti/README.md +5 -0
  24. package/skills/fui-skill/design-md/cal/DESIGN.md +542 -0
  25. package/skills/fui-skill/design-md/cal/README.md +5 -0
  26. package/skills/fui-skill/design-md/claude/DESIGN.md +589 -0
  27. package/skills/fui-skill/design-md/claude/README.md +5 -0
  28. package/skills/fui-skill/design-md/clay/DESIGN.md +541 -0
  29. package/skills/fui-skill/design-md/clay/README.md +5 -0
  30. package/skills/fui-skill/design-md/clickhouse/DESIGN.md +544 -0
  31. package/skills/fui-skill/design-md/clickhouse/README.md +5 -0
  32. package/skills/fui-skill/design-md/cohere/DESIGN.md +451 -0
  33. package/skills/fui-skill/design-md/cohere/README.md +5 -0
  34. package/skills/fui-skill/design-md/coinbase/DESIGN.md +570 -0
  35. package/skills/fui-skill/design-md/coinbase/README.md +5 -0
  36. package/skills/fui-skill/design-md/composio/DESIGN.md +506 -0
  37. package/skills/fui-skill/design-md/composio/README.md +5 -0
  38. package/skills/fui-skill/design-md/cursor/DESIGN.md +537 -0
  39. package/skills/fui-skill/design-md/cursor/README.md +5 -0
  40. package/skills/fui-skill/design-md/elevenlabs/DESIGN.md +504 -0
  41. package/skills/fui-skill/design-md/elevenlabs/README.md +5 -0
  42. package/skills/fui-skill/design-md/expo/DESIGN.md +526 -0
  43. package/skills/fui-skill/design-md/expo/README.md +5 -0
  44. package/skills/fui-skill/design-md/ferrari/DESIGN.md +531 -0
  45. package/skills/fui-skill/design-md/ferrari/README.md +5 -0
  46. package/skills/fui-skill/design-md/figma/DESIGN.md +578 -0
  47. package/skills/fui-skill/design-md/figma/README.md +5 -0
  48. package/skills/fui-skill/design-md/framer/DESIGN.md +544 -0
  49. package/skills/fui-skill/design-md/framer/README.md +5 -0
  50. package/skills/fui-skill/design-md/fui/DESIGN.md +532 -0
  51. package/skills/fui-skill/design-md/hashicorp/DESIGN.md +575 -0
  52. package/skills/fui-skill/design-md/hashicorp/README.md +5 -0
  53. package/skills/fui-skill/design-md/ibm/DESIGN.md +550 -0
  54. package/skills/fui-skill/design-md/ibm/README.md +5 -0
  55. package/skills/fui-skill/design-md/intercom/DESIGN.md +546 -0
  56. package/skills/fui-skill/design-md/intercom/README.md +5 -0
  57. package/skills/fui-skill/design-md/kraken/DESIGN.md +125 -0
  58. package/skills/fui-skill/design-md/kraken/README.md +5 -0
  59. package/skills/fui-skill/design-md/lamborghini/DESIGN.md +288 -0
  60. package/skills/fui-skill/design-md/lamborghini/README.md +5 -0
  61. package/skills/fui-skill/design-md/linear.app/DESIGN.md +548 -0
  62. package/skills/fui-skill/design-md/linear.app/README.md +5 -0
  63. package/skills/fui-skill/design-md/lovable/DESIGN.md +298 -0
  64. package/skills/fui-skill/design-md/lovable/README.md +5 -0
  65. package/skills/fui-skill/design-md/mastercard/DESIGN.md +365 -0
  66. package/skills/fui-skill/design-md/mastercard/README.md +5 -0
  67. package/skills/fui-skill/design-md/meta/DESIGN.md +683 -0
  68. package/skills/fui-skill/design-md/meta/README.md +5 -0
  69. package/skills/fui-skill/design-md/minimax/DESIGN.md +746 -0
  70. package/skills/fui-skill/design-md/minimax/README.md +5 -0
  71. package/skills/fui-skill/design-md/mintlify/DESIGN.md +852 -0
  72. package/skills/fui-skill/design-md/mintlify/README.md +5 -0
  73. package/skills/fui-skill/design-md/miro/DESIGN.md +825 -0
  74. package/skills/fui-skill/design-md/miro/README.md +5 -0
  75. package/skills/fui-skill/design-md/mistral.ai/DESIGN.md +773 -0
  76. package/skills/fui-skill/design-md/mistral.ai/README.md +5 -0
  77. package/skills/fui-skill/design-md/mongodb/DESIGN.md +767 -0
  78. package/skills/fui-skill/design-md/mongodb/README.md +5 -0
  79. package/skills/fui-skill/design-md/nike/DESIGN.md +575 -0
  80. package/skills/fui-skill/design-md/nike/README.md +5 -0
  81. package/skills/fui-skill/design-md/notion/DESIGN.md +821 -0
  82. package/skills/fui-skill/design-md/notion/README.md +5 -0
  83. package/skills/fui-skill/design-md/nvidia/DESIGN.md +640 -0
  84. package/skills/fui-skill/design-md/nvidia/README.md +5 -0
  85. package/skills/fui-skill/design-md/ollama/DESIGN.md +539 -0
  86. package/skills/fui-skill/design-md/ollama/README.md +5 -0
  87. package/skills/fui-skill/design-md/opencode.ai/DESIGN.md +521 -0
  88. package/skills/fui-skill/design-md/opencode.ai/README.md +5 -0
  89. package/skills/fui-skill/design-md/pinterest/DESIGN.md +597 -0
  90. package/skills/fui-skill/design-md/pinterest/README.md +5 -0
  91. package/skills/fui-skill/design-md/playstation/DESIGN.md +661 -0
  92. package/skills/fui-skill/design-md/playstation/README.md +5 -0
  93. package/skills/fui-skill/design-md/posthog/DESIGN.md +690 -0
  94. package/skills/fui-skill/design-md/posthog/README.md +5 -0
  95. package/skills/fui-skill/design-md/raycast/DESIGN.md +669 -0
  96. package/skills/fui-skill/design-md/raycast/README.md +5 -0
  97. package/skills/fui-skill/design-md/renault/DESIGN.md +589 -0
  98. package/skills/fui-skill/design-md/renault/README.md +5 -0
  99. package/skills/fui-skill/design-md/replicate/DESIGN.md +616 -0
  100. package/skills/fui-skill/design-md/replicate/README.md +5 -0
  101. package/skills/fui-skill/design-md/resend/DESIGN.md +585 -0
  102. package/skills/fui-skill/design-md/resend/README.md +5 -0
  103. package/skills/fui-skill/design-md/revolut/DESIGN.md +636 -0
  104. package/skills/fui-skill/design-md/revolut/README.md +5 -0
  105. package/skills/fui-skill/design-md/runwayml/DESIGN.md +244 -0
  106. package/skills/fui-skill/design-md/runwayml/README.md +5 -0
  107. package/skills/fui-skill/design-md/sanity/DESIGN.md +357 -0
  108. package/skills/fui-skill/design-md/sanity/README.md +5 -0
  109. package/skills/fui-skill/design-md/sentry/DESIGN.md +551 -0
  110. package/skills/fui-skill/design-md/sentry/README.md +5 -0
  111. package/skills/fui-skill/design-md/shopify/DESIGN.md +516 -0
  112. package/skills/fui-skill/design-md/shopify/README.md +5 -0
  113. package/skills/fui-skill/design-md/slack/DESIGN.md +482 -0
  114. package/skills/fui-skill/design-md/spacex/DESIGN.md +363 -0
  115. package/skills/fui-skill/design-md/spacex/README.md +5 -0
  116. package/skills/fui-skill/design-md/spotify/DESIGN.md +246 -0
  117. package/skills/fui-skill/design-md/spotify/README.md +5 -0
  118. package/skills/fui-skill/design-md/starbucks/DESIGN.md +580 -0
  119. package/skills/fui-skill/design-md/starbucks/README.md +5 -0
  120. package/skills/fui-skill/design-md/stripe/DESIGN.md +487 -0
  121. package/skills/fui-skill/design-md/stripe/README.md +5 -0
  122. package/skills/fui-skill/design-md/supabase/DESIGN.md +462 -0
  123. package/skills/fui-skill/design-md/supabase/README.md +5 -0
  124. package/skills/fui-skill/design-md/superhuman/DESIGN.md +448 -0
  125. package/skills/fui-skill/design-md/superhuman/README.md +5 -0
  126. package/skills/fui-skill/design-md/tesla/DESIGN.md +286 -0
  127. package/skills/fui-skill/design-md/tesla/README.md +5 -0
  128. package/skills/fui-skill/design-md/theverge/DESIGN.md +339 -0
  129. package/skills/fui-skill/design-md/theverge/README.md +5 -0
  130. package/skills/fui-skill/design-md/together.ai/DESIGN.md +633 -0
  131. package/skills/fui-skill/design-md/together.ai/README.md +5 -0
  132. package/skills/fui-skill/design-md/uber/DESIGN.md +636 -0
  133. package/skills/fui-skill/design-md/uber/README.md +5 -0
  134. package/skills/fui-skill/design-md/vercel/DESIGN.md +736 -0
  135. package/skills/fui-skill/design-md/vercel/README.md +5 -0
  136. package/skills/fui-skill/design-md/vodafone/DESIGN.md +538 -0
  137. package/skills/fui-skill/design-md/vodafone/README.md +5 -0
  138. package/skills/fui-skill/design-md/voltagent/DESIGN.md +521 -0
  139. package/skills/fui-skill/design-md/voltagent/README.md +5 -0
  140. package/skills/fui-skill/design-md/warp/DESIGN.md +526 -0
  141. package/skills/fui-skill/design-md/warp/README.md +5 -0
  142. package/skills/fui-skill/design-md/webflow/DESIGN.md +588 -0
  143. package/skills/fui-skill/design-md/webflow/README.md +5 -0
  144. package/skills/fui-skill/design-md/wired/DESIGN.md +497 -0
  145. package/skills/fui-skill/design-md/wired/README.md +5 -0
  146. package/skills/fui-skill/design-md/wise/DESIGN.md +544 -0
  147. package/skills/fui-skill/design-md/wise/README.md +5 -0
  148. package/skills/fui-skill/design-md/x.ai/DESIGN.md +465 -0
  149. package/skills/fui-skill/design-md/x.ai/README.md +5 -0
  150. package/skills/fui-skill/design-md/zapier/DESIGN.md +537 -0
  151. package/skills/fui-skill/design-md/zapier/README.md +5 -0
  152. package/skills/fui-skill/examples/component.vue +162 -0
  153. package/skills/fui-skill/examples/f-table-patterns.json +331 -0
  154. package/skills/fui-skill/examples/module-patterns.json +973 -0
  155. package/skills/fui-skill/examples/project-patterns.json +222 -0
  156. package/skills/fui-skill/metadata.json +75 -0
  157. package/skills/fui-skill/references/INDEX.md +144 -0
  158. package/skills/fui-skill/references/advanced-techniques.md +160 -0
  159. package/skills/fui-skill/references/coding-standards.md +112 -0
  160. package/skills/fui-skill/references/component-design.md +455 -0
  161. package/skills/fui-skill/references/component-quickref.md +77 -0
  162. package/skills/fui-skill/references/component-table.md +276 -0
  163. package/skills/fui-skill/references/components-dialog.md +192 -0
  164. package/skills/fui-skill/references/components-display.md +147 -0
  165. package/skills/fui-skill/references/components-echart.md +391 -0
  166. package/skills/fui-skill/references/components-input.md +359 -0
  167. package/skills/fui-skill/references/controls-patterns.md +847 -0
  168. package/skills/fui-skill/references/controls-styling-vocabulary.md +140 -0
  169. package/skills/fui-skill/references/db-table-design.md +77 -0
  170. package/skills/fui-skill/references/db-workflow.md +504 -0
  171. package/skills/fui-skill/references/default-function.md +415 -0
  172. package/skills/fui-skill/references/design-modes.md +85 -0
  173. package/skills/fui-skill/references/echart-templates.md +481 -0
  174. package/skills/fui-skill/references/fastproject.md +97 -0
  175. package/skills/fui-skill/references/fsheet.md +218 -0
  176. package/skills/fui-skill/references/fullstack-workflow.md +351 -0
  177. package/skills/fui-skill/references/module-data-patterns.md +126 -0
  178. package/skills/fui-skill/references/module-json-anatomy.md +137 -0
  179. package/skills/fui-skill/references/module-structure.md +260 -0
  180. package/skills/fui-skill/references/new-session.md +108 -0
  181. package/skills/fui-skill/references/pdfmake.md +60 -0
  182. package/skills/fui-skill/references/permission-system.md +169 -0
  183. package/skills/fui-skill/references/platform-architecture.md +294 -0
  184. package/skills/fui-skill/references/project-config.md +335 -0
  185. package/skills/fui-skill/references/project-provisioning.md +383 -0
  186. package/skills/fui-skill/references/script-map.md +296 -0
  187. package/skills/fui-skill/references/sql-clr-functions.md +224 -0
  188. package/skills/fui-skill/references/system-design.md +116 -0
  189. package/skills/fui-skill/references/tapi-file-api.md +191 -0
  190. package/skills/fui-skill/references/tapi-permission-patterns.md +158 -0
  191. package/skills/fui-skill/references/tapi-reference.md +549 -0
  192. package/skills/fui-skill/references/tools-registry.md +460 -0
  193. package/skills/fui-skill/references/ui-crosswindow-patterns.md +317 -0
  194. package/skills/fui-skill/references/ui-dialog-patterns.md +229 -0
  195. package/skills/fui-skill/references/ui-layout-patterns.md +176 -0
  196. package/skills/fui-skill/references/ui-patterns.md +315 -0
  197. package/skills/fui-skill/references/ui-screenshot-review.md +94 -0
  198. package/skills/fui-skill/references/ui-table-cell-patterns.md +316 -0
  199. package/skills/fui-skill/references/ui-templates.md +29 -0
  200. package/skills/fui-skill/references/verification.md +246 -0
  201. package/skills/fui-skill/references/watcher-patterns.md +196 -0
  202. package/skills/fui-skill/references/websocket-realtime.md +254 -0
  203. package/skills/fui-skill/scripts/component-3.0.js +2549 -0
  204. package/skills/fui-skill/scripts/component.js +3142 -0
  205. package/skills/fui-skill/scripts/componentTable-3.0.js +909 -0
  206. package/skills/fui-skill/scripts/componentTable.js +769 -0
  207. package/skills/fui-skill/scripts/defaultfunction-3.0.js +781 -0
  208. package/skills/fui-skill/scripts/defaultfunction.js +966 -0
  209. package/skills/fui-skill/scripts/fastproject-3.0.js +870 -0
  210. package/skills/fui-skill/scripts/fastproject.js +828 -0
  211. package/skills/fui-skill/scripts/fechart.js +890 -0
  212. package/skills/fui-skill/scripts/fsheet.js +1330 -0
@@ -0,0 +1,191 @@
1
+ # tAPI — File API (GET / UPLOAD)
2
+
3
+ > File này sở hữu: **API file qua SP: `spAPIFILE_*`, `tblFileData`, alias `fileContent`, `@sys_FileContent`/`@sys_FileName`**.
4
+
5
+ SP GET và UPLOAD file qua tAPI: prefix `spAPIFILE_`, cột binary alias `fileContent`, params `@sys_FileContent`/`@sys_FileName`, bảng chuẩn `tblFileData`. Load file này khi module cần upload/download/xem file. **Không tự suy từ training data** — tAPI có quy ước riêng.
6
+
7
+ > Nền tảng SP (naming, params, response): xem [tapi-reference.md](tapi-reference.md).
8
+
9
+ ---
10
+
11
+ ## GET file
12
+
13
+ SP phải SELECT **tối thiểu 3 cột bắt buộc** (có thể thêm cột metadata tùy ý):
14
+
15
+ | Cột | Bắt buộc | Ý nghĩa |
16
+ |---|---|---|
17
+ | `FileName` | ✅ | Tên file trả về — có thể là biểu thức, ví dụ `FileName + FileType` |
18
+ | `ContentType` | ✅ | MIME type (vd: `application/pdf`, `image/png`) |
19
+ | `fileContent` | ✅ | Binary content — alias từ cột kiểu **`image` hoặc `varbinary`**. tAPI nhận diện đây là nội dung file cần stream qua kiểu dữ liệu này |
20
+ | cột khác | ❌ | Metadata tùy chọn, ví dụ `Modified`, `FileSize` — phải là kiểu thông thường (không phải binary) |
21
+
22
+ ```sql
23
+ -- Ví dụ thực tế: FileName ghép đuôi, thêm cột Modified, binary aliased từ FileContentBIN
24
+ CREATE PROCEDURE spAPIFILE_moduleImportFile
25
+ @fileID varchar(50)
26
+ AS BEGIN
27
+ SELECT
28
+ FileName = FileName + FileType,
29
+ ContentType,
30
+ Modified = ISNULL(UpdateTime, CreateTime),
31
+ fileContent = FileContentBIN
32
+ FROM tblA_ImportFile
33
+ WHERE fileID = LEFT(@fileID, 32)
34
+ END
35
+ ```
36
+
37
+ > `fileContent` phải alias từ cột kiểu `image` hoặc `varbinary(max)` — tAPI dùng kiểu dữ liệu này để nhận biết và stream nội dung file. Tên cột trong bảng tùy ý (`FileContentBIN`, `BinaryContent`, ...).
38
+ > `FileName` nên bao gồm cả phần đuôi file (`.pdf`, `.xlsx`...) để browser nhận đúng kiểu.
39
+
40
+ **Tham số URL — `@fileID` và `@filename`:**
41
+
42
+ | Param | Bắt buộc | Nguồn | Ý nghĩa |
43
+ |---|---|---|---|
44
+ | `@fileID varchar(...)` | ✅ | Segment đầu tiên sau FunctionName | ID của file cần lấy |
45
+ | `@filename varchar(...)` | ❌ | Segment CUỐI cùng trong URL | Phần tên file hiển thị trong URL (browser/download manager dùng để đặt tên khi tải) |
46
+
47
+ Ngoài hai tham số trên, có thể khai báo thêm `@sys_*` auth params nếu cần kiểm tra quyền.
48
+
49
+ ```sql
50
+ CREATE PROCEDURE spAPIFILE_Document
51
+ @fileID varchar(50), -- bắt buộc, inject từ URL
52
+ @filename varchar(200), -- tùy chọn — inject từ segment cuối URL; SP có thể dùng để
53
+ -- ghi log, kiểm tra, hoặc override FileName trả về
54
+ @sys_UserID varchar(9) -- tùy chọn, inject từ token
55
+ AS BEGIN
56
+ ...
57
+ END
58
+ ```
59
+
60
+ **4 route pattern hỗ trợ:**
61
+
62
+ ```
63
+ {domain}/{apiName}/{FunctionName}/{fileID}
64
+ {domain}/{apiName}/{FunctionName}/{fileID}/{filename}
65
+ {domain}/{apiName}/download/{FunctionName}/{fileID}/{filename}
66
+ {domain}/{apiName}/viewer/{FunctionName}/{fileID}/{filename}
67
+ ```
68
+
69
+ `{FunctionName}` là phần tên sau prefix `spAPIFILE_`. Ví dụ SP `spAPIFILE_Document` → URL dùng `Document`.
70
+
71
+ Route `/viewer/` dùng để xem trực tiếp trong browser (inline), `/download/` để tải về.
72
+
73
+ > **Lưu ý `@filename`:** Segment này trong URL thường là tên file gốc (ví dụ `BaoCao_2024.pdf`) — browser và download manager dùng nó để đặt tên file khi tải về, không nhất thiết phải khớp với `FileName` trong bảng DB. SP không khai báo `@filename` thì tAPI vẫn nhận route có segment đó — param đơn thuần bị bỏ qua.
74
+
75
+ ## Upload file
76
+
77
+ **Params đặc biệt do tAPI tự inject khi upload:**
78
+
79
+ | Param | Kiểu | Mô tả |
80
+ |---|---|---|
81
+ | `@sys_FileContent` | varbinary(max) | Binary content của file |
82
+ | `@sys_FileName` | nvarchar(200) | Tên file gốc |
83
+ | `@sys_FileContentType` | varchar(100) | MIME type |
84
+ | `@sys_FileSize` | int | Kích thước file (bytes) |
85
+ | `@sys_UploadData` | nvarchar(max) | JSON data bổ sung truyền qua header |
86
+
87
+ Ngoài ra toàn bộ `@sys_` auth params cũng available: `@sys_UserID`, `@sys_UserName`, `@sys_SessionID`, `@sys_GroupID`, `@sys_DepartmentID`, `@sys_SystemRight`, `@sys_FunctionRight`.
88
+
89
+ ```sql
90
+ CREATE PROCEDURE spAPIFILE_UPLOAD_Attachment
91
+ @url1_SessionID varchar(36),
92
+ @url2_Mode varchar(20),
93
+ @sys_UserID varchar(9),
94
+ @sys_FileContent varbinary(max),
95
+ @sys_FileName nvarchar(200),
96
+ @sys_FileContentType varchar(100),
97
+ @sys_FileSize int
98
+ AS BEGIN
99
+ INSERT INTO tblAttachFiles(FileName, Capacity, SessionID, CreateUser)
100
+ VALUES(@sys_FileName, @sys_FileSize, @url1_SessionID, @sys_UserID)
101
+ END
102
+ ```
103
+
104
+ Route: `POST {domain}/{apiName}/upload/{spName}/{url1}/{url2}...`
105
+
106
+ ## Bảng lưu trữ file chuẩn — `tblFileData`
107
+
108
+ Đây là cấu trúc bảng chuẩn để dùng chung với cả `spAPIFILE_` (GET) và `spAPIFILE_UPLOAD_` (POST). Khi thiết kế module có file, tạo bảng này (hoặc bảng tương tự) trước khi viết SP.
109
+
110
+ ```sql
111
+ CREATE TABLE [dbo].[tblFileData](
112
+ [FileID] [char](36) NOT NULL, -- UUID, DEFAULT newid()
113
+ [FileName] [nvarchar](200) NOT NULL,
114
+ [PhysicalName] [char](36) NOT NULL, -- UUID, DEFAULT newid()
115
+ [PhysicalSegment] [char](10) NOT NULL, -- subfolder theo ngày, DEFAULT getPhysicalSegment(getdate())
116
+ [CreateTime] [datetime] NOT NULL, -- DEFAULT getdate()
117
+ [WriteToDisk] [datetime] NULL, -- null = chưa ghi ra disk
118
+ [BinaryContent] [image] NULL, -- binary file content — alias là fileContent trong SP GET
119
+ [ContentType] [varchar](100) NULL, -- MIME type, DEFAULT ''
120
+ [Size] [int] NULL,
121
+ CONSTRAINT [PK_tblFileData] PRIMARY KEY CLUSTERED ([FileID] ASC)
122
+ ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
123
+ GO
124
+
125
+ ALTER TABLE [dbo].[tblFileData] ADD CONSTRAINT [DF_tblFileData_FileID] DEFAULT (newid()) FOR [FileID]
126
+ ALTER TABLE [dbo].[tblFileData] ADD CONSTRAINT [DF_tblFileData_PhysicalName] DEFAULT (newid()) FOR [PhysicalName]
127
+ ALTER TABLE [dbo].[tblFileData] ADD CONSTRAINT [DF_tblFileData_PhysicalSegment] DEFAULT ([dbo].[getPhysicalSegment](getdate())) FOR [PhysicalSegment]
128
+ ALTER TABLE [dbo].[tblFileData] ADD CONSTRAINT [DF_tblFileData_CreateTime] DEFAULT (getdate()) FOR [CreateTime]
129
+ ALTER TABLE [dbo].[tblFileData] ADD CONSTRAINT [DF_tblFileData_ContentType] DEFAULT ('') FOR [ContentType]
130
+ ```
131
+
132
+ > **Lưu ý về DDL:** các câu `ALTER TABLE ... ADD CONSTRAINT` ở trên **chạy được qua tool** (ADD là thao tác cộng thêm). Riêng `CREATE TABLE` thì không — MCP chặn, phải do lập trình viên tự chạy. Đây là tài liệu tham chiếu cấu trúc.
133
+
134
+ **Giải thích từng field:**
135
+
136
+ | Field | Kiểu | Mô tả |
137
+ |---|---|---|
138
+ | `FileID` | char(36) PK | UUID tự sinh bằng `newid()` — dùng làm key trong URL |
139
+ | `FileName` | nvarchar(200) | Tên file gốc khi upload |
140
+ | `PhysicalName` | char(36) | UUID tự sinh — tên file thực tế lưu trên disk (tránh trùng tên) |
141
+ | `PhysicalSegment` | char(10) | Subfolder phân tán theo ngày từ hàm `getPhysicalSegment(date)` |
142
+ | `CreateTime` | datetime | Thời điểm tạo record, DEFAULT getdate() |
143
+ | `WriteToDisk` | datetime NULL | Khi nào binary được ghi ra disk; `NULL` = chỉ lưu DB, chưa ra file system |
144
+ | `BinaryContent` | image NULL | Nội dung binary của file — SP GET phải alias là `fileContent` |
145
+ | `ContentType` | varchar(100) | MIME type, ví dụ `application/pdf`, `image/png` |
146
+ | `Size` | int NULL | Kích thước bytes |
147
+
148
+ **SP GET file — map tới bảng:**
149
+
150
+ ```sql
151
+ CREATE PROCEDURE spAPIFILE_Document
152
+ @FileID char(36),
153
+ @sys_UserID varchar(9),
154
+ @sys_SystemRight int
155
+ AS BEGIN
156
+ IF @sys_SystemRight < 1
157
+ BEGIN RAISERROR(N'[Unauthorized]Bạn không có quyền.', 16, 1) RETURN END
158
+
159
+ -- BinaryContent phải alias là fileContent — tAPI đọc đúng tên này
160
+ SELECT FileName, ContentType, fileContent = BinaryContent
161
+ FROM tblFileData WHERE FileID = @FileID
162
+ END
163
+ ```
164
+
165
+ **SP UPLOAD — lưu vào bảng:**
166
+
167
+ ```sql
168
+ CREATE PROCEDURE spAPIFILE_UPLOAD_Document
169
+ @url1_RefID varchar(50),
170
+ @sys_UserID varchar(9),
171
+ @sys_SystemRight int,
172
+ @sys_FileContent varbinary(max),
173
+ @sys_FileName nvarchar(200),
174
+ @sys_FileContentType varchar(100),
175
+ @sys_FileSize int
176
+ AS BEGIN
177
+ IF @sys_SystemRight < 2
178
+ BEGIN RAISERROR(N'[Unauthorized]Bạn không có quyền.', 16, 1) RETURN END
179
+
180
+ DECLARE @NewFileID char(36) = newid() -- sinh UUID trước, dùng để SELECT lại sau
181
+
182
+ INSERT INTO tblFileData(FileID, FileName, BinaryContent, ContentType, Size)
183
+ VALUES(@NewFileID, @sys_FileName, @sys_FileContent, @sys_FileContentType, @sys_FileSize)
184
+
185
+ -- Trả về record vừa insert để client cập nhật danh sách
186
+ SELECT FileID, FileName, Size, ContentType, CreateTime
187
+ FROM tblFileData WHERE FileID = @NewFileID
188
+ END
189
+ ```
190
+
191
+ > **Lưu ý `BinaryContent [image]`**: Kiểu `image` là legacy của SQL Server nhưng vẫn hoạt động tốt với tAPI. Nếu muốn dùng kiểu mới hơn có thể dùng `varbinary(max)` — cả hai đều map được vào `fileContent` alias.
@@ -0,0 +1,158 @@
1
+ # tAPI — Kiểm tra quyền người dùng (Permission Check Patterns)
2
+
3
+ > File này sở hữu: **5 pattern kiểm tra quyền trong thân SP (`@sys_SystemRight`, `getSystemRight`, RAISERROR)**. Khái niệm quyền xem [permission-system.md](permission-system.md).
4
+
5
+ Các pattern kiểm tra quyền trong thân Stored Procedure tAPI. Load file này khi SP cần phân quyền.
6
+
7
+ > Nền tảng SP (naming, params, response, RAISERROR): xem [tapi-reference.md](tapi-reference.md).
8
+ > Khái niệm `SystemRight`/`FunctionRight`, cấu trúc `tblSysRight`/`tblFunction`, và 4 tool quản lý định nghĩa quyền: xem [permission-system.md](permission-system.md).
9
+
10
+ ---
11
+
12
+ ## Tham số hệ thống liên quan đến quyền
13
+
14
+ tAPI tự inject các tham số sau — không cần client truyền lên:
15
+
16
+ | Tham số | Kiểu | Mô tả |
17
+ |---|---|---|
18
+ | `@sys_UserID` | varchar(9) | Mã người dùng đang đăng nhập |
19
+ | `@sys_SystemRight` | int | Mức quyền của user trên module hiện tại |
20
+ | `@sys_FunctionRight` | varchar(2000) | Quyền chức năng dạng `[AD][RPT][MGR]` |
21
+
22
+ **Khai báo trong SP** — luôn đặt cuối danh sách tham số, **không được gán default cho bất kỳ tham số nào, kể cả `@sys_*`** (xem [tapi-reference.md](tapi-reference.md) §2 — tAPI luôn truyền đủ mọi tham số, thiếu thì truyền `NULL`, nên `DEFAULT` không bao giờ được dùng tới; `db_sp_deploy` chặn cứng nếu có):
23
+
24
+ ```sql
25
+ CREATE PROCEDURE spAPI_EntityAction
26
+ @BusinessParam1 int,
27
+ @BusinessParam2 nvarchar(100),
28
+ @sys_UserID varchar(9),
29
+ @sys_SystemRight int
30
+ AS
31
+ ```
32
+
33
+ ## Các mức `@sys_SystemRight`
34
+
35
+ Ý nghĩa từng mức **do mỗi project tự định nghĩa** (`tblSysRight.Note`, quản lý qua `right_system_list`/`right_system_update` — xem [permission-system.md](permission-system.md)). Bảng dưới là quy ước phổ biến dùng khi viết pattern kiểm tra trong SP — không phải giá trị cố định của platform, ngoại trừ `9` luôn là Project Admin:
36
+
37
+ | Giá trị | Ý nghĩa thực tế (quy ước phổ biến) |
38
+ |---|---|
39
+ | `0` | Không có quyền / chưa được cấp quyền trên module |
40
+ | `1` | Quyền xem cơ bản |
41
+ | `2` | Quyền thao tác chuẩn (đọc, thêm, sửa thông thường) |
42
+ | `3` | Quyền nâng cao (quản lý nội bộ, thao tác nhạy cảm) |
43
+ | `9` | Module Admin / Project Admin (cố định trên toàn platform) |
44
+
45
+ ## Helper function kiểm tra quyền theo module cụ thể
46
+
47
+ ```sql
48
+ dbo.getSystemRight(@ModuleID, @sys_UserID)
49
+ ```
50
+
51
+ Trả về mức `SysRight` mà user được assign cho một module xác định — dùng khi cần kiểm tra quyền trên module **khác** với module hiện tại.
52
+
53
+ ---
54
+
55
+ ## Pattern 1 — Chặn truy cập cơ bản (READ operations)
56
+
57
+ Dùng cho mọi SP đọc dữ liệu cần đăng nhập. Yêu cầu ít nhất `SysRight = 2`.
58
+
59
+ ```sql
60
+ If @sys_SystemRight < 2
61
+ Begin
62
+ Raiserror(N'[Unauthorized]Bạn không có quyền trên chức năng này.', 16, 1)
63
+ Return
64
+ End
65
+ ```
66
+
67
+ ## Pattern 2 — Chặn user hoàn toàn không có quyền (minimal check)
68
+
69
+ Dùng khi muốn cho phép cả `SysRight = 1` thao tác, chỉ chặn `SysRight = 0`.
70
+
71
+ ```sql
72
+ If @sys_SystemRight = 0
73
+ Begin
74
+ Raiserror(N'[Unauthorized]Bạn không có quyền trên chức năng này.', 16, 1)
75
+ Return
76
+ End
77
+ ```
78
+
79
+ ## Pattern 3 — Kiểm tra 2 tầng: global + module admin (WRITE operations)
80
+
81
+ Dùng cho các thao tác ghi có tác động đến cấu hình module hoặc dữ liệu người dùng khác. User phải đạt **một trong hai điều kiện**:
82
+ - `@sys_SystemRight >= 3` (quyền cao toàn hệ thống), **hoặc**
83
+ - Là Module Admin (`getSystemRight >= 9`) của module đó.
84
+
85
+ ```sql
86
+ -- Tầng 1: phải có quyền cơ bản
87
+ If @sys_SystemRight < 2
88
+ Begin
89
+ Raiserror(N'[Unauthorized]Bạn không có quyền trên chức năng này.', 16, 1)
90
+ Return
91
+ End
92
+
93
+ -- Tầng 2: phải là admin hệ thống hoặc admin của module đó
94
+ If @sys_SystemRight < 3 and dbo.getSystemRight(@ModuleID, @sys_UserID) < 9
95
+ Begin
96
+ Raiserror(N'[Unauthorized]Bạn không có quyền trên Module này.', 16, 1)
97
+ Return
98
+ End
99
+ ```
100
+
101
+ ## Pattern 4 — Kiểm tra logic nghiệp vụ trước khi thực thi
102
+
103
+ Dùng khi thao tác hợp lệ về quyền nhưng vi phạm ràng buộc dữ liệu (ví dụ: xóa cha khi còn con).
104
+
105
+ ```sql
106
+ -- Kiểm tra ràng buộc trước khi xóa
107
+ If exists(Select * from tblChild WHERE ParentID = @ParentID)
108
+ Begin
109
+ Raiserror(N'Phải xóa dữ liệu liên quan trước khi thực hiện thao tác này.', 16, 1)
110
+ Return
111
+ End
112
+
113
+ DELETE tblParent WHERE ParentID = @ParentID
114
+ ```
115
+
116
+ ## Pattern 5 — Kiểm tra `@sys_FunctionRight`
117
+
118
+ Dùng khi phân quyền theo chức năng cụ thể (không chỉ theo mức số).
119
+
120
+ ```sql
121
+ If CHARINDEX('[ADMIN]', @sys_FunctionRight) = 0
122
+ Begin
123
+ Raiserror(N'[Unauthorized]Bạn không có quyền thực hiện chức năng này.', 16, 1)
124
+ Return
125
+ End
126
+ ```
127
+
128
+ ---
129
+
130
+ ## Quy tắc đặt thứ tự kiểm tra
131
+
132
+ ```
133
+ 1. Kiểm tra quyền hệ thống (@sys_SystemRight) ← luôn đầu tiên
134
+ 2. Kiểm tra quyền module (getSystemRight) ← nếu cần 2 tầng
135
+ 3. Kiểm tra quyền chức năng (@sys_FunctionRight) ← nếu dùng FunctionRight
136
+ 4. Kiểm tra ràng buộc nghiệp vụ ← sau cùng, trước khi ghi
137
+ ```
138
+
139
+ ## Quy ước thông báo lỗi
140
+
141
+ | Tình huống | Message chuẩn |
142
+ |---|---|
143
+ | Thiếu quyền global | `N'[Unauthorized]Bạn không có quyền trên chức năng này.'` |
144
+ | Thiếu quyền module | `N'[Unauthorized]Bạn không có quyền trên Module này.'` |
145
+ | Thiếu quyền chức năng (`FunctionRight`) | `N'[Unauthorized]Bạn không có quyền thực hiện chức năng này.'` |
146
+ | Vi phạm ràng buộc | Mô tả cụ thể, **không** có prefix: `N'Phải xóa X trước khi xóa Y.'` |
147
+ | Dữ liệu không hợp lệ | `N'Dữ liệu không hợp lệ.'` hoặc mô tả cụ thể, **không** có prefix |
148
+
149
+ **Format `RAISERROR` bắt buộc:**
150
+ ```sql
151
+ RAISERROR(N'Thông báo lỗi tiếng Việt.', 16, 1)
152
+ RETURN
153
+ ```
154
+ - **Severity luôn là `16`** — áp dụng cho mọi loại lỗi (validation, unauthorized, business logic)
155
+ - Prefix `N` bắt buộc cho Unicode tiếng Việt
156
+ - `RETURN` bắt buộc ngay sau `RAISERROR` — thiếu `RETURN` SP tiếp tục chạy dù đã báo lỗi
157
+ - Client nhận `{ "Message": "..." }` với nội dung thông báo
158
+ - **Mọi lỗi thiếu quyền ở 5 pattern trên phải mở message bằng `[Unauthorized]`** (vd `N'[Unauthorized]Bạn không có quyền...'`) — tAPI dựa vào tiền tố này để trả HTTP status `401` thay vì mặc định, và tự cắt `[Unauthorized]` khỏi `Message` trước khi trả về client. Lỗi ràng buộc/nghiệp vụ (Pattern 4) **không** dùng prefix này — chi tiết cơ chế + cách client xử lý status 401 xem [tapi-reference.md](tapi-reference.md) §5.