@chill-sharp/ui-core 1.1.12
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/.agents/skills/chillsharp-current-user-preferences/SKILL.md +70 -0
- package/.agents/skills/chillsharp-ui-template/SKILL.md +18 -0
- package/README.md +103 -0
- package/chill-sharp-ui-core.d.ts.map +1 -0
- package/doc/AIAssistedDevelopment/README.md +185 -0
- package/doc/AttachmentModel/README.md +173 -0
- package/doc/AuthenticationModel/README.md +213 -0
- package/doc/AuthenticationModel/how-to-integreate-auth-minimal-api.md +293 -0
- package/doc/ChillSharpClient.md +464 -0
- package/doc/ClientGeneration/README.md +172 -0
- package/doc/ComplianceGuide/README.md +178 -0
- package/doc/Configuration/README.md +94 -0
- package/doc/CurrentUserPreferences.md +114 -0
- package/doc/DateTimePolicy/README.md +154 -0
- package/doc/DateTimeSerialization.md +423 -0
- package/doc/Endpoints.md +260 -0
- package/doc/HowTo/01-simple-blog-sqlite.md +153 -0
- package/doc/HowTo/02-blog-schema-labels.md +140 -0
- package/doc/HowTo/03-authentication.md +218 -0
- package/doc/HowTo/04-blog-posts-one-to-many.md +194 -0
- package/doc/HowTo/05-docker-env-variables.md +274 -0
- package/doc/HowTo/06-chunk-transactions-autocomplete.md +196 -0
- package/doc/Mcp/ChatGPT.md +291 -0
- package/doc/Mcp/README.md +799 -0
- package/doc/MenuGuide/README.md +49 -0
- package/doc/ModelPreparation.md +255 -0
- package/doc/PermissionModel/README.md +277 -0
- package/doc/README.md +228 -0
- package/doc/ReferenceExistence.md +130 -0
- package/doc/RegisterContext.md +217 -0
- package/doc/UiCore/CRUD.md +170 -0
- package/doc/UiCore/README.md +13 -0
- package/doc/ValidationModel/README.md +117 -0
- package/doc/it/AIAssistedDevelopment/README.md +185 -0
- package/doc/it/AttachmentModel/README.md +173 -0
- package/doc/it/AuthenticationModel/README.md +171 -0
- package/doc/it/AuthenticationModel/how-to-integreate-auth-minimal-api.md +292 -0
- package/doc/it/ChillSharpClient.md +464 -0
- package/doc/it/ClientGeneration/README.md +152 -0
- package/doc/it/ComplianceGuide/README.md +178 -0
- package/doc/it/Configuration/README.md +94 -0
- package/doc/it/CurrentUserPreferences.md +114 -0
- package/doc/it/DateTimePolicy/README.md +154 -0
- package/doc/it/DateTimeSerialization.md +423 -0
- package/doc/it/Endpoints.md +260 -0
- package/doc/it/HowTo/01-simple-blog-sqlite.md +152 -0
- package/doc/it/HowTo/02-blog-schema-labels.md +139 -0
- package/doc/it/HowTo/03-authentication.md +221 -0
- package/doc/it/HowTo/04-blog-posts-one-to-many.md +193 -0
- package/doc/it/HowTo/05-docker-env-variables.md +268 -0
- package/doc/it/HowTo/06-chunk-transactions-autocomplete.md +196 -0
- package/doc/it/Mcp/ChatGPT.md +291 -0
- package/doc/it/Mcp/README.md +799 -0
- package/doc/it/MenuGuide/README.md +49 -0
- package/doc/it/ModelPreparation.md +254 -0
- package/doc/it/PermissionModel/README.md +190 -0
- package/doc/it/README.md +172 -0
- package/doc/it/ReferenceExistence.md +130 -0
- package/doc/it/RegisterContext.md +218 -0
- package/doc/it/UiCore/CRUD.md +170 -0
- package/doc/it/UiCore/README.md +13 -0
- package/doc/it/ValidationModel/README.md +117 -0
- package/fesm2022/chill-sharp-ui-core.mjs +16725 -0
- package/fesm2022/chill-sharp-ui-core.mjs.map +1 -0
- package/index.d.ts +6 -0
- package/lib/chill-sharp-ui-root.component.d.ts +6 -0
- package/lib/chill-sharp-ui-root.component.d.ts.map +1 -0
- package/lib/chill-sharp-ui.routes.d.ts +3 -0
- package/lib/chill-sharp-ui.routes.d.ts.map +1 -0
- package/lib/chill.config.d.ts +5 -0
- package/lib/chill.config.d.ts.map +1 -0
- package/lib/layouts/auth-shell.component.d.ts +8 -0
- package/lib/layouts/auth-shell.component.d.ts.map +1 -0
- package/lib/layouts/workspace-page.component.d.ts +49 -0
- package/lib/layouts/workspace-page.component.d.ts.map +1 -0
- package/lib/lib/chill-form.component.d.ts +151 -0
- package/lib/lib/chill-form.component.d.ts.map +1 -0
- package/lib/lib/chill-i18n-button-label.component.d.ts +27 -0
- package/lib/lib/chill-i18n-button-label.component.d.ts.map +1 -0
- package/lib/lib/chill-i18n-label.component.d.ts +30 -0
- package/lib/lib/chill-i18n-label.component.d.ts.map +1 -0
- package/lib/lib/chill-json-input.component.d.ts +31 -0
- package/lib/lib/chill-json-input.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-boolean-control.component.d.ts +12 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-boolean-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-editor-control.component.d.ts +17 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-editor-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-lookup-control.component.d.ts +45 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-lookup-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-scalar-control.component.d.ts +19 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-scalar-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-select-control.component.d.ts +12 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-select-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-textarea-control.component.d.ts +13 -0
- package/lib/lib/chill-polymorphic-input-controls/chill-polymorphic-textarea-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-input.component.d.ts +452 -0
- package/lib/lib/chill-polymorphic-input.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-boolean-control.component.d.ts +7 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-boolean-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-lookup-control.component.d.ts +7 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-lookup-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-number-control.component.d.ts +7 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-number-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-temporal-control.component.d.ts +8 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-temporal-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-value-control.component.d.ts +7 -0
- package/lib/lib/chill-polymorphic-output-controls/chill-polymorphic-output-value-control.component.d.ts.map +1 -0
- package/lib/lib/chill-polymorphic-output.component.d.ts +75 -0
- package/lib/lib/chill-polymorphic-output.component.d.ts.map +1 -0
- package/lib/lib/chill-table.component.d.ts +434 -0
- package/lib/lib/chill-table.component.d.ts.map +1 -0
- package/lib/lib/chill-text-editor-dialog.component.d.ts +14 -0
- package/lib/lib/chill-text-editor-dialog.component.d.ts.map +1 -0
- package/lib/lib/crud-configuration.utils.d.ts +4 -0
- package/lib/lib/crud-configuration.utils.d.ts.map +1 -0
- package/lib/lib/culture-name-options.d.ts +3 -0
- package/lib/lib/culture-name-options.d.ts.map +1 -0
- package/lib/lib/date-format-options.d.ts +3 -0
- package/lib/lib/date-format-options.d.ts.map +1 -0
- package/lib/lib/iana-time-zone-options.d.ts +3 -0
- package/lib/lib/iana-time-zone-options.d.ts.map +1 -0
- package/lib/lib/notice-transition.directive.d.ts +17 -0
- package/lib/lib/notice-transition.directive.d.ts.map +1 -0
- package/lib/lib/schema-property-dialog.component.d.ts +74 -0
- package/lib/lib/schema-property-dialog.component.d.ts.map +1 -0
- package/lib/models/chill-auth.models.d.ts +176 -0
- package/lib/models/chill-auth.models.d.ts.map +1 -0
- package/lib/models/chill-menu.models.d.ts +12 -0
- package/lib/models/chill-menu.models.d.ts.map +1 -0
- package/lib/models/chill-schema.models.d.ts +141 -0
- package/lib/models/chill-schema.models.d.ts.map +1 -0
- package/lib/models/workspace-dialog.models.d.ts +16 -0
- package/lib/models/workspace-dialog.models.d.ts.map +1 -0
- package/lib/models/workspace-task.models.d.ts +36 -0
- package/lib/models/workspace-task.models.d.ts.map +1 -0
- package/lib/pages/confirm-reset-page.component.d.ts +21 -0
- package/lib/pages/confirm-reset-page.component.d.ts.map +1 -0
- package/lib/pages/crud/attachment-upload-dialog.component.d.ts +24 -0
- package/lib/pages/crud/attachment-upload-dialog.component.d.ts.map +1 -0
- package/lib/pages/crud/crud-page.component.d.ts +244 -0
- package/lib/pages/crud/crud-page.component.d.ts.map +1 -0
- package/lib/pages/login-page.component.d.ts +21 -0
- package/lib/pages/login-page.component.d.ts.map +1 -0
- package/lib/pages/permissions/auth-role-dialog.component.d.ts +29 -0
- package/lib/pages/permissions/auth-role-dialog.component.d.ts.map +1 -0
- package/lib/pages/permissions/auth-search-select.component.d.ts +28 -0
- package/lib/pages/permissions/auth-search-select.component.d.ts.map +1 -0
- package/lib/pages/permissions/auth-user-dialog.component.d.ts +35 -0
- package/lib/pages/permissions/auth-user-dialog.component.d.ts.map +1 -0
- package/lib/pages/permissions/permission-editor.component.d.ts +55 -0
- package/lib/pages/permissions/permission-editor.component.d.ts.map +1 -0
- package/lib/pages/permissions/permissions-page.component.d.ts +38 -0
- package/lib/pages/permissions/permissions-page.component.d.ts.map +1 -0
- package/lib/pages/permissions/role-permission.component.d.ts +43 -0
- package/lib/pages/permissions/role-permission.component.d.ts.map +1 -0
- package/lib/pages/permissions/user-permission.component.d.ts +43 -0
- package/lib/pages/permissions/user-permission.component.d.ts.map +1 -0
- package/lib/pages/register-page.component.d.ts +24 -0
- package/lib/pages/register-page.component.d.ts.map +1 -0
- package/lib/pages/reset-password-page.component.d.ts +18 -0
- package/lib/pages/reset-password-page.component.d.ts.map +1 -0
- package/lib/provide-chill-sharp-ui-core.d.ts +8 -0
- package/lib/provide-chill-sharp-ui-core.d.ts.map +1 -0
- package/lib/services/chill.service.d.ts +249 -0
- package/lib/services/chill.service.d.ts.map +1 -0
- package/lib/services/workspace-dialog.service.d.ts +22 -0
- package/lib/services/workspace-dialog.service.d.ts.map +1 -0
- package/lib/services/workspace-layout.service.d.ts +13 -0
- package/lib/services/workspace-layout.service.d.ts.map +1 -0
- package/lib/services/workspace-task-registry.service.d.ts +35 -0
- package/lib/services/workspace-task-registry.service.d.ts.map +1 -0
- package/lib/services/workspace-toolbar.service.d.ts +23 -0
- package/lib/services/workspace-toolbar.service.d.ts.map +1 -0
- package/lib/services/workspace.service.d.ts +114 -0
- package/lib/services/workspace.service.d.ts.map +1 -0
- package/lib/storage-keys.d.ts +5 -0
- package/lib/storage-keys.d.ts.map +1 -0
- package/lib/tasks/crud-task/crud-task.component.d.ts +33 -0
- package/lib/tasks/crud-task/crud-task.component.d.ts.map +1 -0
- package/lib/tasks/goto-url-task/goto-url-task.component.d.ts +31 -0
- package/lib/tasks/goto-url-task/goto-url-task.component.d.ts.map +1 -0
- package/lib/workspace/confirm-message-dialog.component.d.ts +16 -0
- package/lib/workspace/confirm-message-dialog.component.d.ts.map +1 -0
- package/lib/workspace/entity-options-dialog.component.d.ts +29 -0
- package/lib/workspace/entity-options-dialog.component.d.ts.map +1 -0
- package/lib/workspace/external-task-api.d.ts +2 -0
- package/lib/workspace/external-task-api.d.ts.map +1 -0
- package/lib/workspace/user-profile-dialog.component.d.ts +30 -0
- package/lib/workspace/user-profile-dialog.component.d.ts.map +1 -0
- package/lib/workspace/workspace-dialog-host.component.d.ts +26 -0
- package/lib/workspace/workspace-dialog-host.component.d.ts.map +1 -0
- package/lib/workspace/workspace-menu-item-dialog.component.d.ts +61 -0
- package/lib/workspace/workspace-menu-item-dialog.component.d.ts.map +1 -0
- package/lib/workspace/workspace-menu.component.d.ts +104 -0
- package/lib/workspace/workspace-menu.component.d.ts.map +1 -0
- package/lib/workspace/workspace-taskbar.component.d.ts +14 -0
- package/lib/workspace/workspace-taskbar.component.d.ts.map +1 -0
- package/package.json +54 -0
- package/public-api.d.ts +56 -0
- package/public-api.d.ts.map +1 -0
- package/service-worker/chill-sharp-service-worker.js +166 -0
- package/styles/core-theme.scss +1268 -0
- package/template-customization/upgrade.ps1.template +342 -0
- package/template-customization/upgrade.sh.template +271 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# ChillSharp Menu Guide
|
|
2
|
+
|
|
3
|
+
Versione italiana: [Italiano](../it/MenuGuide/README.md)
|
|
4
|
+
|
|
5
|
+
ChillSharp can store an application menu tree in the schema module rather than hard-coding it in the frontend. Menu management is exposed under `/api/chill-schema`.
|
|
6
|
+
|
|
7
|
+
## Menu item model
|
|
8
|
+
|
|
9
|
+
Each item has a stable `Guid`, `PositionNo`, `Title`, optional `Description`, optional `Parent`, `ComponentName`, optional `ComponentConfigurationJson`, and optional `MenuHierarchy`.
|
|
10
|
+
|
|
11
|
+
- `Parent = null` identifies a root item.
|
|
12
|
+
- Children reference their direct parent.
|
|
13
|
+
- Siblings sort by `PositionNo`, then `Title`, then `Guid`.
|
|
14
|
+
- `ComponentName` identifies the client component to open, for example `CRUD`.
|
|
15
|
+
|
|
16
|
+
```json
|
|
17
|
+
{
|
|
18
|
+
"Guid": "00000000-0000-0000-0000-000000000000",
|
|
19
|
+
"PositionNo": 10,
|
|
20
|
+
"Title": "Posts",
|
|
21
|
+
"Description": "Open the post management screen",
|
|
22
|
+
"Parent": null,
|
|
23
|
+
"ComponentName": "CRUD",
|
|
24
|
+
"ComponentConfigurationJson": "{\"ChillType\":\"Model.Post\"}",
|
|
25
|
+
"MenuHierarchy": "CONTENT.POSTS"
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Endpoints
|
|
30
|
+
|
|
31
|
+
- `GET /api/chill-schema/get-menu` returns root items.
|
|
32
|
+
- `GET /api/chill-schema/get-menu?parentGuid={guid}` returns one item's direct children.
|
|
33
|
+
- `POST /api/chill-schema/set-menu` creates an item when its `Guid` is empty or updates the matching item otherwise. A supplied parent must already exist, and an item cannot be its own parent. Updating an existing item with an empty `MenuHierarchy` preserves its stored value.
|
|
34
|
+
- `DELETE /api/chill-schema/delete-menu?menuItemGuid={guid}` deletes the selected item and its complete descendant subtree.
|
|
35
|
+
|
|
36
|
+
Load the tree one level at a time: request roots first, then request children as a branch is expanded.
|
|
37
|
+
|
|
38
|
+
## Visibility with `MenuHierarchy`
|
|
39
|
+
|
|
40
|
+
`MenuHierarchy` accepts one code or comma-separated codes. ChillSharp merges the comma-separated values from the current user and all active roles into an effective prefix set.
|
|
41
|
+
|
|
42
|
+
- `*` grants access to every menu item.
|
|
43
|
+
- With no effective prefix, no items are returned, including items whose hierarchy is empty.
|
|
44
|
+
- With at least one effective prefix, items with an empty hierarchy are visible.
|
|
45
|
+
- A populated item hierarchy is visible when it starts with at least one effective prefix.
|
|
46
|
+
|
|
47
|
+
For example, `CONTENT` grants `CONTENT`, `CONTENT.POSTS`, and `CONTENT.REPORTS.MONTHLY`, but not `ADMIN`. An item can expose more than one branch with `CONTENT, REPORTS.MONTHLY`.
|
|
48
|
+
|
|
49
|
+
Use stable dot-separated codes such as `ADMIN.USERS`, `CONTENT.POSTS`, and `REPORTS.MONTHLY`.
|
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
# Preparing A Model For ChillSharp
|
|
2
|
+
|
|
3
|
+
Versione italiana: [Italiano](./it/ModelPreparation.md)
|
|
4
|
+
|
|
5
|
+
This document describes the model-side requirements for exposing an EF Core domain model through ChillSharp.
|
|
6
|
+
|
|
7
|
+
## Goals
|
|
8
|
+
|
|
9
|
+
After preparation, your model can:
|
|
10
|
+
|
|
11
|
+
- be activated dynamically by Chill type name
|
|
12
|
+
- be queried and mutated through Chill DTOs
|
|
13
|
+
- expose schema metadata for clients
|
|
14
|
+
- participate in audit-field maintenance
|
|
15
|
+
- use context-specific label cultures and current-user information
|
|
16
|
+
|
|
17
|
+
## 1. Implement `IChillContext`
|
|
18
|
+
|
|
19
|
+
Your `DbContext` must implement `IChillContext`.
|
|
20
|
+
|
|
21
|
+
Required behavior:
|
|
22
|
+
|
|
23
|
+
```csharp
|
|
24
|
+
public class AppDbContext : DbContext, IChillContext
|
|
25
|
+
{
|
|
26
|
+
public AppDbContext(DbContextOptions<AppDbContext> options) : base(options) { }
|
|
27
|
+
|
|
28
|
+
public string GetChillTypePrefix()
|
|
29
|
+
{
|
|
30
|
+
return "MyCompany.MyProduct.Data";
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
public string GetPrimaryCultureName()
|
|
34
|
+
{
|
|
35
|
+
return "en-US";
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
public string GetSecondaryCultureName()
|
|
39
|
+
{
|
|
40
|
+
return "it-IT";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public string GetCurrentUserName()
|
|
44
|
+
{
|
|
45
|
+
return Environment.UserName;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### What each method is used for
|
|
51
|
+
|
|
52
|
+
- `GetChillTypePrefix()`
|
|
53
|
+
Expands short Chill type names such as `Model.Blog` into fully qualified CLR types.
|
|
54
|
+
|
|
55
|
+
- `GetPrimaryCultureName()`
|
|
56
|
+
Defines which culture should use `PrimaryLanguageLabel`.
|
|
57
|
+
|
|
58
|
+
- `GetSecondaryCultureName()`
|
|
59
|
+
Defines which culture should use `SecondaryLanguageLabel`.
|
|
60
|
+
|
|
61
|
+
- `GetCurrentUserName()`
|
|
62
|
+
Feeds entity audit tracking.
|
|
63
|
+
|
|
64
|
+
Each context instance can return different values. This is important in multi-tenant or multi-module hosts where more than one Chill context can exist with different language or user settings.
|
|
65
|
+
|
|
66
|
+
## 2. Use `ChillEntity` For Exposed Entities
|
|
67
|
+
|
|
68
|
+
The recommended pattern is to inherit from `ChillSharp.EF.ChillEntity`.
|
|
69
|
+
|
|
70
|
+
```csharp
|
|
71
|
+
using ChillSharp.Annotations;
|
|
72
|
+
using ChillSharp.EF;
|
|
73
|
+
using System.ComponentModel.DataAnnotations;
|
|
74
|
+
|
|
75
|
+
[ChillEntity(
|
|
76
|
+
UniquePropertyKeyString: "4E16F6C0-6B95-4D67-98BC-9F4D0D63EAF1",
|
|
77
|
+
PrimaryLanguageLabel: "Blog",
|
|
78
|
+
SecondaryLanguageLabel: "Blog")]
|
|
79
|
+
public class Blog : ChillEntity
|
|
80
|
+
{
|
|
81
|
+
[Key]
|
|
82
|
+
public override Guid Guid { get; set; }
|
|
83
|
+
|
|
84
|
+
[ChillProperty(
|
|
85
|
+
UniquePropertyKeyString: "50B1BB6C-D794-41E4-A85C-D4F9D7A6FA7E",
|
|
86
|
+
PrimaryLanguageLabel: "Blog title",
|
|
87
|
+
SecondaryLanguageLabel: "Titolo del blog")]
|
|
88
|
+
public string Title { get; set; } = string.Empty;
|
|
89
|
+
|
|
90
|
+
[ChillProperty(
|
|
91
|
+
UniquePropertyKeyString: "A18E7754-D8F7-45FE-B8A8-EA762A4EC9E6",
|
|
92
|
+
PrimaryLanguageLabel: "Blog url",
|
|
93
|
+
SecondaryLanguageLabel: "Url del blog")]
|
|
94
|
+
public string Url { get; set; } = string.Empty;
|
|
95
|
+
|
|
96
|
+
public override string GetLabel(IChillContext context) => Title;
|
|
97
|
+
}
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
`ChillEntity` already provides:
|
|
101
|
+
|
|
102
|
+
- `Guid`
|
|
103
|
+
- `Label`
|
|
104
|
+
- `ShortLabel`
|
|
105
|
+
- `FullTextContent`
|
|
106
|
+
- `Checksum`
|
|
107
|
+
- `LastUpdateUser`
|
|
108
|
+
- `LastUpdate`
|
|
109
|
+
- `LastUpdateUtcOffset`
|
|
110
|
+
|
|
111
|
+
## 3. Annotate Exposed Properties
|
|
112
|
+
|
|
113
|
+
ChillSharp only treats properties decorated with `[ChillProperty]` as part of the Chill metadata surface.
|
|
114
|
+
|
|
115
|
+
That affects:
|
|
116
|
+
|
|
117
|
+
- DTO mapping
|
|
118
|
+
- schema generation
|
|
119
|
+
- checksum calculation
|
|
120
|
+
- label metadata
|
|
121
|
+
|
|
122
|
+
If a property is not marked with `[ChillProperty]`, it is not part of the standard Chill property surface.
|
|
123
|
+
|
|
124
|
+
## 4. Understand Lifecycle Hooks
|
|
125
|
+
|
|
126
|
+
`ChillEngine` drives entity lifecycle methods.
|
|
127
|
+
|
|
128
|
+
### Create flow
|
|
129
|
+
|
|
130
|
+
On create, ChillSharp runs:
|
|
131
|
+
|
|
132
|
+
1. `OnCreate(context)`
|
|
133
|
+
2. `OnUpdate(context)`
|
|
134
|
+
3. save
|
|
135
|
+
4. internal audit update + `OnAfterUpdate(context)`
|
|
136
|
+
5. recompute `Label`, `ShortLabel`, `FullTextContent`
|
|
137
|
+
6. save
|
|
138
|
+
|
|
139
|
+
### Update flow
|
|
140
|
+
|
|
141
|
+
On update, ChillSharp runs:
|
|
142
|
+
|
|
143
|
+
1. `OnUpdate(context)`
|
|
144
|
+
2. save
|
|
145
|
+
3. internal audit update + `OnAfterUpdate(context)`
|
|
146
|
+
4. recompute `Label`, `ShortLabel`, `FullTextContent`
|
|
147
|
+
5. save
|
|
148
|
+
|
|
149
|
+
### Delete flow
|
|
150
|
+
|
|
151
|
+
On delete, ChillSharp runs:
|
|
152
|
+
|
|
153
|
+
1. `OnDelete(context)`
|
|
154
|
+
2. save delete
|
|
155
|
+
3. `OnAfterDelete(context)`
|
|
156
|
+
4. save
|
|
157
|
+
|
|
158
|
+
## 5. Audit-Field Behavior
|
|
159
|
+
|
|
160
|
+
`ChillEntity` automatically maintains:
|
|
161
|
+
|
|
162
|
+
- `Checksum`
|
|
163
|
+
- `LastUpdateUser`
|
|
164
|
+
- `LastUpdate`
|
|
165
|
+
- `LastUpdateUtcOffset`
|
|
166
|
+
|
|
167
|
+
The checksum is computed from all `[ChillProperty]` values except the audit fields themselves.
|
|
168
|
+
|
|
169
|
+
Notes:
|
|
170
|
+
|
|
171
|
+
- scalar values are serialized using invariant culture
|
|
172
|
+
- referenced `IChillEntity` values contribute their `Guid`
|
|
173
|
+
- collections are flattened into a deterministic string sequence before summing bytes
|
|
174
|
+
|
|
175
|
+
### Why overriding `OnAfterUpdate()` is safe
|
|
176
|
+
|
|
177
|
+
`ChillEntity` uses an explicit interface implementation for `IChillEntity.OnAfterUpdate(...)`.
|
|
178
|
+
|
|
179
|
+
`ChillEngine` calls `OnAfterUpdate()` through the interface, so the runtime flow is:
|
|
180
|
+
|
|
181
|
+
1. update audit fields
|
|
182
|
+
2. call the derived class override of `public virtual OnAfterUpdate(...)`
|
|
183
|
+
|
|
184
|
+
This means derived entities get a clean override surface while the base audit logic cannot be skipped accidentally.
|
|
185
|
+
|
|
186
|
+
## 6. Labels And Cultures
|
|
187
|
+
|
|
188
|
+
`PrimaryLanguageLabel` and `SecondaryLanguageLabel` are not just comments. They are interpreted using the active UI culture and the active `IChillContext`.
|
|
189
|
+
|
|
190
|
+
Current behavior:
|
|
191
|
+
|
|
192
|
+
- if the current UI culture matches the context secondary culture, ChillSharp prefers `SecondaryLanguageLabel`
|
|
193
|
+
- if it matches the primary culture, ChillSharp prefers `PrimaryLanguageLabel`
|
|
194
|
+
- otherwise it falls back to primary first, then secondary
|
|
195
|
+
|
|
196
|
+
This logic is used when schema metadata is generated.
|
|
197
|
+
|
|
198
|
+
## 7. Queries
|
|
199
|
+
|
|
200
|
+
Queries should implement `IChillQuery<IChillEntity>` and can also be decorated with `ChillEntityAttribute` and `ChillPropertyAttribute`.
|
|
201
|
+
|
|
202
|
+
That allows query schemas to be generated exactly like entity schemas.
|
|
203
|
+
|
|
204
|
+
## 8. Schema Persistence Readiness
|
|
205
|
+
|
|
206
|
+
If you want persisted schema metadata and schema caching, your context must also implement `IChillSchemaDbContext` and include:
|
|
207
|
+
|
|
208
|
+
```csharp
|
|
209
|
+
modelBuilder.AddChillSchemaModel();
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
Then register:
|
|
213
|
+
|
|
214
|
+
```csharp
|
|
215
|
+
builder.Services.AddChillSchema<AppDbContext>();
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## 9. Auth Readiness
|
|
219
|
+
|
|
220
|
+
If you want ChillSharp auth and permissions, your context must implement `IChillAuthDbContext` and include:
|
|
221
|
+
|
|
222
|
+
```csharp
|
|
223
|
+
modelBuilder.AddChillAuthModel();
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
Then register one of:
|
|
227
|
+
|
|
228
|
+
```csharp
|
|
229
|
+
builder.Services.AddChillAuthApi<AppDbContext>();
|
|
230
|
+
builder.Services.AddChillAuthIdentityApi<AppDbContext, IdentityUser>();
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## 10. I18n Readiness
|
|
234
|
+
|
|
235
|
+
If you want localized text storage and lookup, your context must implement `IChillI18nDbContext` and include:
|
|
236
|
+
|
|
237
|
+
```csharp
|
|
238
|
+
modelBuilder.AddChillI18nModel();
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Then register:
|
|
242
|
+
|
|
243
|
+
```csharp
|
|
244
|
+
builder.Services.AddChillI18nApi<AppDbContext>();
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
## 11. Recommendations
|
|
248
|
+
|
|
249
|
+
- Prefer inheriting from `ChillEntity` instead of implementing `IChillEntity` from scratch.
|
|
250
|
+
- Use stable GUIDs in `UniquePropertyKeyString` and `UniqueEntityKeyString`.
|
|
251
|
+
- Mark only the properties you actually want in the Chill DTO/schema surface.
|
|
252
|
+
- Keep `GetLabel()` and `GetFullTextContent()` cheap enough to run during standard CRUD flows.
|
|
253
|
+
- Return a real request identity from `GetCurrentUserName()` in API hosts.
|
|
254
|
+
- Keep context-specific culture settings on the context, not in static globals.
|
|
255
|
+
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
# Permission Model
|
|
2
|
+
|
|
3
|
+
Versione italiana: [Italiano](../it/PermissionModel/README.md)
|
|
4
|
+
|
|
5
|
+
This document describes the authorization model implemented by `ChillSharp.Auth`.
|
|
6
|
+
|
|
7
|
+
## Purpose
|
|
8
|
+
|
|
9
|
+
The permission model is designed to answer two questions consistently:
|
|
10
|
+
|
|
11
|
+
- can the current user perform an entity-level operation
|
|
12
|
+
- can the current user see or modify a specific property
|
|
13
|
+
|
|
14
|
+
The same model supports both:
|
|
15
|
+
|
|
16
|
+
- server-side enforcement
|
|
17
|
+
- client-side capability filtering
|
|
18
|
+
|
|
19
|
+
## Subjects
|
|
20
|
+
|
|
21
|
+
Permissions can be assigned to:
|
|
22
|
+
|
|
23
|
+
- a user
|
|
24
|
+
- a role
|
|
25
|
+
|
|
26
|
+
A user can belong to multiple roles.
|
|
27
|
+
|
|
28
|
+
## Resource Hierarchy
|
|
29
|
+
|
|
30
|
+
Permissions are evaluated against a three-level hierarchy:
|
|
31
|
+
|
|
32
|
+
```text
|
|
33
|
+
Module -> Entity -> Property
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Module
|
|
37
|
+
|
|
38
|
+
A module is a logical application area, for example:
|
|
39
|
+
|
|
40
|
+
- `Accounting`
|
|
41
|
+
- `Accounting.General`
|
|
42
|
+
- `Blog`
|
|
43
|
+
- `Blog.Admin`
|
|
44
|
+
|
|
45
|
+
Module names can be hierarchical.
|
|
46
|
+
|
|
47
|
+
### Entity
|
|
48
|
+
|
|
49
|
+
An entity is a Chill entity name inside a module, for example:
|
|
50
|
+
|
|
51
|
+
- `Blog`
|
|
52
|
+
- `Post`
|
|
53
|
+
- `AuthUser`
|
|
54
|
+
|
|
55
|
+
### Property
|
|
56
|
+
|
|
57
|
+
A property is a field on an entity, for example:
|
|
58
|
+
|
|
59
|
+
- `Title`
|
|
60
|
+
- `Author`
|
|
61
|
+
- `CanManagePermissions`
|
|
62
|
+
|
|
63
|
+
## Actions
|
|
64
|
+
|
|
65
|
+
### Entity actions
|
|
66
|
+
|
|
67
|
+
- `Query`
|
|
68
|
+
- `Create`
|
|
69
|
+
- `Update`
|
|
70
|
+
- `Delete`
|
|
71
|
+
|
|
72
|
+
### Property actions
|
|
73
|
+
|
|
74
|
+
- `See`
|
|
75
|
+
- `Modify`
|
|
76
|
+
|
|
77
|
+
Property permissions refine an already-allowed entity operation. They do not replace entity permissions.
|
|
78
|
+
|
|
79
|
+
## Effects
|
|
80
|
+
|
|
81
|
+
Each rule has one effect:
|
|
82
|
+
|
|
83
|
+
- `Allow`
|
|
84
|
+
- `Deny`
|
|
85
|
+
|
|
86
|
+
At the same evaluation level, `Deny` wins over `Allow`.
|
|
87
|
+
|
|
88
|
+
## Precedence
|
|
89
|
+
|
|
90
|
+
ChillSharp resolves rules in this order:
|
|
91
|
+
|
|
92
|
+
1. user property rules
|
|
93
|
+
2. user entity rules
|
|
94
|
+
3. user module rules
|
|
95
|
+
4. role property rules
|
|
96
|
+
5. role entity rules
|
|
97
|
+
6. role module rules
|
|
98
|
+
7. default deny
|
|
99
|
+
|
|
100
|
+
This combines two principles:
|
|
101
|
+
|
|
102
|
+
- user rules override role rules
|
|
103
|
+
- more specific rules override broader rules
|
|
104
|
+
|
|
105
|
+
## How Operations Are Evaluated
|
|
106
|
+
|
|
107
|
+
### Query
|
|
108
|
+
|
|
109
|
+
To query an entity:
|
|
110
|
+
|
|
111
|
+
1. the user must have entity `Query`
|
|
112
|
+
2. each returned property must also have `See`
|
|
113
|
+
|
|
114
|
+
If a property is not allowed, the server can remove, null, or mask it depending on the calling surface and implementation.
|
|
115
|
+
|
|
116
|
+
### Create
|
|
117
|
+
|
|
118
|
+
To create an entity:
|
|
119
|
+
|
|
120
|
+
1. the user must have entity `Create`
|
|
121
|
+
2. each provided property must have `Modify`
|
|
122
|
+
|
|
123
|
+
### Update
|
|
124
|
+
|
|
125
|
+
To update an entity:
|
|
126
|
+
|
|
127
|
+
1. the user must have entity `Update`
|
|
128
|
+
2. each changed property must have `Modify`
|
|
129
|
+
|
|
130
|
+
### Delete
|
|
131
|
+
|
|
132
|
+
To delete an entity:
|
|
133
|
+
|
|
134
|
+
1. the user must have entity `Delete`
|
|
135
|
+
|
|
136
|
+
Property rules do not matter for delete.
|
|
137
|
+
|
|
138
|
+
## Default Security Posture
|
|
139
|
+
|
|
140
|
+
The model is default-deny.
|
|
141
|
+
|
|
142
|
+
If no rule grants access, access is denied.
|
|
143
|
+
|
|
144
|
+
This is intentional. It prevents new entities or properties from becoming visible just because they were added to the model.
|
|
145
|
+
|
|
146
|
+
## Typical Rule Examples
|
|
147
|
+
|
|
148
|
+
Allow querying all blog entities in a module:
|
|
149
|
+
|
|
150
|
+
```text
|
|
151
|
+
Allow Query Module=Blog
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Allow updating posts:
|
|
155
|
+
|
|
156
|
+
```text
|
|
157
|
+
Allow Update Module=Blog Entity=Post
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Block edits to a sensitive property while allowing broader updates:
|
|
161
|
+
|
|
162
|
+
```text
|
|
163
|
+
Allow Update Module=Blog Entity=Post
|
|
164
|
+
Deny Modify Module=Blog Entity=Post Property=InternalNotes
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Auth Management API
|
|
168
|
+
|
|
169
|
+
`ChillSharp.Auth` now exposes a management-oriented API that separates:
|
|
170
|
+
|
|
171
|
+
- client-side capability evaluation
|
|
172
|
+
- server-side management of users, roles, and permission rules
|
|
173
|
+
|
|
174
|
+
### `GET chill-auth/get-permissions`
|
|
175
|
+
|
|
176
|
+
Returns the current logged-in user's authorization data as a structured payload:
|
|
177
|
+
|
|
178
|
+
- the current auth user
|
|
179
|
+
- the user's direct permissions
|
|
180
|
+
- the user's assigned roles
|
|
181
|
+
- for each assigned role, that role's permissions
|
|
182
|
+
|
|
183
|
+
Clients should use this payload to evaluate capabilities locally and:
|
|
184
|
+
|
|
185
|
+
- disable UI actions
|
|
186
|
+
- hide fields
|
|
187
|
+
- decide which editors or actions to render
|
|
188
|
+
|
|
189
|
+
The old public `evaluate/*` endpoints are removed. Evaluation is now expected to happen in the client libraries or UI layer by applying the same precedence rules described in this document.
|
|
190
|
+
|
|
191
|
+
### Management Endpoints Requiring `CanManagePermissions`
|
|
192
|
+
|
|
193
|
+
The following endpoints are reserved for privileged users only:
|
|
194
|
+
|
|
195
|
+
- `GET chill-auth/get-user-list`
|
|
196
|
+
- `GET chill-auth/get-user`
|
|
197
|
+
- `POST chill-auth/set-user`
|
|
198
|
+
- `GET chill-auth/get-role-list`
|
|
199
|
+
- `GET chill-auth/get-role`
|
|
200
|
+
- `POST chill-auth/set-role`
|
|
201
|
+
|
|
202
|
+
### `GET chill-auth/get-user-list`
|
|
203
|
+
|
|
204
|
+
Returns the full user list in a lightweight form suitable for dropdowns and selectors.
|
|
205
|
+
|
|
206
|
+
### `GET chill-auth/get-user`
|
|
207
|
+
|
|
208
|
+
Returns a single user as one structured object containing:
|
|
209
|
+
|
|
210
|
+
- user data
|
|
211
|
+
- assigned roles
|
|
212
|
+
- user-specific permissions
|
|
213
|
+
|
|
214
|
+
Role permissions are not expanded here because the UI can load them from the related role payload when needed.
|
|
215
|
+
|
|
216
|
+
### `POST chill-auth/set-user`
|
|
217
|
+
|
|
218
|
+
Creates or updates a user with:
|
|
219
|
+
|
|
220
|
+
- the full assigned role list
|
|
221
|
+
- the full list of user-specific permissions
|
|
222
|
+
|
|
223
|
+
The server synchronizes changes incrementally:
|
|
224
|
+
|
|
225
|
+
- adds missing roles and removes deleted roles
|
|
226
|
+
- adds missing permissions and removes deleted permissions
|
|
227
|
+
|
|
228
|
+
It does not clear and recreate the full set blindly.
|
|
229
|
+
|
|
230
|
+
### `GET chill-auth/get-role-list`
|
|
231
|
+
|
|
232
|
+
Returns the full role list in a lightweight form suitable for dropdowns and selectors.
|
|
233
|
+
|
|
234
|
+
### `GET chill-auth/get-role`
|
|
235
|
+
|
|
236
|
+
Returns a single role as one structured object containing:
|
|
237
|
+
|
|
238
|
+
- role data
|
|
239
|
+
- role-specific permissions
|
|
240
|
+
- users assigned to the role
|
|
241
|
+
|
|
242
|
+
### `POST chill-auth/set-role`
|
|
243
|
+
|
|
244
|
+
Creates or updates a role with:
|
|
245
|
+
|
|
246
|
+
- the full list of role permissions
|
|
247
|
+
- the full list of users assigned to the role
|
|
248
|
+
|
|
249
|
+
The server synchronizes changes incrementally:
|
|
250
|
+
|
|
251
|
+
- adds missing permissions and removes deleted permissions
|
|
252
|
+
- adds missing user-role assignments and removes deleted assignments
|
|
253
|
+
|
|
254
|
+
It does not clear and recreate the full set blindly.
|
|
255
|
+
|
|
256
|
+
## Server Enforcement
|
|
257
|
+
|
|
258
|
+
Clients may evaluate capabilities locally for UX purposes, but the server remains the source of truth.
|
|
259
|
+
|
|
260
|
+
Entity-level server authorization continues to be enforced through the existing ChillSharp ACL integration. Management endpoints additionally require `CanManagePermissions` when the caller is authenticated.
|
|
261
|
+
|
|
262
|
+
## Related Runtime Pieces
|
|
263
|
+
|
|
264
|
+
The permission model is backed by:
|
|
265
|
+
|
|
266
|
+
- `AuthUser`
|
|
267
|
+
- `AuthRole`
|
|
268
|
+
- `AuthUserRole`
|
|
269
|
+
- `AuthPermissionRule`
|
|
270
|
+
|
|
271
|
+
Management endpoints are exposed through `ChillSharp.Auth`.
|
|
272
|
+
|
|
273
|
+
For registration and account flows, see:
|
|
274
|
+
|
|
275
|
+
- [AuthenticationModel/README.md](../AuthenticationModel/README.md)
|
|
276
|
+
|
|
277
|
+
|