Skip to content

Conversation

@Boy132
Copy link
Member

@Boy132 Boy132 commented Jan 6, 2026

@Boy132 Boy132 self-assigned this Jan 6, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 6, 2026

📝 Walkthrough

Walkthrough

Adds a new ResourceLimit enum registering per-server resource rate limiters and applies them to client API routes; lowers client API default rate limit; replaces daemon revokeUserJTI calls with deauthorize; consolidates several creation flows into DB transactions with lockForUpdate and transactional logging; relaxes node upload_size validation; adds migration to clear orphan allocation notes.

Changes

Cohort / File(s) Summary of changes
Resource rate limiting
app/Enums/ResourceLimit.php, app/Providers/RouteServiceProvider.php, routes/api-client.php, config/http.php
New ResourceLimit enum (throttleKey, middleware, limit, boot); ResourceLimit::boot() invoked from RouteServiceProvider; resource middleware applied to multiple client routes; client API default rate reduced from 720120.
Daemon deauthorization (repo, services & tests)
app/Repositories/Daemon/DaemonServerRepository.php, app/Services/Servers/DetailsModificationService.php, app/Services/Subusers/SubuserDeletionService.php, app/Services/Subusers/SubuserUpdateService.php, tests/Integration/.../DeleteSubuserTest.php, tests/Integration/.../SubuserAuthorizationTest.php
Added deauthorize(string $user) (POST /api/deauthorize-user); revokeUserJTI() deprecated; callers updated to deauthorize($user->uuid); SubuserUpdateService now logs warnings and sets log.revoked = false on ConnectionException; tests updated accordingly.
Transactional locking & consolidated logging
app/Http/Controllers/Api/Client/Servers/BackupController.php, app/Http/Controllers/Api/Client/Servers/DatabaseController.php, app/Http/Controllers/Api/Client/Servers/NetworkAllocationController.php
Creation flows wrapped in Activity::event(...)->transaction(...); relations acquire lockForUpdate() before counts/creates; logging consolidated inside transaction; results returned from transaction closure.
Node upload size validation & admin forms
app/Models/Node.php, app/Filament/Admin/Resources/Nodes/Pages/CreateNode.php, app/Filament/Admin/Resources/Nodes/Pages/EditNode.php, lang/en/admin/node.php
Relaxed upload_size validation from ['int','between:1,1024']['int','min:1']; removed maxValue(1024) from Filament forms; upload_limit_help changed from array to single string.
Server deletion allocation cleanup & DB migration
app/Services/Servers/ServerDeletionService.php, database/migrations/2026_01_09_134116_clear_unused_allocation_notes.php
During server deletion, detached allocations now also clear notes (notes = null); new migration clears notes for allocations where server_id is NULL.
Config / backup settings
config/backups.php, app/Http/Controllers/Api/Remote/Backups/BackupRemoteUploadController.php
Casts environment config values to int for presigned lifespan, max part size, prune age, and throttle values; max_part_size falls back to controller constant; minor change in part size retrieval.
Docs / text fixes
app/Extensions/OAuth/Schemas/GithubSchema.php, contributing.md, security.md, lang/en/admin/node.php
Minor wording/label updates (e.g., "Github" → "GitHub") and formatting tweaks; language key type changed for upload help.
Middleware ordering / bootstrap
bootstrap/app.php
Adds middleware priority configuration to ensure SubstituteBindings runs earlier.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant Router
  participant Middleware as ResourceLimitMiddleware
  participant RateLimiter
  participant DB as ServerModel
  participant Controller

  Client->>Router: HTTP request to protected client route
  Router->>Middleware: apply ResourceLimit::X->middleware()
  Middleware->>RateLimiter: compute throttle key (resource + server UUID)
  RateLimiter->>DB: resolve Server from request (validate/lookup)
  DB-->>RateLimiter: return server UUID
  RateLimiter->>RateLimiter: check/apply per-server RateLimit
  alt allowed
    Middleware->>Controller: forward request
    Controller->>DB: perform action (may use lockForUpdate inside transaction)
    DB-->>Controller: result
    Controller-->>Client: success response
  else throttled
    Middleware-->>Client: 429 Too Many Requests
  end
Loading
🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 73.91% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'Add changes from upstream' is vague and does not clearly convey the specific nature of the changes made in this pull request. Replace with a more descriptive title that summarizes the main changes, such as 'Add resource limiting, improve transaction handling, and update configuration casting' or reference the primary feature being introduced.
✅ Passed checks (1 passed)
Check name Status Explanation
Description check ✅ Passed The description references upstream commits and dependencies, providing context about the sync; while not deeply descriptive of each change, it is related to the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


📜 Recent review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c89aa4f and a28111e.

📒 Files selected for processing (2)
  • app/Http/Controllers/Api/Remote/Backups/BackupRemoteUploadController.php
  • config/backups.php
🧰 Additional context used
🧬 Code graph analysis (1)
config/backups.php (1)
app/Http/Controllers/Api/Remote/Backups/BackupRemoteUploadController.php (1)
  • BackupRemoteUploadController (21-141)
🔇 Additional comments (6)
app/Http/Controllers/Api/Remote/Backups/BackupRemoteUploadController.php (1)

132-140: LGTM! Type casting appropriately centralized.

The removal of the explicit (int) cast is consistent with config/backups.php now handling type coercion (line 19). The method's : int return type provides type safety, and the validation logic correctly handles edge cases.

config/backups.php (5)

3-3: LGTM! Import supports constant reference.

The import enables referencing DEFAULT_MAX_PART_SIZE on line 19, eliminating the hardcoded 5GB value and establishing a single source of truth.


14-14: LGTM! Type safety improvement aligns with PR objective.

Explicitly casting presigned_url_lifespan to int ensures type safety for the addMinutes() call in BackupRemoteUploadController (line 79) and fulfills the stated PR objective.


19-19: LGTM! Dual improvement: type safety and maintainability.

This change provides two benefits:

  1. Explicit (int) cast ensures type safety
  2. Using BackupRemoteUploadController::DEFAULT_MAX_PART_SIZE replaces the hardcoded 5GB value, establishing a single source of truth

23-23: LGTM! Consistent type safety improvement.

The explicit cast to int for prune_age ensures type consistency when the value originates from environment variables.


31-32: LGTM! Type safety for throttle configuration.

Both throttle values are appropriately cast to int, ensuring type consistency for limit (count) and period (seconds) values.


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.

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: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
app/Models/Node.php (1)

83-91: Remove duplicate 'description' entry.

The 'description' field appears twice in the $fillable array (lines 84 and 90), which is redundant.

🔎 Proposed fix
 protected $fillable = [
-    'public', 'name', 'description',
+    'public', 'name',
     'fqdn', 'scheme', 'behind_proxy',
     'memory', 'memory_overallocate', 'disk',
     'disk_overallocate', 'cpu', 'cpu_overallocate',
     'upload_size', 'daemon_base',
     'daemon_sftp', 'daemon_sftp_alias', 'daemon_listen', 'daemon_connect',
     'description', 'maintenance_mode', 'tags',
 ];
🤖 Fix all issues with AI Agents
In @app/Http/Controllers/Api/Client/Servers/DatabaseController.php:
- Around line 62-70: The lockForUpdate() call on the Eloquent relation in
DatabaseController (the $server->databases()->lockForUpdate() inside the
Activity::event(...) transaction) does not execute a query and therefore does
not acquire the row lock; change that call to execute the query (for example
replace it with $server->databases()->lockForUpdate()->get()) so the lock is
actually acquired before calling deployDatabaseService->handle; apply the same
fix in BackupController where a similar $server->...->lockForUpdate() is used
(use ->get() or another terminating method like ->count()).

In @app/Repositories/Daemon/DaemonServerRepository.php:
- Around line 154-162: The deauthorize method is sending the payload wrapped
under a 'json' key (Guzzle style) which results in {"json": {...}} being posted;
update the deauthorize method (the post call on getHttpClient()) to send the
body array directly (match how create() and revokeUserJTI() pass data) so the
request payload is {"user": "...", "servers": [...]} rather than wrapped,
preserving the same keys ('user' and 'servers') and keeping the server UUID from
$this->server->uuid.

In @tests/Integration/Api/Client/Server/Subuser/DeleteSubuserTest.php:
- Line 45: The test mock for the server deauthorization call is expecting an
integer ID but the implementation calls deauthorize with the subuser's UUID
string; update the two expectations on the mock for setServer->deauthorize
(currently using $subuser->id) to use $subuser->uuid instead so they match the
method signature public function deauthorize(string $user): void and correctly
validate UUID usage.

In @tests/Integration/Api/Client/Server/Subuser/SubuserAuthorizationTest.php:
- Line 40: The test is calling deauthorize with the wrong type: update the mock
expectation so deauthorize() receives the UUID string rather than the integer
id; replace the argument $internal->id with $internal->uuid in the mock
expectation (the line using $mock->expects('setServer->deauthorize')->with(...))
so it matches the method signature deauthorize(string $user) and production
usage.
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6ebeb40 and 5060038.

📒 Files selected for processing (20)
  • app/Enums/ResourceLimit.php
  • app/Extensions/OAuth/Schemas/GithubSchema.php
  • app/Filament/Admin/Resources/Nodes/Pages/CreateNode.php
  • app/Filament/Admin/Resources/Nodes/Pages/EditNode.php
  • app/Http/Controllers/Api/Client/Servers/BackupController.php
  • app/Http/Controllers/Api/Client/Servers/DatabaseController.php
  • app/Http/Controllers/Api/Client/Servers/NetworkAllocationController.php
  • app/Models/Node.php
  • app/Providers/RouteServiceProvider.php
  • app/Repositories/Daemon/DaemonServerRepository.php
  • app/Services/Servers/DetailsModificationService.php
  • app/Services/Servers/ServerDeletionService.php
  • app/Services/Subusers/SubuserDeletionService.php
  • app/Services/Subusers/SubuserUpdateService.php
  • config/http.php
  • contributing.md
  • routes/api-client.php
  • security.md
  • tests/Integration/Api/Client/Server/Subuser/DeleteSubuserTest.php
  • tests/Integration/Api/Client/Server/Subuser/SubuserAuthorizationTest.php
💤 Files with no reviewable changes (1)
  • app/Filament/Admin/Resources/Nodes/Pages/CreateNode.php
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-08-12T17:33:57.388Z
Learnt from: lancepioch
Repo: pelican-dev/panel PR: 1595
File: app/Services/Servers/ServerCreationService.php:182-184
Timestamp: 2025-08-12T17:33:57.388Z
Learning: In the Pelican Panel codebase, when updating allocations to assign them to servers, the preferred pattern is to use whereNull('server_id'), lockForUpdate(), and direct property assignment with save() rather than mass update methods, to prevent race conditions and mass-assignment issues while ensuring model events fire properly.

Applied to files:

  • app/Services/Servers/ServerDeletionService.php
  • app/Http/Controllers/Api/Client/Servers/NetworkAllocationController.php
📚 Learning: 2025-11-05T22:21:31.863Z
Learnt from: notAreYouScared
Repo: pelican-dev/panel PR: 1865
File: app/Filament/Admin/Resources/Nodes/Pages/EditNode.php:682-682
Timestamp: 2025-11-05T22:21:31.863Z
Learning: In app/Filament/Admin/Resources/Nodes/Pages/EditNode.php, the diagnostics tab's upload action intentionally does not use the iconButton() modifier, while the pull action does. This UI difference is intentional.

Applied to files:

  • app/Filament/Admin/Resources/Nodes/Pages/EditNode.php
🧬 Code graph analysis (8)
app/Services/Servers/ServerDeletionService.php (1)
app/Models/Node.php (1)
  • allocations (267-270)
app/Services/Servers/DetailsModificationService.php (2)
app/Repositories/Daemon/DaemonRepository.php (1)
  • setServer (24-31)
app/Repositories/Daemon/DaemonServerRepository.php (1)
  • deauthorize (154-162)
app/Providers/RouteServiceProvider.php (1)
app/Enums/ResourceLimit.php (1)
  • boot (55-64)
app/Http/Controllers/Api/Client/Servers/NetworkAllocationController.php (5)
app/Models/Server.php (2)
  • allocation (296-299)
  • allocations (306-309)
app/Services/Activity/ActivityLogService.php (3)
  • transaction (173-182)
  • log (136-155)
  • property (109-117)
app/Models/Allocation.php (1)
  • server (129-132)
app/Models/ServerTransfer.php (1)
  • server (76-79)
app/Exceptions/DisplayException.php (1)
  • DisplayException (19-99)
app/Http/Controllers/Api/Client/Servers/DatabaseController.php (3)
app/Services/Activity/ActivityLogService.php (4)
  • event (48-53)
  • transaction (173-182)
  • log (136-155)
  • property (109-117)
app/Models/Database.php (1)
  • server (84-87)
app/Models/Server.php (1)
  • databases (378-381)
app/Services/Subusers/SubuserDeletionService.php (2)
app/Repositories/Daemon/DaemonRepository.php (1)
  • setServer (24-31)
app/Repositories/Daemon/DaemonServerRepository.php (1)
  • deauthorize (154-162)
app/Services/Subusers/SubuserUpdateService.php (2)
app/Repositories/Daemon/DaemonRepository.php (1)
  • setServer (24-31)
app/Repositories/Daemon/DaemonServerRepository.php (1)
  • deauthorize (154-162)
routes/api-client.php (1)
app/Enums/ResourceLimit.php (1)
  • middleware (38-41)
🔇 Additional comments (20)
app/Services/Servers/ServerDeletionService.php (1)

81-84: LGTM! Proper cleanup of allocation notes during server deletion.

The addition of clearing the notes field alongside server_id ensures that allocations are fully reset when a server is deleted, making them ready for reuse without residual data.

The mass update approach within the transaction is appropriate for this cleanup scenario and provides good performance.

app/Http/Controllers/Api/Client/Servers/NetworkAllocationController.php (1)

110-120: Excellent implementation of allocation creation with proper concurrency control.

The transactional approach with lockForUpdate() correctly prevents race conditions when enforcing the allocation limit. By locking existing allocations before counting, this ensures that concurrent requests for the same server are serialized—preventing multiple requests from simultaneously seeing "under limit" and creating allocations that exceed the configured maximum.

The pattern aligns with best practices: acquiring locks, validating constraints, creating resources, and logging activity all within a single atomic transaction.

Based on learnings, the lockForUpdate() pattern is the preferred approach for allocation operations to prevent race conditions.

app/Providers/RouteServiceProvider.php (1)

102-103: LGTM! Resource-based rate limiting properly bootstrapped.

The placement of ResourceLimit::boot() at the end of configureRateLimiting() is appropriate, ensuring that per-resource rate limiters are registered after the base API rate limiters.

app/Extensions/OAuth/Schemas/GithubSchema.php (2)

21-21: LGTM! Correct branding applied.

The step label has been updated to use the correct "GitHub" capitalization.


25-25: LGTM! Correct branding applied.

The HTML link text has been updated to use the correct "GitHub" capitalization.

contributing.md (1)

11-11: LGTM! Correct branding applied.

The documentation has been updated to use the correct "GitHub" capitalization.

config/http.php (1)

16-16: The claim about reducing the rate limit from 720 to 120 cannot be verified.

The config/http.php file is new to this codebase—it wasn't modified from a previous value. Additionally, the ResourceLimit enum provides per-resource rate limiting that is already in place and adequately restrictive:

  • Creation operations: 2–10 requests per 10–15 minutes (per server)
  • Websocket: 5 requests per minute
  • Backup restore: 3 requests per 15 minutes

These per-resource limits are applied per-server (not per-user) and complement the global 120 requests/minute limit. The rate limiting strategy is properly implemented without evidence of any 83% reduction occurring.

Likely an incorrect or invalid review comment.

app/Filament/Admin/Resources/Nodes/Pages/EditNode.php (1)

323-326: The upload_size field validation is properly configured with only a minimum constraint.

The field in EditNode.php (lines 323-326) and CreateNode.php correctly enforce minValue(1) with no maximum limit, aligning with the PR objective to accept any positive integer. This is consistent with the Node model validation rule ('upload_size' => ['int', 'min:1']). The upload_size value is properly passed to the daemon as upload_limit in the Node model configuration. No changes are needed here.

app/Models/Node.php (1)

113-113: LGTM: Upload size validation relaxed.

The validation correctly removes the upper bound constraint, allowing any positive integer as specified in the PR objectives. This provides more flexibility for node configurations with large upload requirements.

app/Http/Controllers/Api/Client/Servers/BackupController.php (2)

86-86: LGTM: Proper boolean input handling.

Using $request->boolean('is_locked') is more explicit and type-safe compared to the generic input() method.


89-100: Verify lockForUpdate() usage - lock may not be acquired.

Similar to the DatabaseController, $server->backups()->lockForUpdate() on line 90 does not execute a query and therefore doesn't acquire a lock. The lockForUpdate() method requires a terminating call like get(), first(), or count() to execute.

This pattern appears in multiple controllers in this PR, suggesting it may be an upstream pattern. Please verify the intended locking behavior.

routes/api-client.php (1)

3-3: LGTM: Resource-based rate limiting properly applied.

The addition of ResourceLimit middleware to resource creation endpoints follows a consistent pattern and aligns with the PR objective to add throttling. The middleware is appropriately applied to operations that could be resource-intensive or subject to abuse:

  • WebSocket connections
  • Database creation
  • File pulling
  • Schedule creation
  • Allocation creation
  • Subuser creation
  • Backup restoration

Also applies to: 54-56, 65-66, 83-84, 90-91, 104-105, 113-114, 127-128

app/Services/Servers/DetailsModificationService.php (1)

51-51: LGTM: Correctly migrated to UUID-based deauthorization.

The change from revokeUserJTI($owner) to deauthorize($server->user->uuid) correctly uses the owner's UUID for the new deauthorization method. The error handling remains appropriate for daemon connectivity issues.

app/Services/Subusers/SubuserUpdateService.php (1)

49-56: LGTM: Correct UUID usage with improved error handling.

The migration to deauthorize($subuser->user->uuid) correctly uses the UUID string. The enhanced error handling with contextual logging is a good improvement over the previous silent catch.

app/Services/Subusers/SubuserDeletionService.php (1)

31-37: LGTM: Correct UUID usage with appropriate error handling.

The change to deauthorize($subuser->user->uuid) correctly uses the UUID string. The error handling with contextual logging and the revoked flag update ensures graceful degradation when the daemon is unreachable.

security.md (1)

11-13: LGTM: Improved formatting for vulnerability reporting.

The markdown formatting improvements enhance readability and provide proper linking for the security advisory submission.

app/Repositories/Daemon/DaemonServerRepository.php (1)

136-147: LGTM!

The deprecation annotation with @see reference to the new method is appropriate and provides clear migration guidance.

app/Enums/ResourceLimit.php (3)

18-31: LGTM!

The enum cases and throttleKey() method are well-structured. Using $this->name ensures unique keys per resource type.


38-53: LGTM!

The middleware integration and rate limit definitions are appropriate. The default fallback in limit() handles cases not explicitly listed (AllocationCreate, ScheduleCreate).


55-64: Assertion failure would result in 500 error if routes misconfigured.

Assert::isInstanceOf() throws InvalidArgumentException if the server route parameter is missing or not a Server instance, yielding an opaque 500 error. However, this is mitigated by design: all routes using ResourceLimit::*->middleware() are nested under the /servers/{server:uuid} prefix in routes/api-client.php, which guarantees model binding of the server parameter. The middleware is sufficiently tightly coupled to this routing structure that misconfiguration is unlikely without breaking other routes as well.

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: 2

🤖 Fix all issues with AI agents
In @app/Http/Controllers/Api/Client/Servers/NetworkAllocationController.php:
- Around line 110-122: The row lock call
($server->allocations()->lockForUpdate()) is not executed, so the subsequent
check ($server->allocations->count()) can read an unlocked or cached collection
and cause a race; execute the locked query and use its result for the count
inside the Activity::event(...)->transaction(...) closure (e.g. call a terminal
operation on $server->allocations()->lockForUpdate() and store that result in a
local variable), then perform the allocation_limit check against that
locked/counted result and pass the locked allocation or fresh data into
assignableAllocationService->handle to prevent concurrent requests from
bypassing the limit.

In @lang/en/admin/node.php:
- Line 64: The 'upload_limit_help' translation in lang/en/admin/node.php was
changed to a single string but corresponding keys in other locales (e.g., zh-CN,
hu-HU, fr-FR) remain arrays, causing trans() to return different types per
locale; update each locale file to define 'upload_limit_help' as the same single
string value (not an array) so the key's type is consistent across translations,
ensuring functions like trans('admin.node.upload_limit_help') always return a
string.
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between fad5868 and 85fd11a.

📒 Files selected for processing (4)
  • app/Filament/Admin/Resources/Nodes/Pages/CreateNode.php
  • app/Filament/Admin/Resources/Nodes/Pages/EditNode.php
  • app/Http/Controllers/Api/Client/Servers/NetworkAllocationController.php
  • lang/en/admin/node.php
🚧 Files skipped from review as they are similar to previous changes (2)
  • app/Filament/Admin/Resources/Nodes/Pages/EditNode.php
  • app/Filament/Admin/Resources/Nodes/Pages/CreateNode.php
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-12T17:33:57.388Z
Learnt from: lancepioch
Repo: pelican-dev/panel PR: 1595
File: app/Services/Servers/ServerCreationService.php:182-184
Timestamp: 2025-08-12T17:33:57.388Z
Learning: In the Pelican Panel codebase, when updating allocations to assign them to servers, the preferred pattern is to use whereNull('server_id'), lockForUpdate(), and direct property assignment with save() rather than mass update methods, to prevent race conditions and mass-assignment issues while ensuring model events fire properly.

Applied to files:

  • app/Http/Controllers/Api/Client/Servers/NetworkAllocationController.php
🔇 Additional comments (1)
app/Http/Controllers/Api/Client/Servers/NetworkAllocationController.php (1)

18-18: LGTM! Scramble API documentation grouping added.

The addition of the #[Group('Server - Allocation')] attribute properly groups these allocation endpoints for API documentation.

Also applies to: 21-21

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

🤖 Fix all issues with AI agents
In @database/migrations/2026_01_09_134116_clear_unused_allocation_notes.php:
- Around line 11-16: Wrap the bulk update in a DB::transaction() inside the
migration's up() method to ensure atomicity; instead of a single update call,
select rows whereNull('server_id') and process them in chunks (e.g., chunkById)
while applying lockForUpdate() on the query, then update each chunk's notes to
null, so the operation is performed safely and prevents partial commits and race
conditions.
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 85fd11a and c89aa4f.

📒 Files selected for processing (1)
  • database/migrations/2026_01_09_134116_clear_unused_allocation_notes.php
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-08-12T17:33:57.388Z
Learnt from: lancepioch
Repo: pelican-dev/panel PR: 1595
File: app/Services/Servers/ServerCreationService.php:182-184
Timestamp: 2025-08-12T17:33:57.388Z
Learning: In the Pelican Panel codebase, when updating allocations to assign them to servers, the preferred pattern is to use whereNull('server_id'), lockForUpdate(), and direct property assignment with save() rather than mass update methods, to prevent race conditions and mass-assignment issues while ensuring model events fire properly.

Applied to files:

  • database/migrations/2026_01_09_134116_clear_unused_allocation_notes.php
🔇 Additional comments (1)
database/migrations/2026_01_09_134116_clear_unused_allocation_notes.php (1)

21-24: LGTM!

The no-op down() method is appropriate for a data cleanup migration, since restoring cleared notes is not meaningful.

@Boy132 Boy132 requested a review from rmartinoscar January 12, 2026 17:01
@Boy132 Boy132 merged commit 53aa49b into main Jan 13, 2026
32 checks passed
@Boy132 Boy132 deleted the boy132/upstream-changes branch January 13, 2026 07:39
@github-actions github-actions bot locked and limited conversation to collaborators Jan 13, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants