--- 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 _tabPermissions` - `private readonly Dictionary _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 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.