HEX
Server: LiteSpeed
System: Linux php-prod-1.spaceapp.ru 5.15.0-157-generic #167-Ubuntu SMP Wed Sep 17 21:35:53 UTC 2025 x86_64
User: xnsbb3110 (1041)
PHP: 8.1.33
Disabled: NONE
Upload Files
File: //proc/self/root/usr/local/CyberCP/public/imunifyav/plib/library/MovePermissions.php
<?php
/**
 * Class MovePermissions
 *
 * Static migration class to update service plans with new permissions
 * Migrates Revisium Antivirus permissions to Imunify360 permissions
 * by updating service plan permissions through the Plesk XML API.
 * Only migrates permissions that were explicitly set for the old extension.
 */

namespace Imunify360;

class MovePermissions {
    /** @var string Permission for Revisium Antivirus on/off */
    private static $RA_ON = "ext_permission_revisium_antivirus_ra_on";

    /** @var string Permission for Revisium Antivirus scanning */
    private static $RA_SCANNING_ALLOWED = "ext_permission_revisium_antivirus_ra_scanning_allowed";

    /** @var string Permission for Revisium Antivirus cleanup */
    private static $RA_CLEANUP_ALLOWED = "ext_permission_revisium_antivirus_ra_cleanup_allowed";

    /** @var array Mapping from old to new permissions */
    private static $PERMISSION_MAPPING;

    private static $log_filename = 'permissions-migration.log';
    private static $premission_migrated = 'imunify360-permissions-migrated';

    /**
     * Migration function from Revisium Antivirus to Imunify360 permissions.
     * Only sets a new permission if the corresponding old permission was explicitly defined.
     *
     * @return void
     */
    public static function migrate() {
        if (!ImunifyHelper::isInstalledRevisiumAV()) {
            self::logger(ImunifyLog::INFO, "Revisium Antivirus extension not detected - skipping permission migration.");
            return;
        }

        // check if migration already done and skip
        if (\pm_Settings::get(self::$premission_migrated, false)) {
            self::logger(ImunifyLog::INFO, "Permission migration already done - skipping.");
            return;
        }


        // Initialize Plesk SDK if not already initialized
        require_once("sdk.php");

        // Initialize permission mapping
        self::$PERMISSION_MAPPING = [
            self::$RA_ON => "ext_permission_imunify360_imunify_end_user_on",
            self::$RA_SCANNING_ALLOWED => "ext_permission_imunify360_imunify_scanning_allowed",
            self::$RA_CLEANUP_ALLOWED => "ext_permission_imunify360_imunify_cleanup_allowed",
        ];


        try {
            // 1. Get all service plans from Plesk
            self::logger(ImunifyLog::INFO, "Getting service plans...");
            $servicePlans = self::getServicePlansPermissions();
            self::logger(ImunifyLog::INFO, "Starting migration from Revisium Antivirus to Imunify360 permissions");

            if (empty($servicePlans)) {
                self::logger(ImunifyLog::INFO, "No service plans found. Skipping...");
                return;
            }

            self::logger(ImunifyLog::INFO, "Found " . count($servicePlans) . " service plans");

            $plansUpdated = 0;
            $permissionsMigratedCount = 0;

            // 2. Process each Service Plan
            foreach ($servicePlans as $plan) {
                $servicePlanId = isset($plan['id']) ? $plan['id'] : null;
                $servicePlanName = isset($plan['name']) ? $plan['name'] : 'Unknown'; // For logging

                if (!$servicePlanId) {
                    self::logger(ImunifyLog::WARN, "Skipping a plan due to missing ID.");
                    continue;
                }

                $explicitOldPermissions = isset($plan['permissions']) ? $plan['permissions'] : [];
                $permissionsToSet = []; // Array to hold only the permissions we need to explicitly set

                foreach (self::$PERMISSION_MAPPING as $oldPerm => $newPerm) {
                    if (array_key_exists($oldPerm, $explicitOldPermissions)) {
                        $value = $explicitOldPermissions[$oldPerm];
                        $permissionsToSet[$newPerm] = $value;
                        self::logger(ImunifyLog::DEBUG, "Plan {$servicePlanId} ('{$servicePlanName}'): Mapping old '{$oldPerm}' (".($value?'true':'false').") to new '{$newPerm}'.");
                        $permissionsMigratedCount++;
                    } else {
                        self::logger(ImunifyLog::DEBUG, "Plan {$servicePlanId} ('{$servicePlanName}'): Old permission '{$oldPerm}' was not explicitly set. Skipping mapping for '{$newPerm}'.");
                    }
                }

                if (!empty($permissionsToSet)) {
                    self::logger(ImunifyLog::INFO, "Updating service plan {$servicePlanId} ('{$servicePlanName}') with " . count($permissionsToSet) . " explicitly migrated permission(s)...");

                    try {
                        $result = self::updateServicePlanPermissions($servicePlanId, $permissionsToSet);

                        if (isset($result['status']) && $result['status'] === 'ok') {
                            self::logger(ImunifyLog::INFO, "Successfully updated service plan {$servicePlanId} ('{$servicePlanName}')");
                            $plansUpdated++;
                        } else {
                            $errorMessage = isset($result['errtext']) ? $result['errtext'] : (isset($result['error']) ? $result['error'] : 'Unknown API error');
                            self::logger(ImunifyLog::WARN, "Failed to update service plan {$servicePlanId} ('{$servicePlanName}'): {$errorMessage}");
                        }
                    } catch (\Exception $e) {
                        self::logger(ImunifyLog::ERR, "Error updating service plan {$servicePlanId} ('{$servicePlanName}'): " . $e->getMessage());
                    }
                } else {
                    self::logger(ImunifyLog::INFO, "No explicit Revisium permissions found for service plan {$servicePlanId} ('{$servicePlanName}'). No update needed.");
                }
            }

            \pm_Settings::set(self::$premission_migrated, true);
            self::logger(ImunifyLog::INFO, "Migration check completed. {$plansUpdated} plan(s) updated with a total of {$permissionsMigratedCount} explicit permission setting(s).");

        } catch (\Exception $e) {
            self::logger(ImunifyLog::ERR, "Error during migration: " . $e->getMessage());
        }
    }

    /**
     * Log messages using ImunifyLog directed to a specific file.
     *
     * @param int $level Log level (ImunifyLog::INFO, ImunifyLog::WARN, ImunifyLog::ERR, ImunifyLog::DEBUG)
     * @param string $message Message to log
     * @return void
     */
    private static function logger(int $level, string $message) {
        switch ($level) {
            case ImunifyLog::ERR:
                ImunifyLog::err($message, self::$log_filename);
                break;
            case ImunifyLog::INFO:
                ImunifyLog::info($message, self::$log_filename);
                break;
            case ImunifyLog::WARN:
                ImunifyLog::warn($message, self::$log_filename);
                break;
            default: // Catches DEBUG and any unexpected level
                ImunifyLog::debug($message, self::$log_filename);
        }
    }

    /**
     * Get all service plans with their permissions from Plesk
     *
     * @return array Service plans with their IDs and permissions
     */
    private static function getServicePlansPermissions(): array {
        try {
            $xmlString = '<packet><service-plan><get><filter/></get></service-plan></packet>';
            $xml = new \SimpleXMLElement($xmlString);
            $response = \pm_ApiRpc::getService()->call($xml);
            $plans = [];

            if (isset($response->{'service-plan'}->get->result)) {
                $results = $response->{'service-plan'}->get->result;
                foreach ($results as $result) {
                    if (isset($result->status) && (string)$result->status === 'ok') {
                        $plan = [
                            'id' => isset($result->id) ? (string)$result->id : null,
                            'name' => isset($result->name) ? (string)$result->name : 'Unknown',
                            'permissions' => []
                        ];

                        if (!$plan['id']) {
                            self::logger(ImunifyLog::WARN, "Found a service plan result with status 'ok' but no ID.");
                            continue; // Skip plans without ID
                        }

                        if (isset($result->permissions->permission)) {
                            foreach ($result->permissions->permission as $permission) {
                                if (isset($permission->name) && isset($permission->value)) {
                                    // Store only explicitly returned permissions
                                    $plan['permissions'][(string)$permission->name] = ((string)$permission->value === 'true');
                                }
                            }
                        }
                        $plans[] = $plan;
                    } elseif (isset($result->status) && (string)$result->status === 'error') {
                        $errText = isset($result->errtext) ? (string)$result->errtext : 'Unknown error';
                        $errCode = isset($result->errcode) ? (string)$result->errcode : 'N/A';
                        $planId = isset($result->id) ? (string)$result->id : 'N/A';
                        self::logger(ImunifyLog::WARN, "Error retrieving details for service plan ID {$planId}: [{$errCode}] {$errText}");
                    }
                }
            } else {
                self::logger(ImunifyLog::WARN, "Unexpected response structure or no results found when getting service plans.");
            }

            return $plans;
        } catch (\Exception $e) {
            self::logger(ImunifyLog::ERR, "Failed to get Plesk service plans: " . $e->getMessage());
            return [];
        }
    }

    /**
     * Update a service plan with new permissions
     *
     * @param string $servicePlanId ID of the service plan to update
     * @param array $permissionsDict Dictionary of permission names and boolean values
     * @return array Response status of the update operation
     */
    private static function updateServicePlanPermissions($servicePlanId, $permissionsDict) {
        try {
            $permissionsXml = '';
            foreach ($permissionsDict as $name => $value) {
                $boolValue = $value ? 'true' : 'false';
                $permissionsXml .= "<permission><name>{$name}</name><value>{$boolValue}</value></permission>";
            }

            $xmlString = '<packet><service-plan><set>'
                . '<filter><id>' . $servicePlanId . '</id></filter>'
                . '<permissions>' . $permissionsXml . '</permissions>'
                . '</set></service-plan></packet>';

            $xml = new \SimpleXMLElement($xmlString);
            $response = \pm_ApiRpc::getService()->call($xml);

            $result = [];

            if (isset($response->{'service-plan'}->{'set'}->{'result'})) {
                $resultNode = $response->{'service-plan'}->{'set'}->{'result'};
                $result['status'] = isset($resultNode->status) ? (string)$resultNode->status : 'error'; // Default to error if status missing

                if (isset($resultNode->id)) {
                    $result['id'] = (string)$resultNode->id;
                }

                if ($result['status'] === 'error') {
                    $result['errcode'] = isset($resultNode->errcode) ? (string)$resultNode->errcode : 'UNKNOWN';
                    $result['errtext'] = isset($resultNode->errtext) ? (string)$resultNode->errtext : 'Unknown error details';
                }
            } else {
                $result['status'] = 'error';
                $result['errtext'] = 'Unexpected API response format for service-plan set operation.';
                self::logger(ImunifyLog::WARN, "Unexpected API response for plan {$servicePlanId}: " . $response->asXML());
            }

            return $result;
        } catch (\Exception $e) {
            self::logger(ImunifyLog::ERR, "Exception during API call to update service plan {$servicePlanId}: " . $e->getMessage());
            return [
                'status' => 'error',
                'errtext' => 'Exception during API call: ' . $e->getMessage(),
                'error' => $e->getMessage(),
                'code' => $e->getCode()
            ];
        }
    }
}