Files
DP44/docs/ai/DataPRO/Users.md

223 lines
11 KiB
Markdown
Raw Normal View History

2026-04-17 14:55:32 -04:00
---
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-17T15:49:59.567576+00:00"
model: "zai-org/GLM-5-FP8"
schema_version: 1
sha256: "ff967d41cf0dfb7b"
---
# Documentation: DTS.Slice.Users Module
## 1. Purpose
This module provides user management infrastructure for the DTS.Slice application, including authentication challenges, permission/visibility control for UI items, tag-based entity categorization, and user collection persistence. It handles the interaction between in-memory user objects, UI permission settings, and database storage, supporting both default role-based users and custom user configurations with tag-based access control.
---
## 2. Public Interface
### ChallengeDialog (Form)
A Windows Forms dialog prompting for administrator password when elevated privileges are required.
**Constructor:**
- `ChallengeDialog()` - Initializes the dialog component.
**UI Controls (publicly accessible):**
- `tbPassword` - TextBox with `PasswordChar = '*'` and `UseSystemPasswordChar = true`
- `lblLoginFailedMessage` - Label displaying login failure messages (DarkRed foreground)
- `btnContinue` - Button to submit password
- `btnCancel` - Button to cancel the operation
- `label2` - Instructional label explaining admin access requirement
---
### IUIItems (Interface)
Defines the contract for UI items that support role-based permission and visibility settings.
| Method | Return Type | Description |
|--------|-------------|-------------|
| `GetDefaultRolePermission(User.DefaultRoles role)` | `User.UserPermissionLevels` | Gets the default permission level for a given role. |
| `GetDefaultRoleVisibility(User.DefaultRoles role)` | `bool` | Gets the default visibility for a given role. |
| `SetVisible(bool bShow)` | `void` | Sets the visibility state. |
| `SetEnabled(bool bEnabled)` | `void` | Sets the enabled state. |
| `GetRequiredPermission()` | `User.UserPermissionLevels` | Gets the required permission level. |
| `GetName()` | `string` | Gets the UI item name. |
| `GetID()` | `long` | Gets the UI item ID. |
| `SetID(long id)` | `void` | Sets the UI item ID. |
---
### UIItemHelper (Class)
A data container class for UI item settings.
**Constructor:**
- `UIItemHelper(long uiItemId, short permission, bool visible, string uiItemName)`
**Properties:**
| Property | Type | Access |
|----------|------|--------|
| `UIItemId` | `long` | get; private set; |
| `UIItemName` | `string` | get; private set; |
| `IsVisible` | `bool` | get; private set; |
| `Permission` | `short` | get; private set; |
---
### TagAwareBase (Abstract Class)
Abstract base class providing tag management functionality for entities that support tagging.
**Enum: TagTypes**
- `User`, `Group`, `Template`, `TestSetup`, `Sensors`, `SensorModels`
**Abstract Property:**
- `TagTypes TagType { get; }` - Must be implemented by derived classes.
**Properties:**
| Property | Type | Description |
|----------|------|-------------|
| `TagsBlobBytes` | `byte[]` | Gets/sets tags as a serialized byte array (4 bytes per int). |
| `TagIDs` | `int[]` | Gets/sets the array of tag IDs. Never null; defaults to empty array. |
**Methods:**
| Method | Signature | Description |
|--------|-----------|-------------|
| `SetTagsFromCommaSeparatedString` | `void SetTagsFromCommaSeparatedString(string tagText)` | Parses comma-separated tags and sets them. |
| `SetTags` | `virtual void SetTags(string[] tagsText)` | Sets tags from string array; notifies property change. |
| `GetTagsAsCommaSeparatedString` | `string GetTagsAsCommaSeparatedString()` | Returns tags as comma-separated string. |
| `GetTagsArray` | `virtual string[] GetTagsArray()` | Returns tag text array from IDs. |
| `GetTagIDs` | `virtual int[] GetTagIDs()` | Returns the TagIDs array. |
| `RemoveTags` | `virtual void RemoveTags(string[] tagsText)` | Removes specified tags. |
| `TagCompatible` | `bool TagCompatible(string tags)` | Checks if any comma-separated tag matches. |
| `TagCompatible` | `virtual bool TagCompatible(int[] tags)` | Checks if any tag ID intersects. |
| `HasIntersectingTag` | `virtual bool HasIntersectingTag(int[] tags)` | Returns true if any tag ID is in TagIDs. |
| `InsertTagsFromCommaSeparatedString` | `void InsertTagsFromCommaSeparatedString(int id, TagTypes tagType, string tags)` | Sets tags and commits to database. |
| `Commit` | `void Commit(int id, TagTypes tagType)` | Persists tag assignments to database. |
| `GetTagIdList` | `List<int> GetTagIdList(int objectId, TagTypes tagType)` | Retrieves tag IDs for an object from database. |
---
### Tags (Class)
Singleton class managing tag definitions with in-memory caching.
**Nested Class: Tag**
| Member | Type/Signature | Description |
|--------|----------------|-------------|
| `INVALID_ID` | `const int = -1` | Constant for invalid tag ID. |
| `ID` | `int` | Tag identifier. |
| `Text` | `string` | Tag display text. |
| `IsObsolete` | `bool` | Obsolescence flag. |
| `Tag(string tagText, int tagId)` | Constructor | Creates tag with text and ID. |
| `Tag(Tag copy)` | Constructor | Copy constructor. |
| `Tag(IDataRecord reader)` | Constructor | Constructs from data reader. |
| `Tag(DataRow dr)` | Constructor | Constructs from data row. |
| `Clone()` | `object` | ICloneable implementation. |
**Static Property:**
- `TagsInstance` - Singleton instance (lazy-initialized).
**Static Methods:**
| Method | Return Type | Description |
|--------|-------------|-------------|
| `AddTag(string tagText)` | `bool` | Adds tag to DB if not in cache; returns false if already exists or null/empty. |
| `MigrateTag(string tagText)` | `bool` | Adds tag during migration (commits even if exists). |
| `AddRange(string[] tagText)` | `bool[]` | Adds multiple tags with start-trimming; returns null if input is null/empty. |
| `GetIDFromTagText(string tagText)` | `int` | Gets tag ID from database by text. |
| `GetIDsFromTagText(string[] tagText)` | `int[]` | Gets array of IDs for tag texts; filters out INVALID_ID. |
| `GetTagTextFromID(int tagID)` | `string` | Gets tag text from cache by ID; returns null if invalid/not found. |
| `GetTagTextFromIDs(int[] tagId)` | `string[]` | Gets tag texts for IDs; skips invalid/null results. |
**Instance Methods:**
| Method | Signature | Description |
|--------|-----------|-------------|
| `ContainsTag` | `bool ContainsTag(string text)` | Checks if tag text exists in cache. |
| `UpdateList` | `void UpdateList()` | Refreshes cache from database. |
---
### UserCollection (Class)
Singleton managing user persistence and retrieval with thread-safe access.
**Event:**
- `PropertyChanged` - Implements `INotifyPropertyChanged`.
**Static Property:**
- `UsersList` - Singleton instance (thread-safe, lazy-initialized).
**Static Methods:**
| Method | Signature | Description |
|--------|-----------|-------------|
| `GetUserToTagIdLookup` | `Dictionary<int, List<int>> GetUserToTagIdLookup()` | Returns mapping of user IDs to tag ID lists. |
| `GetAllUsers` | `User[] GetAllUsers(IUIItems[] allItems, int? uid = null)` | Gets all users or single user if uid specified. Auto-creates default users. |
| `GetUser` | `User GetUser(int uid, IUIItems[] items)` | Gets user by ID. |
| `GetUser` | `User GetUser(string username, IUIItems[] items)` | Gets user by username. |
**Instance Methods:**
| Method | Signature | Description |
|--------|-----------|-------------|
| `Commit` | `void Commit(User user, string username, IUIItems[] items)` | Inserts/updates user, settings, permissions, and tags. Raises PropertyChanged. |
| `Delete` | `void Delete(User user)` | Deletes a user from database. |
| `Delete` | `void Delete(User[] users)` | Deletes multiple users. |
---
## 3. Invariants
1. **TagIDs never null**: `TagIDs` property always returns an array; setter converts null to `new int[0]`.
2. **Tag cache thread-safety**: All access to `_tagsLookup` in `Tags` class is protected by `LOCK_OBJECT`.
3. **UserCollection singleton thread-safety**: Access to `_userList` is protected by `MyLock`.
4. **Invalid tag ID constant**: `Tag.INVALID_ID` is always `-1`. Values ≤ 0 or equal to `INVALID_ID` are treated as invalid.
5. **Tag trimming**: Tags are trimmed at the start (not end) when added via `AddRange`.
6. **Default user auto-creation**: `GetAllUsers` automatically creates default role users and non-default power users if they don't exist in the database.
7. **TagsBlobBytes format**: Serialized as 4-byte integers via `Buffer.BlockCopy`.
---
## 4. Dependencies
### This module depends on:
- `System.Windows.Forms` - For `ChallengeDialog` UI components
- `System.Data.SqlClient` - For database operations
- `DTS.Common.Storage` - For `DbOperations` and `DbOperationsEnum`
- `DTS.Common.Utilities.Logging` - For `APILogger`
- `DTS.Common.Classes` - Referenced in `UserCollection`
- `DTS.Common.Interface.Tags` - Referenced in `UserCollection`
- `DTS.Slice.Users.UserSettings` - For `TestSetupDefaults` and `Defaults`
- `Common.Base.BasePropertyChanged` - Base class for `TagAwareBase`
### External dependencies inferred:
- `User` class (referenced but not in provided source files)
- `DbOperations` static class for database command creation
- `DbOperations.Connection` for query execution
---
## 5. Gotchas
1. **RemoveTags is not implemented**: `TagAwareBase.RemoveTags(string[] tagsText)` has an empty method body with only a comment `// remove tags!!!` and `-;`. Calling this method does nothing.
2. **Tags cache staleness**: The `_tagsLookup` cache in `Tags` is only populated on construction and when `UpdateList()` is explicitly called. `AddTag` updates the cache, but external tag additions won't be reflected.
3. **GetAllUsers dual-purpose behavior**: The method serves two purposes based on the `uid` parameter. When `uid` is null, it auto-creates default users; when `uid` has a value, it returns only that user without auto-creation.
4. **ChallengeDialog has no event handlers**: The `btnContinue` and `btnCancel` buttons have no click events wired in the designer. The calling code must attach handlers.
5. **Error parameters ignored**: Stored procedure calls retrieve `@errorNumber` and `@errorMessage` output parameters, but the error message is never used—only the error number is checked against zero.
6. **Commented-out code references bug tracker**: A commented-out null check in `SetTagsFromCommaSeparatedString` references `http://fogbugz/fogbugz/default.asp?7176`, suggesting historical bug context.
7. **Tag trimming is asymmetric**: `AddRange` trims only the start of tags (`TrimStart()`), not the end.
8. **UpdateAll does nothing**: `Tags.UpdateAll(Tag tag)` only sets the ID from existing text; the comment indicates rename/edit/delete features are not implemented.