You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
137 lines
4.8 KiB
137 lines
4.8 KiB
<?php
|
|
|
|
namespace App\Http\Controllers\Api\Admin;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Requests\Admin\StoreSignupChannelRequest;
|
|
use App\Http\Requests\Admin\UpdateSignupChannelRequest;
|
|
use App\Models\Competition;
|
|
use App\Models\SignupChannel;
|
|
use App\Support\ChannelEntryEncryption;
|
|
use Illuminate\Http\JsonResponse;
|
|
use Illuminate\Http\Response;
|
|
|
|
class SignupChannelController extends Controller
|
|
{
|
|
public function index(Competition $competition): JsonResponse
|
|
{
|
|
$channels = $competition->signupChannels()
|
|
->orderByDesc('id')
|
|
->get()
|
|
->map(fn (SignupChannel $channel) => $this->toSummary($channel, $competition))
|
|
->values();
|
|
|
|
return response()->json([
|
|
'data' => $channels,
|
|
]);
|
|
}
|
|
|
|
public function store(StoreSignupChannelRequest $request, Competition $competition): JsonResponse
|
|
{
|
|
/** @var SignupChannel $channel */
|
|
$channel = $competition->signupChannels()->create(
|
|
$this->normalizePayload($request->validated(), true)
|
|
);
|
|
|
|
return response()->json($this->toDetail($channel, $competition), 201);
|
|
}
|
|
|
|
public function show(Competition $competition, SignupChannel $signupChannel): JsonResponse
|
|
{
|
|
$this->assertChannelBelongs($competition, $signupChannel);
|
|
$this->ensureEncryptionKeyPair($signupChannel);
|
|
|
|
return response()->json($this->toDetail($signupChannel, $competition));
|
|
}
|
|
|
|
public function update(
|
|
UpdateSignupChannelRequest $request,
|
|
Competition $competition,
|
|
SignupChannel $signupChannel
|
|
): JsonResponse {
|
|
$this->assertChannelBelongs($competition, $signupChannel);
|
|
|
|
$signupChannel->fill($this->normalizePayload($request->validated()));
|
|
$signupChannel->ensureEncryptionKeyPair();
|
|
$signupChannel->save();
|
|
|
|
return response()->json($this->toDetail($signupChannel, $competition));
|
|
}
|
|
|
|
public function destroy(Competition $competition, SignupChannel $signupChannel): Response
|
|
{
|
|
$this->assertChannelBelongs($competition, $signupChannel);
|
|
$signupChannel->delete();
|
|
|
|
return response()->noContent();
|
|
}
|
|
|
|
/**
|
|
* @return array<string, mixed>
|
|
*/
|
|
private function toSummary(SignupChannel $channel, Competition $competition): array
|
|
{
|
|
return [
|
|
'id' => $channel->id,
|
|
'competition_id' => $channel->competition_id,
|
|
'competition_name' => $competition->name,
|
|
'channel_code' => $channel->channel_code,
|
|
'channel_name' => $channel->channel_name,
|
|
'status' => $channel->status,
|
|
'encryption_algorithm' => $channel->encryption_algorithm ?: ChannelEntryEncryption::ALGORITHM,
|
|
'entry_encryption_enabled' => (bool) $channel->entry_encryption_enabled,
|
|
'success_callback_url' => $channel->success_callback_url,
|
|
'success_callback_type' => $channel->success_callback_type ?: SignupChannel::CALLBACK_TYPE_WEB,
|
|
'mini_program_callback_path' => $channel->mini_program_callback_path,
|
|
'mini_program_callback_method' => $channel->mini_program_callback_method
|
|
?: SignupChannel::MINI_PROGRAM_METHOD_REDIRECT_TO,
|
|
'remark' => $channel->remark,
|
|
'created_at' => $channel->created_at?->toIso8601String(),
|
|
'updated_at' => $channel->updated_at?->toIso8601String(),
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @return array<string, mixed>
|
|
*/
|
|
private function toDetail(SignupChannel $channel, Competition $competition): array
|
|
{
|
|
$row = $this->toSummary($channel, $competition);
|
|
$row['shared_secret'] = $channel->shared_secret;
|
|
$row['encryption_public_key'] = $channel->encryption_public_key;
|
|
|
|
return $row;
|
|
}
|
|
|
|
private function assertChannelBelongs(Competition $competition, SignupChannel $channel): void
|
|
{
|
|
if ((int) $channel->competition_id !== (int) $competition->id) {
|
|
abort(404);
|
|
}
|
|
}
|
|
|
|
private function ensureEncryptionKeyPair(SignupChannel $channel): void
|
|
{
|
|
$channel->ensureEncryptionKeyPair();
|
|
if ($channel->isDirty()) {
|
|
$channel->save();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $payload
|
|
* @return array<string, mixed>
|
|
*/
|
|
private function normalizePayload(array $payload, bool $isCreate = false): array
|
|
{
|
|
if ($isCreate || array_key_exists('success_callback_url', $payload)) {
|
|
$payload['success_callback_url'] = trim((string) ($payload['success_callback_url'] ?? ''));
|
|
}
|
|
if ($isCreate || array_key_exists('mini_program_callback_path', $payload)) {
|
|
$payload['mini_program_callback_path'] = trim((string) ($payload['mini_program_callback_path'] ?? ''));
|
|
}
|
|
|
|
return $payload;
|
|
}
|
|
}
|