feat: extend event toolkit and polish guest pwa
This commit is contained in:
@@ -4,7 +4,9 @@ namespace App\Http\Controllers\Api\Tenant;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Tenant\EventStoreRequest;
|
||||
use App\Http\Resources\Tenant\EventJoinTokenResource;
|
||||
use App\Http\Resources\Tenant\EventResource;
|
||||
use App\Http\Resources\Tenant\PhotoResource;
|
||||
use App\Models\Event;
|
||||
use App\Models\EventPackage;
|
||||
use App\Models\Package;
|
||||
@@ -228,6 +230,10 @@ class EventController extends Controller
|
||||
unset($validated[$unused]);
|
||||
}
|
||||
|
||||
if (isset($validated['settings']) && is_array($validated['settings'])) {
|
||||
$validated['settings'] = array_merge($event->settings ?? [], $validated['settings']);
|
||||
}
|
||||
|
||||
$event->update($validated);
|
||||
$event->load(['eventType', 'tenant']);
|
||||
|
||||
@@ -277,6 +283,141 @@ class EventController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
public function toolkit(Request $request, Event $event): JsonResponse
|
||||
{
|
||||
$tenantId = $request->attributes->get('tenant_id');
|
||||
|
||||
if ($event->tenant_id !== $tenantId) {
|
||||
return response()->json(['error' => 'Event not found'], 404);
|
||||
}
|
||||
|
||||
$event->load(['eventType', 'eventPackage.package']);
|
||||
|
||||
$photoQuery = Photo::query()->where('event_id', $event->id);
|
||||
$pendingPhotos = (clone $photoQuery)
|
||||
->where('status', 'pending')
|
||||
->latest('created_at')
|
||||
->take(6)
|
||||
->get();
|
||||
|
||||
$recentUploads = (clone $photoQuery)
|
||||
->where('status', 'approved')
|
||||
->latest('created_at')
|
||||
->take(8)
|
||||
->get();
|
||||
|
||||
$pendingCount = (clone $photoQuery)->where('status', 'pending')->count();
|
||||
$uploads24h = (clone $photoQuery)->where('created_at', '>=', now()->subDay())->count();
|
||||
$totalUploads = (clone $photoQuery)->count();
|
||||
|
||||
$tasks = $event->tasks()
|
||||
->orderBy('tasks.sort_order')
|
||||
->orderBy('tasks.created_at')
|
||||
->get(['tasks.id', 'tasks.title', 'tasks.description', 'tasks.priority', 'tasks.is_completed']);
|
||||
|
||||
$taskSummary = [
|
||||
'total' => $tasks->count(),
|
||||
'completed' => $tasks->where('is_completed', true)->count(),
|
||||
];
|
||||
$taskSummary['pending'] = max(0, $taskSummary['total'] - $taskSummary['completed']);
|
||||
|
||||
$translate = static function ($value, string $fallback = '') {
|
||||
if (is_array($value)) {
|
||||
$locale = app()->getLocale();
|
||||
$candidates = array_filter([
|
||||
$locale,
|
||||
$locale && str_contains($locale, '-') ? explode('-', $locale)[0] : null,
|
||||
'de',
|
||||
'en',
|
||||
]);
|
||||
|
||||
foreach ($candidates as $candidate) {
|
||||
if ($candidate && isset($value[$candidate]) && $value[$candidate] !== '') {
|
||||
return $value[$candidate];
|
||||
}
|
||||
}
|
||||
|
||||
$first = reset($value);
|
||||
|
||||
return $first !== false ? $first : $fallback;
|
||||
}
|
||||
|
||||
if (is_string($value) && $value !== '') {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return $fallback;
|
||||
};
|
||||
|
||||
$taskPreview = $tasks
|
||||
->take(6)
|
||||
->map(fn ($task) => [
|
||||
'id' => $task->id,
|
||||
'title' => $translate($task->title, 'Task'),
|
||||
'description' => $translate($task->description, null),
|
||||
'is_completed' => (bool) $task->is_completed,
|
||||
'priority' => $task->priority,
|
||||
])
|
||||
->values();
|
||||
|
||||
$joinTokenQuery = $event->joinTokens();
|
||||
$totalInvites = (clone $joinTokenQuery)->count();
|
||||
$activeInvites = (clone $joinTokenQuery)
|
||||
->whereNull('revoked_at')
|
||||
->where(function ($query) {
|
||||
$query->whereNull('expires_at')
|
||||
->orWhere('expires_at', '>', now());
|
||||
})
|
||||
->where(function ($query) {
|
||||
$query->whereNull('usage_limit')
|
||||
->orWhereColumn('usage_limit', '>', 'usage_count');
|
||||
})
|
||||
->count();
|
||||
|
||||
$recentInvites = (clone $joinTokenQuery)
|
||||
->orderByDesc('created_at')
|
||||
->take(3)
|
||||
->get();
|
||||
|
||||
$alerts = [];
|
||||
if (($event->settings['engagement_mode'] ?? 'tasks') !== 'photo_only' && $taskSummary['total'] === 0) {
|
||||
$alerts[] = 'no_tasks';
|
||||
}
|
||||
if ($activeInvites === 0) {
|
||||
$alerts[] = 'no_invites';
|
||||
}
|
||||
if ($pendingCount > 0) {
|
||||
$alerts[] = 'pending_photos';
|
||||
}
|
||||
|
||||
return response()->json([
|
||||
'event' => new EventResource($event),
|
||||
'metrics' => [
|
||||
'uploads_total' => $totalUploads,
|
||||
'uploads_24h' => $uploads24h,
|
||||
'pending_photos' => $pendingCount,
|
||||
'active_invites' => $activeInvites,
|
||||
'engagement_mode' => $event->settings['engagement_mode'] ?? 'tasks',
|
||||
],
|
||||
'tasks' => [
|
||||
'summary' => $taskSummary,
|
||||
'items' => $taskPreview,
|
||||
],
|
||||
'photos' => [
|
||||
'pending' => PhotoResource::collection($pendingPhotos)->resolve($request),
|
||||
'recent' => PhotoResource::collection($recentUploads)->resolve($request),
|
||||
],
|
||||
'invites' => [
|
||||
'summary' => [
|
||||
'total' => $totalInvites,
|
||||
'active' => $activeInvites,
|
||||
],
|
||||
'items' => EventJoinTokenResource::collection($recentInvites)->resolve($request),
|
||||
],
|
||||
'alerts' => $alerts,
|
||||
]);
|
||||
}
|
||||
|
||||
public function toggle(Request $request, Event $event): JsonResponse
|
||||
{
|
||||
$tenantId = $request->attributes->get('tenant_id');
|
||||
|
||||
@@ -7,6 +7,7 @@ use App\Http\Resources\Tenant\EventJoinTokenResource;
|
||||
use App\Models\Event;
|
||||
use App\Models\EventJoinToken;
|
||||
use App\Services\EventJoinTokenService;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\AnonymousResourceCollection;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
@@ -30,12 +31,7 @@ class EventJoinTokenController extends Controller
|
||||
{
|
||||
$this->authorizeEvent($request, $event);
|
||||
|
||||
$validated = $request->validate([
|
||||
'label' => ['nullable', 'string', 'max:255'],
|
||||
'expires_at' => ['nullable', 'date', 'after:now'],
|
||||
'usage_limit' => ['nullable', 'integer', 'min:1'],
|
||||
'metadata' => ['nullable', 'array'],
|
||||
]);
|
||||
$validated = $this->validatePayload($request);
|
||||
|
||||
$token = $this->joinTokenService->createToken($event, array_merge($validated, [
|
||||
'created_by' => Auth::id(),
|
||||
@@ -46,6 +42,50 @@ class EventJoinTokenController extends Controller
|
||||
->setStatusCode(201);
|
||||
}
|
||||
|
||||
public function update(Request $request, Event $event, EventJoinToken $joinToken): EventJoinTokenResource
|
||||
{
|
||||
$this->authorizeEvent($request, $event);
|
||||
|
||||
if ($joinToken->event_id !== $event->id) {
|
||||
abort(404);
|
||||
}
|
||||
|
||||
$validated = $this->validatePayload($request, true);
|
||||
|
||||
$payload = [];
|
||||
|
||||
if (array_key_exists('label', $validated)) {
|
||||
$payload['label'] = $validated['label'];
|
||||
}
|
||||
|
||||
if (array_key_exists('expires_at', $validated)) {
|
||||
$payload['expires_at'] = $validated['expires_at'];
|
||||
}
|
||||
|
||||
if (array_key_exists('usage_limit', $validated)) {
|
||||
$payload['usage_limit'] = $validated['usage_limit'];
|
||||
}
|
||||
|
||||
if (! empty($payload)) {
|
||||
$joinToken->fill($payload);
|
||||
}
|
||||
|
||||
if (array_key_exists('metadata', $validated)) {
|
||||
$current = is_array($joinToken->metadata) ? $joinToken->metadata : [];
|
||||
$incoming = $validated['metadata'];
|
||||
|
||||
if ($incoming === null) {
|
||||
$joinToken->metadata = null;
|
||||
} else {
|
||||
$joinToken->metadata = array_replace_recursive($current, $incoming);
|
||||
}
|
||||
}
|
||||
|
||||
$joinToken->save();
|
||||
|
||||
return new EventJoinTokenResource($joinToken->fresh());
|
||||
}
|
||||
|
||||
public function destroy(Request $request, Event $event, EventJoinToken $joinToken): EventJoinTokenResource
|
||||
{
|
||||
$this->authorizeEvent($request, $event);
|
||||
@@ -68,4 +108,54 @@ class EventJoinTokenController extends Controller
|
||||
abort(404, 'Event not found');
|
||||
}
|
||||
}
|
||||
|
||||
private function validatePayload(Request $request, bool $partial = false): array
|
||||
{
|
||||
$rules = [
|
||||
'label' => [$partial ? 'nullable' : 'sometimes', 'string', 'max:255'],
|
||||
'expires_at' => [$partial ? 'nullable' : 'sometimes', 'nullable', 'date', 'after:now'],
|
||||
'usage_limit' => [$partial ? 'nullable' : 'sometimes', 'nullable', 'integer', 'min:1'],
|
||||
'metadata' => [$partial ? 'nullable' : 'sometimes', 'nullable', 'array'],
|
||||
'metadata.layout_customization' => ['nullable', 'array'],
|
||||
'metadata.layout_customization.layout_id' => ['nullable', 'string', 'max:100'],
|
||||
'metadata.layout_customization.headline' => ['nullable', 'string', 'max:120'],
|
||||
'metadata.layout_customization.subtitle' => ['nullable', 'string', 'max:160'],
|
||||
'metadata.layout_customization.description' => ['nullable', 'string', 'max:500'],
|
||||
'metadata.layout_customization.badge_label' => ['nullable', 'string', 'max:80'],
|
||||
'metadata.layout_customization.instructions_heading' => ['nullable', 'string', 'max:120'],
|
||||
'metadata.layout_customization.link_heading' => ['nullable', 'string', 'max:120'],
|
||||
'metadata.layout_customization.cta_label' => ['nullable', 'string', 'max:120'],
|
||||
'metadata.layout_customization.cta_caption' => ['nullable', 'string', 'max:160'],
|
||||
'metadata.layout_customization.link_label' => ['nullable', 'string', 'max:160'],
|
||||
'metadata.layout_customization.instructions' => ['nullable', 'array', 'max:6'],
|
||||
'metadata.layout_customization.instructions.*' => ['nullable', 'string', 'max:160'],
|
||||
'metadata.layout_customization.logo_url' => ['nullable', 'string', 'max:2048'],
|
||||
'metadata.layout_customization.logo_data_url' => ['nullable', 'string'],
|
||||
'metadata.layout_customization.accent_color' => ['nullable', 'string', 'regex:/^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})$/'],
|
||||
'metadata.layout_customization.text_color' => ['nullable', 'string', 'regex:/^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})$/'],
|
||||
'metadata.layout_customization.background_color' => ['nullable', 'string', 'regex:/^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})$/'],
|
||||
'metadata.layout_customization.secondary_color' => ['nullable', 'string', 'regex:/^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})$/'],
|
||||
'metadata.layout_customization.badge_color' => ['nullable', 'string', 'regex:/^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})$/'],
|
||||
'metadata.layout_customization.background_gradient' => ['nullable', 'array'],
|
||||
'metadata.layout_customization.background_gradient.angle' => ['nullable', 'numeric'],
|
||||
'metadata.layout_customization.background_gradient.stops' => ['nullable', 'array', 'max:5'],
|
||||
'metadata.layout_customization.background_gradient.stops.*' => ['nullable', 'string', 'regex:/^#([A-Fa-f0-9]{3}|[A-Fa-f0-9]{6})$/'],
|
||||
];
|
||||
|
||||
$validated = $request->validate($rules);
|
||||
|
||||
if (isset($validated['metadata']['layout_customization']['instructions'])) {
|
||||
$validated['metadata']['layout_customization']['instructions'] = array_values(array_filter(
|
||||
$validated['metadata']['layout_customization']['instructions'],
|
||||
fn ($value) => is_string($value) && trim($value) !== ''
|
||||
));
|
||||
}
|
||||
|
||||
if (isset($validated['metadata']['layout_customization']['logo_data_url'])
|
||||
&& ! is_string($validated['metadata']['layout_customization']['logo_data_url'])) {
|
||||
unset($validated['metadata']['layout_customization']['logo_data_url']);
|
||||
}
|
||||
|
||||
return $validated;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,8 @@ class EventJoinTokenLayoutController extends Controller
|
||||
abort(404, 'Unbekanntes Exportformat.');
|
||||
}
|
||||
|
||||
$layoutConfig = $this->applyCustomization($layoutConfig, $joinToken);
|
||||
|
||||
$tokenUrl = url('/e/'.$joinToken->token);
|
||||
|
||||
$qrPngDataUri = 'data:image/png;base64,'.base64_encode(
|
||||
@@ -66,6 +68,7 @@ class EventJoinTokenLayoutController extends Controller
|
||||
'tokenUrl' => $tokenUrl,
|
||||
'qrPngDataUri' => $qrPngDataUri,
|
||||
'backgroundStyle' => $backgroundStyle,
|
||||
'customization' => $joinToken->metadata['layout_customization'] ?? null,
|
||||
];
|
||||
|
||||
$filename = sprintf('%s-%s.%s', Str::slug($eventName ?: 'event'), $layoutConfig['id'], $format);
|
||||
@@ -80,7 +83,7 @@ class EventJoinTokenLayoutController extends Controller
|
||||
|
||||
$html = view('layouts.join-token.pdf', $viewData)->render();
|
||||
|
||||
$options = new Options();
|
||||
$options = new Options;
|
||||
$options->set('isHtml5ParserEnabled', true);
|
||||
$options->set('isRemoteEnabled', true);
|
||||
$options->set('defaultFont', 'Helvetica');
|
||||
@@ -115,6 +118,57 @@ class EventJoinTokenLayoutController extends Controller
|
||||
return is_string($name) && $name !== '' ? $name : 'Event';
|
||||
}
|
||||
|
||||
private function applyCustomization(array $layout, EventJoinToken $joinToken): array
|
||||
{
|
||||
$customization = data_get($joinToken->metadata, 'layout_customization');
|
||||
|
||||
if (! is_array($customization)) {
|
||||
return $layout;
|
||||
}
|
||||
|
||||
$layoutId = $customization['layout_id'] ?? null;
|
||||
if (is_string($layoutId) && isset($layout['id']) && $layoutId !== $layout['id']) {
|
||||
// Allow customization to target a specific layout; if mismatch, skip style overrides.
|
||||
// General text overrides are still applied below.
|
||||
}
|
||||
|
||||
$colorKeys = [
|
||||
'accent' => 'accent_color',
|
||||
'text' => 'text_color',
|
||||
'background' => 'background_color',
|
||||
'secondary' => 'secondary_color',
|
||||
'badge' => 'badge_color',
|
||||
];
|
||||
|
||||
foreach ($colorKeys as $layoutKey => $customKey) {
|
||||
if (isset($customization[$customKey]) && is_string($customization[$customKey])) {
|
||||
$layout[$layoutKey] = $customization[$customKey];
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($customization['background_gradient']) && is_array($customization['background_gradient'])) {
|
||||
$layout['background_gradient'] = $customization['background_gradient'];
|
||||
}
|
||||
|
||||
foreach (['headline' => 'name', 'subtitle', 'description', 'badge_label', 'instructions_heading', 'link_heading', 'cta_label', 'cta_caption', 'link_label'] as $customKey => $layoutKey) {
|
||||
if (isset($customization[$customKey]) && is_string($customization[$customKey])) {
|
||||
$layout[$layoutKey] = $customization[$customKey];
|
||||
}
|
||||
}
|
||||
|
||||
if (array_key_exists('instructions', $customization) && is_array($customization['instructions'])) {
|
||||
$layout['instructions'] = array_values(array_filter($customization['instructions'], fn ($value) => is_string($value) && trim($value) !== ''));
|
||||
}
|
||||
|
||||
if (! empty($customization['logo_data_url']) && is_string($customization['logo_data_url'])) {
|
||||
$layout['logo_url'] = $customization['logo_data_url'];
|
||||
} elseif (! empty($customization['logo_url']) && is_string($customization['logo_url'])) {
|
||||
$layout['logo_url'] = $customization['logo_url'];
|
||||
}
|
||||
|
||||
return $layout;
|
||||
}
|
||||
|
||||
private function buildBackgroundStyle(array $layout): string
|
||||
{
|
||||
$gradient = $layout['background_gradient'] ?? null;
|
||||
@@ -128,4 +182,4 @@ class EventJoinTokenLayoutController extends Controller
|
||||
|
||||
return $layout['background'] ?? '#FFFFFF';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
63
app/Http/Controllers/Api/Tenant/TenantFeedbackController.php
Normal file
63
app/Http/Controllers/Api/Tenant/TenantFeedbackController.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api\Tenant;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Event;
|
||||
use App\Models\TenantFeedback;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class TenantFeedbackController extends Controller
|
||||
{
|
||||
public function store(Request $request): JsonResponse
|
||||
{
|
||||
$tenantId = $request->attributes->get('tenant_id');
|
||||
|
||||
if (! $tenantId) {
|
||||
abort(403, 'Unauthorised');
|
||||
}
|
||||
|
||||
$validated = $request->validate([
|
||||
'category' => ['required', 'string', 'max:80'],
|
||||
'sentiment' => ['nullable', 'string', Rule::in(['positive', 'neutral', 'negative'])],
|
||||
'rating' => ['nullable', 'integer', 'min:1', 'max:5'],
|
||||
'title' => ['nullable', 'string', 'max:120'],
|
||||
'message' => ['nullable', 'string', 'max:2000'],
|
||||
'event_slug' => ['nullable', 'string', 'max:255'],
|
||||
'metadata' => ['nullable', 'array'],
|
||||
]);
|
||||
|
||||
$eventId = null;
|
||||
if (! empty($validated['event_slug'])) {
|
||||
$eventSlug = $validated['event_slug'];
|
||||
$event = Event::query()
|
||||
->where('slug', $eventSlug)
|
||||
->where('tenant_id', $tenantId)
|
||||
->select('id')
|
||||
->first();
|
||||
|
||||
$eventId = $event?->id;
|
||||
}
|
||||
|
||||
$feedback = TenantFeedback::create([
|
||||
'tenant_id' => $tenantId,
|
||||
'event_id' => $eventId,
|
||||
'category' => $validated['category'],
|
||||
'sentiment' => $validated['sentiment'] ?? null,
|
||||
'rating' => $validated['rating'] ?? null,
|
||||
'title' => $validated['title'] ?? null,
|
||||
'message' => $validated['message'] ?? null,
|
||||
'metadata' => $validated['metadata'] ?? null,
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'message' => 'Feedback gespeichert',
|
||||
'data' => [
|
||||
'id' => $feedback->id,
|
||||
'created_at' => $feedback->created_at?->toIso8601String(),
|
||||
],
|
||||
], 201);
|
||||
}
|
||||
}
|
||||
@@ -7,22 +7,25 @@ use App\Models\OAuthCode;
|
||||
use App\Models\RefreshToken;
|
||||
use App\Models\Tenant;
|
||||
use App\Models\TenantToken;
|
||||
use Firebase\JWT\JWT;
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Str;
|
||||
use Firebase\JWT\JWT;
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class OAuthController extends Controller
|
||||
{
|
||||
private const AUTH_CODE_TTL_MINUTES = 5;
|
||||
|
||||
private const ACCESS_TOKEN_TTL_SECONDS = 3600;
|
||||
|
||||
private const REFRESH_TOKEN_TTL_DAYS = 30;
|
||||
|
||||
private const LEGACY_TOKEN_HEADER_KID = 'fotospiel-jwt';
|
||||
|
||||
/**
|
||||
@@ -104,6 +107,14 @@ class OAuthController extends Controller
|
||||
'state' => $request->state,
|
||||
]);
|
||||
|
||||
if ($this->shouldReturnJsonAuthorizeResponse($request)) {
|
||||
return response()->json([
|
||||
'code' => $code,
|
||||
'state' => $request->state,
|
||||
'redirect_url' => $redirectUrl,
|
||||
]);
|
||||
}
|
||||
|
||||
return redirect()->away($redirectUrl);
|
||||
}
|
||||
|
||||
@@ -402,6 +413,40 @@ class OAuthController extends Controller
|
||||
];
|
||||
}
|
||||
|
||||
private function shouldReturnJsonAuthorizeResponse(Request $request): bool
|
||||
{
|
||||
if ($request->expectsJson() || $request->ajax()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$redirectUri = (string) $request->string('redirect_uri');
|
||||
$redirectHost = $redirectUri !== '' ? parse_url($redirectUri, PHP_URL_HOST) : null;
|
||||
$requestHost = $request->getHost();
|
||||
|
||||
if ($redirectHost && ! $this->hostsMatch($requestHost, $redirectHost)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$origin = $request->headers->get('Origin');
|
||||
if ($origin) {
|
||||
$originHost = parse_url($origin, PHP_URL_HOST);
|
||||
if ($originHost && $redirectHost && ! $this->hostsMatch($originHost, $redirectHost)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private function hostsMatch(?string $first, ?string $second): bool
|
||||
{
|
||||
if (! $first || ! $second) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return strtolower($first) === strtolower($second);
|
||||
}
|
||||
|
||||
private function createRefreshToken(Tenant $tenant, OAuthClient $client, array $scopes, string $accessTokenJti, Request $request): string
|
||||
{
|
||||
$refreshTokenId = (string) Str::uuid();
|
||||
@@ -566,6 +611,7 @@ class OAuthController extends Controller
|
||||
File::put($directory.DIRECTORY_SEPARATOR.'public.key', $publicKey, true);
|
||||
File::chmod($directory.DIRECTORY_SEPARATOR.'public.key', 0644);
|
||||
}
|
||||
|
||||
private function scopesAreAllowed(array $requestedScopes, array $availableScopes): bool
|
||||
{
|
||||
if (empty($requestedScopes)) {
|
||||
@@ -682,7 +728,7 @@ class OAuthController extends Controller
|
||||
return redirect('/event-admin')->with('error', 'Invalid state parameter');
|
||||
}
|
||||
|
||||
$client = new Client();
|
||||
$client = new Client;
|
||||
$clientId = config('services.stripe.connect_client_id');
|
||||
$secret = config('services.stripe.connect_secret');
|
||||
$redirectUri = url('/api/v1/oauth/stripe-callback');
|
||||
@@ -710,11 +756,12 @@ class OAuthController extends Controller
|
||||
}
|
||||
|
||||
session()->forget(['stripe_state', 'tenant_id']);
|
||||
|
||||
return redirect('/event-admin')->with('success', 'Stripe account connected successfully');
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Stripe OAuth error: '.$e->getMessage());
|
||||
|
||||
return redirect('/event-admin')->with('error', 'Connection error: '.$e->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user