223 lines
11 KiB
Markdown
223 lines
11 KiB
Markdown
|
|
---
|
||
|
|
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.
|