Files

133 lines
8.6 KiB
Markdown
Raw Permalink Normal View History

2026-04-17 14:55:32 -04:00
---
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 users 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.