133 lines
8.6 KiB
Markdown
133 lines
8.6 KiB
Markdown
|
|
---
|
|||
|
|
source_files:
|
|||
|
|
- DataPRO/Modules/PreviousDBVersions/Version57/DatabaseExport/Users/IUIItems.cs
|
|||
|
|
- DataPRO/Modules/PreviousDBVersions/Version57/DatabaseExport/Users/ITagAware.cs
|
|||
|
|
- DataPRO/Modules/PreviousDBVersions/Version57/DatabaseExport/Users/Tags.cs
|
|||
|
|
- DataPRO/Modules/PreviousDBVersions/Version57/DatabaseExport/Users/User.cs
|
|||
|
|
generated_at: "2026-04-16T04:58:34.034818+00:00"
|
|||
|
|
model: "Qwen/Qwen3-Coder-Next-FP8"
|
|||
|
|
schema_version: 1
|
|||
|
|
sha256: "d08339a454aa8af1"
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# Users
|
|||
|
|
|
|||
|
|
## Documentation: `DatabaseExport.Users` Module (Version 57)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 1. Purpose
|
|||
|
|
|
|||
|
|
This module provides data models and utilities for representing and persisting user account information in a legacy database export context (specifically for database version 57). It defines core abstractions for users (`User`), tag-aware entities (`TagAwareBase`), UI item identification (`IUIItems`), and centralized tag management (`Tags`). Its primary role is to enable serialization of user data—including permissions, visibility settings, and tags—into XML-compatible formats, while leveraging an in-memory cache of tags for efficient lookup. It supports default system users (e.g., `Admin`, `Guest`) and enforces immutability constraints on default users’ roles.
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 2. Public Interface
|
|||
|
|
|
|||
|
|
#### Interface: `IUIItems`
|
|||
|
|
- **`string GetName()`**
|
|||
|
|
Returns a unique string identifier for a UI item (e.g., tab or module name). Used as the key in permission/visibility dictionaries.
|
|||
|
|
|
|||
|
|
#### Abstract Class: `TagAwareBase`
|
|||
|
|
- **`byte[] TagsBlobBytes { get; set; }`**
|
|||
|
|
Serializes/deserializes the `TagIDs` array to/from a byte array using `Buffer.BlockCopy`. Setter includes a `try/catch` that silently discards exceptions (no logging in source).
|
|||
|
|
- **`int[] TagIDs { get; set; }`**
|
|||
|
|
Stores the list of tag IDs associated with the entity. Setter replaces with empty array if `null`.
|
|||
|
|
- **`string GetTagsCommaSeperatedString()`**
|
|||
|
|
Returns a comma-separated string of tag *text* values (e.g., `"Role:Admin,Version:1"`), derived from `TagIDs` via `GetTagsArray()`.
|
|||
|
|
- **`virtual string[] GetTagsArray()`**
|
|||
|
|
Converts `TagIDs` to human-readable tag strings using `Tags.GetTagTextFromIDs()`. Overridable.
|
|||
|
|
|
|||
|
|
#### Class: `Tags`
|
|||
|
|
- **`class Tag`**
|
|||
|
|
Represents a single tag with `ID`, `Text`, and `IsObsolete` fields. Includes:
|
|||
|
|
- `const int INVALID_ID = -1`
|
|||
|
|
- Constructor from `DataRow` (populates fields from DB columns; exceptions silently ignored).
|
|||
|
|
- `Clone()` implementation (returns a new `Tag` instance with copied values).
|
|||
|
|
- **`static Tags TagsInstance { get; }`**
|
|||
|
|
Singleton accessor (lazy-initialized on first access).
|
|||
|
|
- **`static string GetTagTextFromID(int tagID)`**
|
|||
|
|
Returns the tag text for a given ID from the in-memory cache. Returns `null` if `tagID < 0`, `INVALID_ID`, or not found.
|
|||
|
|
- **`static string[] GetTagTextFromIDs(int[] tagID)`**
|
|||
|
|
Converts an array of tag IDs to an array of tag texts, skipping `INVALID_ID` and `null`/whitespace results.
|
|||
|
|
- **`private void UpdateList()`**
|
|||
|
|
Populates/refreshes the `_tagsLookup` dictionary by querying the database (`SELECT * FROM [Tags table]`). Uses `lock(MyLock)` for thread safety.
|
|||
|
|
|
|||
|
|
#### Class: `User`
|
|||
|
|
- **Nested Enums**
|
|||
|
|
- `DefaultRoles`: `Administrator`, `PowerUser`, `User`, `Guest`
|
|||
|
|
- `UserPermissionLevels`: `Deny`, `Read`, `ReadAndExecute`, `Edit`, `Admin`
|
|||
|
|
- `Tags`: Enumerates tag names used for user metadata (e.g., `Role`, `UserName`, `Password`)
|
|||
|
|
- `XmlFields`: Enumerates XML element names for serialization (e.g., `ID`, `UserName`, `IUIItemPermissions`)
|
|||
|
|
- **Constants**
|
|||
|
|
- `DEFAULT_LAST_MODIFIED_BY = "---"`
|
|||
|
|
- `DEFAULT_ADMIN_USERNAME = "Admin"`, `DEFAULT_GUEST_USERNAME = "Guest"`, etc.
|
|||
|
|
- `INVALID_ID = -1`
|
|||
|
|
- **Properties**
|
|||
|
|
- `bool IsADefaultUser` → `true` if `UserName` matches `GetDefaultUserName(Role)`.
|
|||
|
|
- `string Name`, `string UserName`, `int Id`, `DefaultRoles Role`, `int Version`, `DateTime LastModified`, `string LastModifiedBy`, `bool LocalOnly`
|
|||
|
|
- `private readonly Dictionary<IUIItems, UserPermissionLevels> _tabPermissions`
|
|||
|
|
- `private readonly Dictionary<IUIItems, bool> _showTabs`
|
|||
|
|
- **Methods**
|
|||
|
|
- **`public override ConstraintHelper[] GetConstraints()`**
|
|||
|
|
Returns a constraint for `UserName` (used for uniqueness validation).
|
|||
|
|
- **`public override string LookupTable => DbOperations.Users.USERS_TABLE`**
|
|||
|
|
Specifies the database table name.
|
|||
|
|
- **`public User(DataRow row)`**
|
|||
|
|
Constructor that initializes all properties from a database `DataRow`.
|
|||
|
|
- **`public string GetPermissionSerialized()`**
|
|||
|
|
Serializes `_tabPermissions` as `"UIItemName=PermissionLevelInt,..."` (thread-safe via `lock(TabPermissionsLock)`).
|
|||
|
|
- **`public static string GetDefaultUserName(DefaultRoles role)`**
|
|||
|
|
Maps `DefaultRoles` to default usernames (e.g., `Administrator` → `"Admin"`).
|
|||
|
|
- **`public string GetVisibilitySerialized()`**
|
|||
|
|
Serializes `_showTabs` as `"UIItemName=1/0,..."`.
|
|||
|
|
- **`public Dictionary<string, string> GetValues()`**
|
|||
|
|
Returns a dictionary of XML field names to values for serialization, including:
|
|||
|
|
- Basic fields (`ID`, `UserName`, `DisplayName`, `Password`, `Role`, etc.)
|
|||
|
|
- Serialized permissions (`IUIItemPermissions`)
|
|||
|
|
- Serialized visibility (`IUIItemVisibility`)
|
|||
|
|
- Tag string (`UserTags` via `GetTagsCommaSeperatedString()`)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 3. Invariants
|
|||
|
|
|
|||
|
|
- **`TagIDs` must be non-null**: The `TagIDs` setter replaces `null` with `new int[0]`.
|
|||
|
|
- **`INVALID_ID = -1` is excluded from tag lookups**: `GetTagTextFromID` and `GetTagTextFromIDs` explicitly skip `INVALID_ID`.
|
|||
|
|
- **Default users are immutable by role**: Setting `Role` on a `User` where `IsADefaultUser == true` throws `NotSupportedException` if the role changes.
|
|||
|
|
- **Tag text lookup is case-sensitive and text-based**: `_tagsLookup` uses `Tag.Text` as the dictionary key (in `UpdateList()`), but `GetTagTextFromId` searches by `Tag.ID` (linear scan).
|
|||
|
|
- **`TagsInstance` is a singleton**: Initialized once on first access; `_tagsLookup` is populated only at construction and via `UpdateList()` (not auto-refreshed).
|
|||
|
|
- **`TagsBlobBytes` size must be divisible by `sizeof(int)`**: The setter assumes `value.Length % sizeof(int) == 0`; otherwise, `Buffer.BlockCopy` may throw (caught silently).
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 4. Dependencies
|
|||
|
|
|
|||
|
|
- **Imports/Usings**:
|
|||
|
|
- `System`, `System.Text`, `System.Collections.Generic`, `System.Linq`, `System.Data`
|
|||
|
|
- **External Types Referenced (from source)**:
|
|||
|
|
- `DbOperations.Tags` (static class with `TagFields` enum and `Table` property)
|
|||
|
|
- `DbOperations.Users` (static class with `UserFields` enum and `USERS_TABLE` property)
|
|||
|
|
- `DbOperations.Connection` (provides `QueryDataSet`)
|
|||
|
|
- `DbOperations.GetCommand()` (returns `IDbCommand`)
|
|||
|
|
- `DbTimeStampBase` (base class of `TagAwareBase`; not shown, assumed to provide timestamp fields)
|
|||
|
|
- `ConstraintHelper` (used in `GetConstraints()`)
|
|||
|
|
- **Depended Upon By**:
|
|||
|
|
- `User` is used by export/serialization logic (e.g., `GetValues()` implies integration with XML export).
|
|||
|
|
- `Tags.TagsInstance` is used by `TagAwareBase.GetTagsArray()` and `User.GetValues()`.
|
|||
|
|
- `IUIItems` is used as a key in `User`’s permission/visibility dictionaries (implementations not in this source).
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
### 5. Gotchas
|
|||
|
|
|
|||
|
|
- **Silent exception handling**: Multiple `catch (Exception)` blocks (in `TagAwareBase.TagsBlobBytes`, `Tag` constructor, `Tags.UpdateList`) log nothing—only commented-out logging stubs exist. Errors may go unnoticed.
|
|||
|
|
- **Inefficient tag lookup**: `GetTagTextFromId` performs a linear scan over `_tagsLookup` to find by ID, despite `_tagsLookup` being keyed by `Text`. This is O(n) per lookup.
|
|||
|
|
- **`TagsBlobBytes` setter is fragile**: Assumes input byte array length is divisible by `sizeof(int)`; otherwise, `Buffer.BlockCopy` throws (caught silently).
|
|||
|
|
- **`TagsInstance` not thread-safe during initialization**: `_tagsInstance` is assigned without double-checked locking (only `null == _tagsInstance` check), risking multiple instantiations in multi-threaded scenarios.
|
|||
|
|
- **`IsADefaultUser` is role-dependent but role change is restricted**: A user’s default status is computed at runtime, but changing the role of a default user is blocked—this may cause confusion if default usernames are reassigned.
|
|||
|
|
- **`GetTagsCommaSeperatedString()` has typo**: Method name uses "Seperated" (missing 'a'), consistent with legacy naming.
|
|||
|
|
- **`TagsBlobBytes` and `TagIDs` are redundant**: `TagsBlobBytes` is a byte-level serialization of `TagIDs`, but only `TagIDs` is used in `GetTagsArray()`. `TagsBlobBytes` may be legacy or for external compatibility.
|
|||
|
|
- **No validation of `UserName` uniqueness**: While `GetConstraints()` defines a uniqueness constraint, enforcement is external (e.g., in DB or caller), and the `User` class does not validate this itself.
|
|||
|
|
|
|||
|
|
None identified beyond these.
|