Skip to content

Conversation

@KroZen-Dev
Copy link

@KroZen-Dev KroZen-Dev commented Jan 11, 2026

This pull request enhances the management functionality for both servers and users by introducing optional reason parameters for suspension, unsuspension, and deletion via the API. This allows administrators to provide context for these actions, which is then recorded in the activity log for improved auditability and tracking.

Changes Made:

  1. app/Http/Controllers/Api/ServerController.php:
  • Updated the suspend and unSuspend methods to accept Request and log the reason (if provided).
  • Updated the destroy method to capture an optional reason before deleting the server record.
  • Both status change methods now return the server with loaded product data for consistency.
  1. app/Http/Controllers/Api/UserController.php:
  • Updated the suspend and unsuspend methods to accept Request and capture an optional reason.
  • Updated the destroy method to log the deletion action with a reason before the user is removed.
  • Integrated Spatie Activity Log to record all user status changes and deletions, ensuring alignment with the server management API.
  1. resources/views/admin/activitylogs/index.blade.php:
  • Replaced unsafe explode('\', $log->subject_type)[2] with the safer class_basename($log->subject_type) helper.
  • Improved Causer display with better fallbacks and a distinct badge for system-automated actions.
  • Enhanced Properties handling to properly validate arrays and prevent errors with nested or null data.
  • Added intuitive icons for update/action types and improved formatting for property lists.
  • Refactored HTML structure for better scannability and readability.

API Usage:

Servers:

  • Suspend: PATCH /api/servers/{server}/suspend | JSON: {"reason": "Violation of TOS"}
  • Unsuspend: PATCH /api/servers/{server}/unsuspend | JSON: {"reason": "Issue resolved"}
  • Delete: DELETE /api/servers/{server} | JSON: {"reason": "User requested deletion"}

Users:

  • Suspend: PATCH /api/users/{user}/suspend | JSON: {"reason": "Chargeback detected"}
  • Unsuspend: PATCH /api/users/{user}/unsuspend | JSON: {"reason": "Verification complete"}
  • Delete: DELETE /api/users/{user} | JSON: {"reason": "Account cleanup"}
image image image

Removed unnecessary comments and improved the search input handling. Updated links and adjusted layout for better readability.
Updated suspend method to accept a reason parameter from the request and log it.
Added reason parameter to unSuspend method for logging.
@KroZen-Dev KroZen-Dev changed the title Patch 8 Add optional reason parameter for server suspension and unsuspension via API Jan 11, 2026
@KroZen-Dev KroZen-Dev changed the title Add optional reason parameter for server suspension and unsuspension via API Add optional reason for server suspension and unsuspension via API Jan 11, 2026
Updated constants to public visibility and added destroy method for user deletion.
@KroZen-Dev KroZen-Dev changed the title Add optional reason for server suspension and unsuspension via API Add optional reason for server/user suspension, unsuspension and deletion via API Jan 11, 2026
@KroZen-Dev KroZen-Dev changed the title Add optional reason for server/user suspension, unsuspension and deletion via API Add optional reason to server/user moderation actions via API Jan 11, 2026
@MrWeez MrWeez requested review from 1day2die and Ferks-FK January 11, 2026 22:22
@KroZen-Dev
Copy link
Author

I think we should set a character limit for the reason text; if a message is too long, it will break the layout on the Activity Log page.

Is it worth making a restriction? And how many symbols exactly?

Added validation for 'reason' input in destroy, suspend, and unSuspend methods.
Added validation for 'reason' input in suspend, unsuspend, and destroy methods.
Removed validation for 'reason' input in destroy, suspend, and unSuspend methods. Added substring limitation for 'reason' input.
Removed validation for 'reason' input and added substring limitation.
@KroZen-Dev
Copy link
Author

The reason field is now automatically truncated to 320 characters using mb_substr to ensure log compatibility and prevent potential database overflows 🤗

@MrWeez
Copy link
Collaborator

MrWeez commented Jan 12, 2026

The reason field is now automatically truncated to 320 characters using mb_substr to ensure log compatibility and prevent potential database overflows 🤗

It seems to me that the approach with mb_substr is not correct. In my opinion, it would be more correct to describe this limit in the API documentation, and return an error if the reason is more than the required number of characters.

@KroZen-Dev
Copy link
Author

KroZen-Dev commented Jan 12, 2026

I considered that approach, but it turned out to be extremely inconvenient and impractical. I develop my own systems that automatically clean up stopped servers, block users attempting to bypass account restrictions, and so on, and it’s very convenient for me to pass detailed reason strings like:

reason = ( f"Automated security action: Duplicate IP detected on account '{user_name}' (ID: {user_id}). " f"Shared IP: {dup.get('ip')} | Email: {u.get('email', 'Unknown')}. " f"Other users sharing this IP: {other_users_str}. " f"Detected at {datetime.now(timezone.utc).isoformat() + 'Z'}" )

Sometimes the length of the email or username fits within the 320-character limit, but other times the username or email is so long that if we return an error if the reason is more than the required number of characters, the block will fail. This creates a vulnerability where users could deliberately create long emails, usernames, server names, file names, etc. In my case, for example, this would constantly cause errors and the user/server would not be blocked.

@Ferks-FK
Copy link
Collaborator

Ferks-FK commented Jan 12, 2026

It's best to leave it as it was before, with $request->validate.

@MrWeez
Copy link
Collaborator

MrWeez commented Jan 12, 2026

I considered that approach, but it turned out to be extremely inconvenient and impractical. I develop my own systems that automatically clean up stopped servers, block users attempting to bypass account restrictions, and so on, and it’s very convenient for me to pass detailed reason strings like:

reason = ( f"Automated security action: Duplicate IP detected on account '{user_name}' (ID: {user_id}). " f"Shared IP: {dup.get('ip')} | Email: {u.get('email', 'Unknown')}. " f"Other users sharing this IP: {other_users_str}. " f"Detected at {datetime.now(timezone.utc).isoformat() + 'Z'}" )

Sometimes the length of the email or username fits within the 320-character limit, but other times the username or email is so long that if we return an error if the reason is more than the required number of characters, the block will fail. This creates a vulnerability where users could deliberately create long emails, usernames, server names, file names, etc. In my case, for example, this would constantly cause errors and the user/server would not be blocked.

The fact that your use case needs this should not affect the code of the original CtrlPanel. You can create your own fork that will have the fixes you need. It's not a good practice to push changes that your use case needs in the public project codebase.

Maybe my explanation isn't perfect, because I'm writing this on the fly

@KroZen-Dev
Copy link
Author

What I'm saying is that developers won't always add static reason text. I didn't try to describe my needs specifically, but gave an example of how I use it and how other developers can use it. This change does not change the panel code in any way, because the changes do not even make sending a reason mandatory

@KroZen-Dev
Copy link
Author

That is, just make a direct return of the error?> It's best to leave it as it was before, with $request->validate.

@MrWeez
Copy link
Collaborator

MrWeez commented Jan 13, 2026

That is, just make a direct return of the error?> It's best to leave it as it was before, with $request->validate.

Use $request->validate and throw an error if the validation isn't successful

@MrWeez MrWeez added the Low Priority Can wait, not urgent. Handle when possible label Jan 13, 2026
@KroZen-Dev
Copy link
Author

That is, just make a direct return of the error?> It's best to leave it as it was before, with $request->validate.

Use $request->validate and throw an error if the validation isn't successful

Done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Low Priority Can wait, not urgent. Handle when possible

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants