Files
2026-04-17 14:55:32 -04:00

179 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
source_files:
- DataPRO/Users/ChallengeDialog.cs
- DataPRO/Users/IUIItems.cs
- DataPRO/Users/UIItemHelper.cs
- DataPRO/Users/ChallengeDialog.designer.cs
- DataPRO/Users/ITagAware.cs
- DataPRO/Users/Tags.cs
- DataPRO/Users/UserCollection.cs
generated_at: "2026-04-16T03:46:19.938942+00:00"
model: "Qwen/Qwen3-Coder-Next-FP8"
schema_version: 1
sha256: "411369925e7525de"
---
# Documentation: `DTS.Slice.Users` Module
## 1. Purpose
This module provides core user and tag management functionality for the DataPRO application, including UI permission/visibility control, user CRUD operations, and tag-based object association. It enables role-based access control (RBAC) by associating users with permission levels and visibility flags for UI elements, and supports tagging arbitrary entities (users, groups, tests, sensors, etc.) for flexible filtering and grouping. The module includes a modal dialog (`ChallengeDialog`) for prompting administrator credentials when elevated privileges are required.
## 2. Public Interface
### `ChallengeDialog` (Windows Form)
- **`ChallengeDialog()`**
Public constructor. Initializes the form via `InitializeComponent()`. Displays a password prompt for admin access with fields for password entry (`tbPassword`), a failure message label (`lblLoginFailedMessage`), and `Continue`/`Cancel` buttons (`btnContinue`, `btnCancel`). No custom logic is implemented in the provided source—behavior is entirely UI-driven.
### `IUIItems` Interface
- **`UserPermissionLevels GetDefaultRolePermission(DefaultRoles role)`**
Returns the default permission level for a given role on this UI item.
- **`bool GetDefaultRoleVisibility(DefaultRoles role)`**
Returns whether the UI item is visible by default for a given role.
- **`void SetVisible(bool bShow)`**
Sets the visibility state of the UI item.
- **`void SetEnabled(bool bEnabled)`**
Sets the enabled state of the UI item.
- **`UserPermissionLevels GetRequiredPermission()`**
Returns the minimum permission level required to access this UI item.
- **`string GetName()`**
Returns the display name of the UI item.
- **`long GetID()`**
Returns the unique identifier of the UI item.
- **`void SetID(long id)`**
Sets the unique identifier of the UI item.
### `UIItemHelper` Class
- **`UIItemHelper(long uiItemId, short permission, bool visible, string uiItemName)`**
Constructor. Stores UI item metadata: ID, permission level, visibility, and name.
- **`long UIItemId { get; }`**
Read-only ID of the UI item.
- **`string UIItemName { get; }`**
Read-only display name of the UI item.
- **`bool IsVisible { get; }`**
Read-only visibility flag.
- **`short Permission { get; }`**
Read-only permission level (stored as `short`).
### `TagAwareBase` (Abstract Class)
- **`TagTypes TagType { get; }`**
Abstract property returning the type of entity this tag-aware object represents (e.g., `User`, `TestSetup`).
- **`int[] TagIDs { get; set; }`**
Array of tag IDs associated with the object. Setter accepts `null` (treated as empty array).
- **`byte[] TagsBlobBytes { get; set; }`**
Binary blob representation of `TagIDs` (int array → byte array via `Buffer.BlockCopy`). Setter logs exceptions on failure.
- **`void SetTagsFromCommaSeparatedString(string tagText)`**
Parses comma-separated tag text, trims whitespace, and updates `TagIDs` via `SetTags()`.
- **`virtual void SetTags(string[] tagsText)`**
Updates `Tags` collection and `TagIDs` based on tag text array. Raises `OnPropertyChanged("TagIDs")`.
- **`string GetTagsAsCommaSeparatedString()`**
Returns comma-separated tag text (e.g., `"tag1,tag2"`).
- **`virtual string[] GetTagsArray()`**
Returns array of tag text strings corresponding to `TagIDs`.
- **`virtual int[] GetTagIDs()`**
Returns `TagIDs` array.
- **`virtual void RemoveTags(string[] tagsText)`**
Stub—no implementation provided.
- **`bool TagCompatible(string tags)`**
Returns `true` if *any* tag in the input string matches a tag on this object. Ignores empty/whitespace tags.
- **`virtual bool TagCompatible(int[] tags)`**
Returns `true` if `tags` array is empty or shares at least one ID with `TagIDs`.
- **`virtual bool HasIntersectingTag(int[] tags)`**
Returns `true` if `tags` and `TagIDs` share at least one ID.
- **`void InsertTagsFromCommaSeparatedString(int id, TagTypes tagType, string tags)`**
Sets tags from comma-separated string and commits associations to DB.
- **`void Commit(int id, TagTypes tagType)`**
Deletes existing tag assignments for `(id, tagType)` and inserts new assignments for current `TagIDs`. Uses stored procedures `sp_TagAssignmentsDelete` and `sp_TagAssignmentsInsert`. Logs errors via `APILogger`.
- **`List<int> GetTagIdList(int objectId, TagTypes tagType)`**
Retrieves tag IDs for `(objectId, tagType)` from DB via `sp_TagAssignmentsGet`. Returns empty list on failure; logs exceptions.
### `Tags` Class (Singleton)
- **`Tag INVALID_ID = -1`**
Constant representing an invalid/missing tag ID.
- **`class Tag`**
Represents a single tag with `ID`, `Text`, and `IsObsolete` properties. Implements `ICloneable`.
- **`static Tags TagsInstance { get; }`**
Singleton instance. Initialized on first access.
- **`static bool AddTag(string tagText)`**
Adds a new tag if not already present in cache or DB. Returns `false` if tag exists or input is null/empty.
- **`static bool MigrateTag(string tagText)`**
Commits a tag to DB (used for migration). Does not check cache.
- **`static bool[] AddRange(string[] tagText)`**
Adds multiple tags. Trims leading whitespace from each. Returns array of success flags.
- **`static int GetIDFromTagText(string tagText)`**
Retrieves tag ID from DB for given text. Returns `Tag.INVALID_ID` if not found.
- **`static int[] GetIDsFromTagText(string[] tagText)`**
Converts array of tag text to array of IDs. Skips invalid IDs.
- **`static string GetTagTextFromID(int tagID)`**
Retrieves tag text from in-memory cache for given ID. Returns `null` if invalid or not found.
- **`static string[] GetTagTextFromIDs(int[] tagId)`**
Converts array of IDs to array of tag text. Skips invalid/empty entries.
- **`bool ContainsTag(string text)`**
Checks if tag text exists in in-memory cache.
- **`void UpdateList()`**
Refreshes in-memory cache from DB via `sp_TagsGet`. Clears cache first.
### `UserCollection` Class (Singleton)
- **`static UserCollection UsersList { get; }`**
Singleton instance. Thread-safe via `lock`.
- **`static Dictionary<int, List<int>> GetUserToTagIdLookup()`**
Returns mapping of user IDs to their associated tag IDs. Calls `DbOperations.TagAssignmentsGet(TagTypes.User, out ...)`.
- **`static User[] GetAllUsers(IUIItems[] allItems, int? uid = null)`**
Loads users from DB. If `uid` is provided, returns only that user; otherwise, ensures default users (roles + special accounts like `DefaultAeroUsername`) exist in DB. Uses `sp_UserUIItemSettingsGet`, `sp_UsersGet`. For non-`uid` calls, commits missing default users via `UsersList.Commit()`.
- **`static User GetUser(int uid, IUIItems[] items)`**
Wrapper around `GetAllUsers(items, uid)`. Returns first result or `null`.
- **`static User GetUser(string username, IUIItems[] items)`**
Retrieves user ID by username via `sp_UsersGetId`, then calls `GetUser(id, items)`.
- **`void Commit(User user, string username, IUIItems[] items)`**
Persists user to DB via `sp_UsersUpdateInsert`. Updates user settings and permissions/visibility via `InsertPermissionsAndVisibility()` and `InsertTags()`. Raises `OnPropertyChanged("AllUsers")`.
- **`void Delete(User user)` / `void Delete(User[] users)`**
Deletes user(s) via `sp_UsersDelete`. Raises `OnPropertyChanged("AllUsers")`.
- **`private static void InsertTags(User user)`**
Deletes existing tag assignments for user and inserts new ones for `user.TagIDs`.
- **`private static void InsertPermissionsAndVisibility(User user, IReadOnlyList<IUIItems> items)`**
Deletes existing UI item permissions for user via `sp_UserUIItemSettingsDelete`, then inserts new permissions/visibility for each `item` via `sp_UserUIItemSettingsInsert`.
## 3. Invariants
- **Tag IDs are non-negative integers** except `Tag.INVALID_ID = -1` (used for missing IDs).
- **`Tags` singleton is lazily initialized and thread-safe** via `lock(LOCK_OBJECT)` for cache access.
- **`UserCollection.UsersList` is a singleton** with thread-safe lazy initialization (`lock(MyLock)`).
- **`UIItemHelper` properties are immutable after construction** (read-only auto-properties).
- **`TagIDs` array is never `null`** (setter normalizes `null` to `new int[0]`).
- **`TagCompatible(string)` ignores empty/whitespace tags** in input.
- **`Commit(int id, TagTypes tagType)` in `TagAwareBase` deletes existing assignments before inserting new ones**—no partial updates.
- **`GetAllUsers` ensures default users exist** in DB when called without `uid` (e.g., `DefaultAeroUsername`, `DefaultCrashUsername`, `DefaultTSRAIRUsername`).
- **`ChallengeDialog` has no custom logic**—behavior is purely UI-driven (no event handlers or validation in source).
## 4. Dependencies
### Internal Dependencies
- **`DTS.Slice.Users.User`** (not provided in source, but referenced in `UserCollection.cs`): Core user model with properties like `Id`, `UserName`, `Role`, `TagIDs`, `GetPermission()`, `IsShowTabFlagSet()`, `GetPasswordHash()`, `IsADefaultUser`, `TagType`.
- **`DTS.Slice.Users.UserSettings.TestSetupDefaults`**: Used in `UserCollection.Commit()` to manage user-specific settings.
- **`DTS.Slice.Users.UserSettings.Defaults`**: Used to create/update user setting properties.
### External Dependencies
- **`System.Windows.Forms`**: `ChallengeDialog` inherits from `Form`; uses `TableLayoutPanel`, `TextBox`, `Button`, `Label`.
- **`DTS.Common.Storage.DbOperations`**: Provides database access methods (`GetSQLCommand`, `QueryDataSet`, `TagAssignmentsGet`, `Tags` nested class with fields like `TagFields`, `TagAssignmentFields`).
- **`DTS.Common.Storage.DbOperationsEnum.StoredProcedure`**: Enum for stored procedure names (e.g., `sp_TagsInsert`, `sp_UsersGet`).
- **`DTS.Common.Utilities.Logging.APILogger`**: Used for exception logging.
- **`DTS.Common.Base.BasePropertyChanged`**: Base class for `TagAwareBase` (implements `INotifyPropertyChanged`).
- **`DTS.Common.Interface.Tags`**: Namespace for tag-related interfaces (e.g., `ICloneable` usage).
### Inferred Dependencies
- **Database stored procedures**: `sp_TagsInsert`, `sp_TagsGetId`, `sp_TagsGet`, `sp_UsersUpdateInsert`, `sp_UsersGet`, `sp_UsersGetId`, `sp_UsersDelete`, `sp_UserUIItemSettingsGet`, `sp_UserUIItemSettingsDelete`, `sp_UserUIItemSettingsInsert`, `sp_TagAssignmentsDelete`, `sp_TagAssignmentsInsert`.
- **`User.DefaultRoles` enum**: Referenced in `IUIItems` and `UserCollection.GetAllUsers`.
- **`User.UserPermissionLevels` enum**: Referenced in `IUIItems` and `UIItemHelper`.
## 5. Gotchas
- **`TagIDs` setter accepts `null` but normalizes to empty array**—no exception thrown, but `TagsBlobBytes` setter silently returns if input length < `sizeof(int)`.
- **`TagCompatible(string)` returns `true` for empty/whitespace input**—not `false` as might be expected.
- **`Tags` cache is only updated on startup or when `AddTag`/`MigrateTag` is called**—changes to tags in DB by other processes are not reflected until `UpdateList()` is explicitly invoked.
- **`GetAllUsers` commits missing default users to DB**—this may cause unintended side effects if called repeatedly (e.g., during testing).
- **`ChallengeDialog` has no public methods or properties**—its behavior (e.g., password validation, dialog result) is not implemented in the provided source.
- **`RemoveTags` in `TagAwareBase` is a stub**—no implementation provided.
- **`UserCollection.Commit` calls `InsertPermissionsAndVisibility` for *all* `IUIItems`**—even if permission/visibility hasnt changed, potentially causing unnecessary DB writes.
- **`Tags.GetTagTextFromID` uses in-memory cache only**—no DB fallback if tag is missing from cache.
- **`Tags.AddTag` trims leading whitespace only** (via `TrimStart`) when adding tags—trailing whitespace is preserved in DB.
- **`UIItemHelper.Permission` is stored as `short`**—mismatch with `UserPermissionLevels` enum (assumed to be `short`-backed, but not verified in source).