HEX
Server: LiteSpeed
System: Linux s1049.use1.mysecurecloudhost.com 4.18.0-477.27.2.lve.el8.x86_64 #1 SMP Wed Oct 11 12:32:56 UTC 2023 x86_64
User: xedaptot (3356)
PHP: 8.3.31
Disabled: NONE
Upload Files
File: /home/xedaptot/be.naniguide.com/app/Http/Controllers/Refactor/Admin/AdminAdsSettingsController.php
<?php

namespace App\Http\Controllers\Refactor\Admin;

use App\Http\Controllers\Controller;
use App\Http\Requests\Refactor\Ads\AdsSettingsUpdateRequest;
use App\Model\AdPlatform;
use App\Model\Setting;
use App\Services\Ads\AdCredentialResolver;
use App\Services\Ads\AdPlatformManager;
use App\Services\Ads\TestConnectionResult;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

/**
 * Phase N — Admin Self-Service Ads Platform Configuration.
 *
 * Lets SaaS admins configure OAuth app credentials via a step-by-step wizard
 * instead of editing .env. Provides a live "Test Connection" button that
 * validates credentials against each platform's API without requiring user OAuth.
 */
class AdminAdsSettingsController extends Controller
{
    public function __construct(private readonly AdPlatformManager $manager)
    {
    }

    /**
     * Show the 5-step wizard.
     */
    public function show(Request $request)
    {
        if (!$this->canManage($request)) {
            return $this->notAuthorized();
        }

        $credentials = [];
        $sources = [];
        foreach (AdPlatform::PLATFORMS as $platform) {
            $credentials[$platform] = AdCredentialResolver::all($platform);
            $sources[$platform] = AdCredentialResolver::source($platform);
        }

        $globals = [
            'mock_mode' => (string) (Setting::get('ads.mock_mode') ?? (config('ads.mock_mode') ? 'yes' : 'no')),
            'metrics_sync_interval' => (int) (Setting::get('ads.metrics_sync_interval') ?? config('ads.metrics_sync_interval', 15)),
            'rate_limit_buffer' => (int) (Setting::get('ads.rate_limit_buffer') ?? 80),
        ];

        return view('refactor.pages.admin.ads.settings', [
            'credentials' => $credentials,
            'sources' => $sources,
            'globals' => $globals,
            'platforms' => AdPlatform::PLATFORMS,
            'platformLabels' => AdPlatform::PLATFORM_LABELS,
            'requiredKeys' => AdCredentialResolver::REQUIRED_KEYS,
        ]);
    }

    /**
     * Save wizard input to settings table.
     */
    public function update(AdsSettingsUpdateRequest $request)
    {
        if (!$this->canManage($request)) {
            return $this->notAuthorized();
        }

        $map = [
            'ads_meta_app_id' => 'ads.meta.app_id',
            'ads_meta_app_secret' => 'ads.meta.app_secret',
            'ads_google_client_id' => 'ads.google.client_id',
            'ads_google_client_secret' => 'ads.google.client_secret',
            'ads_google_developer_token' => 'ads.google.developer_token',
            'ads_tiktok_app_id' => 'ads.tiktok.app_id',
            'ads_tiktok_app_secret' => 'ads.tiktok.app_secret',
            'ads_linkedin_client_id' => 'ads.linkedin.client_id',
            'ads_linkedin_client_secret' => 'ads.linkedin.client_secret',
            'ads_mock_mode' => 'ads.mock_mode',
            'ads_metrics_sync_interval' => 'ads.metrics_sync_interval',
            'ads_rate_limit_buffer' => 'ads.rate_limit_buffer',
        ];

        foreach ($map as $input => $settingKey) {
            if ($request->filled($input)) {
                Setting::set($settingKey, $request->input($input));
            }
        }

        if ($request->ajax() || $request->wantsJson()) {
            return response()->json([
                'status' => 'success',
                'message' => trans('refactor/ads_admin_settings.saved'),
            ]);
        }

        $request->session()->flash('alert-success', trans('refactor/ads_admin_settings.saved'));
        return redirect()->route('refactor.admin.ads.settings.show');
    }

    /**
     * AJAX: test credentials for a single platform WITHOUT persisting.
     * Accepts POST body with draft credentials so admin can test before save.
     */
    public function testConnection(Request $request, string $platform): JsonResponse
    {
        if (!$this->canManage($request)) {
            return response()->json(['status' => 'error', 'message' => 'Not authorized'], 403);
        }

        if (!in_array($platform, AdPlatform::PLATFORMS, true)) {
            return response()->json([
                'status' => TestConnectionResult::STATUS_ERROR,
                'message' => 'Unknown platform.',
            ], 422);
        }

        // Collect draft credentials from request body. Fall back to persisted settings if not in body.
        $draftCreds = [];
        foreach (AdCredentialResolver::requiredKeys($platform) as $key) {
            $input = "ads_{$platform}_{$key}";
            $draftCreds[$key] = $request->input($input) ?: AdCredentialResolver::resolve($platform, $key);
        }

        $adapter = $this->manager->adapter($platform);
        $result = $adapter->testAppCredentials($draftCreds);

        return response()->json([
            'status' => $result->status,
            'message' => $result->message,
            'app_review_status' => $result->appReviewStatus,
            'is_dev_mode' => $result->isDevMode(),
            'resolution_hint' => $result->resolutionHint,
        ]);
    }

    /**
     * AJAX: get the latest app review status for a platform (cached).
     */
    public function reviewStatus(Request $request, string $platform): JsonResponse
    {
        if (!$this->canManage($request)) {
            return response()->json(['status' => 'error', 'message' => 'Not authorized'], 403);
        }

        if (!in_array($platform, AdPlatform::PLATFORMS, true)) {
            return response()->json(['status' => 'error', 'message' => 'Unknown platform.'], 422);
        }

        if (!AdCredentialResolver::isConfigured($platform)) {
            return response()->json([
                'configured' => false,
                'app_review_status' => null,
            ]);
        }

        $adapter = $this->manager->adapter($platform);
        $result = $adapter->testAppCredentials(AdCredentialResolver::all($platform));

        return response()->json([
            'configured' => true,
            'app_review_status' => $result->appReviewStatus,
            'is_dev_mode' => $result->isDevMode(),
            'message' => $result->message,
        ]);
    }

    private function canManage(Request $request): bool
    {
        $user = $request->user();
        if (!$user) {
            return false;
        }

        /** @var \App\Model\Admin|null $admin */
        $admin = $user->admin()->first();
        if (!$admin) {
            return false;
        }

        // Reuse setting_general permission; admins who can manage settings can manage ads platform creds.
        return $admin->getPermission('setting_general') === 'yes';
    }
}