Skip to content

Conversation

@ImMohammad20000
Copy link
Contributor

@ImMohammad20000 ImMohammad20000 commented Nov 26, 2025

Summary by CodeRabbit

  • New Features

    • Bulk user creation from templates with configurable username generation strategies (random or sequential)
    • New API endpoint for creating multiple users simultaneously with automatic subscription URL generation
    • Telegram bot integration for template-based bulk user creation workflows
  • Tests

    • Added test coverage for bulk creation with random and sequential username strategies

✏️ Tip: You can customize this high-level summary in your review settings.

@ImMohammad20000 ImMohammad20000 added the enhancement New feature or request label Nov 26, 2025
@coderabbitai
Copy link

coderabbitai bot commented Nov 26, 2025

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Walkthrough

Bulk user creation feature from templates is added, enabling creation of multiple users with configurable username strategies (random or sequence). The feature spans database operations, models, API endpoints, and Telegram handlers with validation and subscription URL generation.

Changes

Cohort / File(s) Summary
Database CRUD Layer
app/db/crud/user.py
Added get_existing_usernames() helper to check if usernames exist in database, and create_users_bulk() for bulk user insertion with batch commits, group/admin association, and attribute loading.
Data Models & Validation
app/models/user.py
Introduced UsernameGenerationStrategy enum (random/sequence), BulkCreationBase with count and strategy fields, BulkUsersFromTemplate with strategy validation logic, and BulkUsersCreateResponse for API responses.
Business Logic Layer
app/operation/user.py
Added bulk creation orchestration via bulk_create_users_from_template() and supporting internal methods: _generate_usernames() for random/sequence strategies, _build_bulk_user_models(), _filter_existing_usernames(), _persist_bulk_users(), _build_user_create_from_template(), and _format_validation_errors().
API Endpoints
app/routers/user.py
Added POST endpoint s/bulk/from_template returning BulkUsersCreateResponse, delegating to bulk_create_users_from_template() operation.
Telegram Handler Layer
app/telegram/handlers/admin/bulk_actions.py
Added multi-step FSM flow for bulk creation: bulk_create_from_template(), bulk_template_chosen(), bulk_template_count(), bulk_template_strategy(), bulk_template_sequence_username(), bulk_template_start_number(), and _perform_bulk_creation() with URL chunking and message routing.
Telegram UI/State Management
app/telegram/keyboards/bulk_actions.py, app/telegram/utils/forms.py, app/telegram/utils/texts.py
Extended BulkAction enum with create_from_template, added BulkTemplateSelector and UsernameStrategySelector keyboard builders, BulkCreateFromTemplate FSM state group, and new message/button labels for bulk workflows.
Tests
tests/api/test_user.py
Added three test functions covering sequence strategy, random strategy, and validation rejection scenarios for bulk template-based creation.

Sequence Diagram(s)

sequenceDiagram
    participant User as Admin
    participant API as API Endpoint
    participant Op as UserOperation
    participant CRUD as CRUD Layer
    participant DB as Database

    User->>API: POST /s/bulk/from_template<br/>(count, strategy, username, ...)
    API->>Op: bulk_create_users_from_template()
    
    activate Op
    Op->>Op: Validate template & strategy
    
    alt Strategy == Random
        Op->>Op: _generate_usernames(strategy=random)
        Note over Op: Generate random usernames<br/>(count times)
    else Strategy == Sequence
        Op->>Op: _generate_usernames(strategy=sequence,<br/>base_username, start_number)
        Note over Op: Generate sequential usernames<br/>(base_username + suffix)
    end
    
    Op->>Op: _build_bulk_user_models(usernames)
    Note over Op: Construct UserCreate models<br/>from candidate usernames
    
    Op->>Op: _filter_existing_usernames(new_users)
    Op->>CRUD: Check DB for existing usernames
    CRUD->>DB: Query users table
    DB-->>CRUD: Existing usernames
    CRUD-->>Op: UserCreate list (duplicates removed)
    
    Op->>Op: _persist_bulk_users(filtered_users)
    Op->>CRUD: create_users_bulk(users, groups, admin)
    CRUD->>DB: Batch insert users + associations
    DB-->>CRUD: Created user records
    CRUD-->>Op: Created User list + attributes
    
    Op->>Op: Generate subscription URLs
    Op->>Op: Emit notifications
    
    deactivate Op
    Op-->>API: BulkUsersCreateResponse<br/>(created_count, subscription_urls)
    API-->>User: 201 with URLs
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Areas requiring extra attention:

  • app/operation/user.py — Multiple helper methods with distinct logic paths; strategy-dependent validation in _generate_usernames() and _build_user_create_from_template() warrant careful review for edge cases and error handling.
  • app/telegram/handlers/admin/bulk_actions.py — FSM state flow across six route handlers with branching logic (e.g., random strategy bypassing username/start_number prompts); verify state transitions, message routing via _message_target(), and URL chunking correctness.
  • app/models/user.py — Post-validation logic in BulkUsersFromTemplate.validate_username_strategy() enforces mutually exclusive field constraints; confirm validation rules align with operation expectations.
  • tests/api/test_user.py — Verify test setup/teardown (template and user cleanup) is complete and that assertions capture both success and validation-error scenarios.

Poem

🐰 Bulk users hop in, quite a feat!
Random and sequence, strategies sweet,
Templates spawn many with one swift request,
Subscription URLs delivered in a burst,
Batch creation bounding through databases anew! 🚀

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 15.91% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature: bulk user creation from templates with configurable username strategies (random and sequence).

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@ImMohammad20000
Copy link
Contributor Author

@coderabbitai review

@coderabbitai
Copy link

coderabbitai bot commented Nov 26, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (3)
app/telegram/keyboards/bulk_actions.py (1)

60-74: Consider using adjust(1, repeat=True) for consistency.

The adjust(1, 1) call only sets layout for the first two buttons (random and sequence), but there are three buttons including the back button. While this may work due to default behavior, using adjust(1, repeat=True) would be more explicit and consistent with BulkTemplateSelector (line 57).

-        self.adjust(1, 1)
+        self.adjust(1, repeat=True)
app/operation/user.py (1)

129-141: Dead code: width is always 0, making zfill ineffective.

The width variable is initialized to 0 and never updated, so the condition if width: (line 137) is always false, and the zfill(width) call never executes. If zero-padding is intended for sequence usernames, width needs to be calculated or made configurable. Otherwise, these lines can be simplified.

             prefix = base_username
-            width = 0
-            inferred_start_number = 1

             generated: list[str] = []
-            current = start_number if start_number is not None else inferred_start_number
+            current = start_number if start_number is not None else 1
             for _ in range(count):
-                suffix = str(current)
-                if width:
-                    suffix = suffix.zfill(width)
-                generated.append(f"{prefix}{suffix}")
+                generated.append(f"{prefix}{current}")
                 current += 1
             return generated
app/telegram/handlers/admin/bulk_actions.py (1)

108-130: Minor inconsistency: stored strategy value is unused.

Line 127 stores strategy.value in state, but bulk_template_start_number hardcodes UsernameGenerationStrategy.sequence on line 197 rather than retrieving it. This works correctly since only the sequence path reaches that handler, but consider removing the unused state update or using the stored value for consistency.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 110c2e2 and 558737d.

📒 Files selected for processing (9)
  • app/db/crud/user.py (3 hunks)
  • app/models/user.py (2 hunks)
  • app/operation/user.py (8 hunks)
  • app/routers/user.py (2 hunks)
  • app/telegram/handlers/admin/bulk_actions.py (1 hunks)
  • app/telegram/keyboards/bulk_actions.py (3 hunks)
  • app/telegram/utils/forms.py (1 hunks)
  • app/telegram/utils/texts.py (5 hunks)
  • tests/api/test_user.py (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (7)
app/telegram/keyboards/bulk_actions.py (2)
app/models/user.py (1)
  • UsernameGenerationStrategy (195-197)
app/telegram/keyboards/admin.py (3)
  • AdminPanel (17-43)
  • AdminPanelAction (9-14)
  • Callback (18-19)
tests/api/test_user.py (5)
tests/api/conftest.py (1)
  • access_token (440-445)
tests/api/test_bulk.py (1)
  • setup_groups (16-19)
tests/api/helpers.py (4)
  • create_user_template (154-176)
  • unique_name (12-13)
  • delete_user (149-151)
  • delete_user_template (179-181)
app/routers/user_template.py (1)
  • create_user_template (19-32)
app/db/models.py (2)
  • group_ids (210-211)
  • group_ids (346-347)
app/telegram/utils/texts.py (1)
app/telegram/handlers/admin/bulk_actions.py (1)
  • bulk_create_from_template (66-73)
app/db/crud/user.py (1)
app/db/models.py (6)
  • DataLimitResetStrategy (113-118)
  • User (121-282)
  • expire (164-167)
  • expire (170-171)
  • expire (174-175)
  • NextPlan (303-313)
app/telegram/handlers/admin/bulk_actions.py (8)
app/models/validators.py (1)
  • validate_username (127-141)
app/operation/__init__.py (1)
  • OperatorType (27-33)
app/operation/user.py (1)
  • bulk_create_users_from_template (617-661)
app/operation/user_template.py (2)
  • UserTemplateOperation (21-68)
  • get_user_templates (65-68)
app/telegram/keyboards/base.py (2)
  • CancelKeyboard (12-19)
  • Callback (18-19)
app/telegram/keyboards/bulk_actions.py (7)
  • BulkActionPanel (19-40)
  • BulkAction (12-16)
  • BulkTemplateSelector (43-57)
  • UsernameStrategySelector (60-74)
  • Callback (20-22)
  • Callback (44-45)
  • Callback (61-62)
app/telegram/utils/forms.py (1)
  • BulkCreateFromTemplate (26-30)
app/models/user_template.py (1)
  • validate_username (45-46)
app/models/user.py (2)
app/telegram/utils/forms.py (1)
  • CreateUserFromTemplate (13-14)
dashboard/src/service/api/index.ts (1)
  • CreateUserFromTemplate (1641-1645)
app/routers/user.py (5)
app/models/user.py (2)
  • BulkUsersCreateResponse (225-227)
  • BulkUsersFromTemplate (205-222)
app/operation/user.py (1)
  • bulk_create_users_from_template (617-661)
app/db/base.py (1)
  • get_db (57-59)
app/models/admin.py (1)
  • AdminDetails (48-64)
app/routers/authentication.py (1)
  • get_current (37-52)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: test-databases (timescaledb)
🔇 Additional comments (22)
app/db/crud/user.py (2)

80-89: LGTM!

The get_existing_usernames function is well-implemented with proper early exit for empty input and efficient IN query for batch lookup.


506-544: LGTM!

The bulk creation function properly handles:

  • Early exit for empty input
  • Correct group assignment using list(groups) to avoid shared reference issues
  • Proper sequencing with flush before NextPlan creation to ensure user IDs are available
  • Single commit at the end for atomicity
app/telegram/utils/texts.py (1)

34-34: LGTM!

The new button labels, prompts, and messages are clear, consistent with existing patterns, and properly support the bulk creation workflow.

Also applies to: 48-49, 64-68, 79-80, 270-277

app/telegram/utils/forms.py (1)

26-31: LGTM!

The new BulkCreateFromTemplate state group properly captures all required fields for the Telegram-based bulk creation workflow.

app/routers/user.py (1)

320-341: LGTM!

The new bulk creation endpoint is well-structured with:

  • Appropriate HTTP 201 status for resource creation
  • Comprehensive error responses (400, 403, 404, 409)
  • Clear documentation of the strategy options and parameters
  • Consistent authentication pattern with existing template-based creation
tests/api/test_user.py (3)

356-394: LGTM!

The sequence strategy test comprehensively validates:

  • Correct username generation with start_number offset
  • Proper template attribute inheritance (data_limit, status)
  • Subscription URL generation
  • Proper cleanup in finally block

397-434: LGTM!

The random strategy test properly validates the bulk creation flow and uses group filtering to retrieve created users for verification and cleanup.


437-457: LGTM!

Good negative test case validating that the API correctly rejects invalid combinations (random strategy with username) with HTTP 422.

app/models/user.py (1)

195-227: LGTM!

The new models are well-designed:

  • UsernameGenerationStrategy enum cleanly defines the two strategies
  • BulkCreationBase enforces count bounds (1-500) with sensible default
  • BulkUsersFromTemplate properly overrides username to be optional and includes comprehensive validation via model_validator
  • The validator correctly enforces mutual exclusivity rules between strategy and username/start_number fields
app/operation/user.py (6)

74-78: LGTM!

Clean utility method for formatting Pydantic validation errors into readable strings.


145-164: LGTM!

The method correctly handles bulk model building by:

  • Deduplicating candidate usernames locally
  • Silently skipping invalid usernames (appropriate for bulk operations to maximize throughput)
  • Returning only successfully built models

166-174: LGTM!

Efficient filtering with proper early exit and set-based lookup for O(1) existence checks.


176-196: LGTM!

The persistence method properly:

  • Handles empty input with early exit
  • Uses bulk insert for efficiency
  • Generates subscription URLs after successful creation
  • Fires off notifications asynchronously
  • Logs each creation for audit purposes

558-575: LGTM!

Clean extraction of user creation logic from template. The method properly:

  • Applies template's username prefix/suffix
  • Formats validation errors for clear API responses
  • Applies template settings after model construction

617-661: LGTM!

The bulk creation orchestration is well-structured:

  • Validates template before proceeding
  • Generates candidate usernames based on strategy
  • Filters existing usernames to prevent conflicts
  • Groups are validated once (all users share template groups)
  • Returns comprehensive response with subscription URLs and count

The duplicate validation of strategy/username (also in model) provides defense-in-depth.

app/telegram/handlers/admin/bulk_actions.py (7)

10-29: LGTM!

The imports and global initialization follow the existing patterns in the file (matching user_operations). The new dependencies align with the bulk creation feature requirements.


34-36: LGTM!

Clean helper for polymorphic event handling.


38-58: LGTM!

The chunking logic correctly accounts for newline separators and respects the Telegram message limit with adequate headroom.


65-73: LGTM!

The handler correctly initiates the bulk creation flow. The template fetch returns all templates; disabled templates are filtered at creation time in the operation layer.


76-105: LGTM!

The flow correctly captures the template selection and validates the count within acceptable bounds (1-500).


160-179: LGTM!

The start number validation correctly handles optional input (empty string → None) and validates non-negative integers.


138-144: The original review comment is incorrect. UserValidator.validate_username is properly implemented as a static method in app/models/validators.py (line 127) and can be called exactly as shown in line 140 of bulk_actions.py. The method exists, is correctly imported, and follows the same usage pattern found throughout the codebase (e.g., in user.py and user_template.py).

@ImMohammad20000 ImMohammad20000 merged commit 2604c6b into dev Nov 28, 2025
16 checks passed
@ImMohammad20000 ImMohammad20000 deleted the bulk-users branch November 28, 2025 10:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants