From 37a2fee910eda0ab141187c62cec2f521eca5775 Mon Sep 17 00:00:00 2001 From: Crypto2099 <63186174+Crypto2099@users.noreply.github.com> Date: Fri, 22 Sep 2023 22:31:45 -0700 Subject: [PATCH 1/4] Add support for testnet mode, add additional information about events and open graph data. --- .../Controllers/API/V1/NonceController.php | 273 ++++++++---------- .../Admin/ManageEventsController.php | 86 +++--- application/app/Models/Event.php | 14 +- application/app/Models/Ticket.php | 5 + application/app/Services/EventService.php | 78 ++--- .../CardanoClients/BlockFrostClient.php | 5 + application/config/filesystems.php | 30 +- ...23_042340_add_location_to_events_table.php | 39 +++ ..._09_23_043453_add_event_date_to_events.php | 32 ++ .../2023_09_23_043840_add_image_to_events.php | 31 ++ application/resources/nodejs/validateNonce.js | 8 +- .../views/admin/manage-events/form.blade.php | 95 +++++- .../views/admin/manage-events/view.blade.php | 47 ++- application/resources/views/event.blade.php | 156 +++++++--- .../resources/views/layouts/app.blade.php | 11 +- 15 files changed, 616 insertions(+), 294 deletions(-) create mode 100644 application/database/migrations/2023_09_23_042340_add_location_to_events_table.php create mode 100644 application/database/migrations/2023_09_23_043453_add_event_date_to_events.php create mode 100644 application/database/migrations/2023_09_23_043840_add_image_to_events.php diff --git a/application/app/Http/Controllers/API/V1/NonceController.php b/application/app/Http/Controllers/API/V1/NonceController.php index 0cbb39e..7c9aa5d 100644 --- a/application/app/Http/Controllers/API/V1/NonceController.php +++ b/application/app/Http/Controllers/API/V1/NonceController.php @@ -2,95 +2,86 @@ namespace App\Http\Controllers\API\V1; -use Exception; -use Throwable; -use Carbon\Carbon; +use App\Exceptions\AppException; +use App\Http\Controllers\Controller; +use App\Http\Traits\JsonResponseTrait; use App\Models\Event; -use Ramsey\Uuid\Uuid; use App\Models\Ticket; -use Endroid\QrCode\QrCode; -use Illuminate\Http\Request; use App\Services\EventService; use App\Services\TicketService; -use Endroid\QrCode\Label\Label; +use App\ThirdParty\CardanoClients\ICardanoClient; +use Carbon\Carbon; use Endroid\QrCode\Color\Color; -use App\Exceptions\AppException; -use Illuminate\Http\JsonResponse; -use Endroid\QrCode\Writer\PngWriter; -use App\Http\Controllers\Controller; use Endroid\QrCode\Encoding\Encoding; -use App\Http\Traits\JsonResponseTrait; +use Endroid\QrCode\ErrorCorrectionLevel\ErrorCorrectionLevelHigh; use Endroid\QrCode\Label\Font\NotoSans; -use Symfony\Component\HttpFoundation\Response; -use App\ThirdParty\CardanoClients\ICardanoClient; +use Endroid\QrCode\Label\Label; +use Endroid\QrCode\QrCode; use Endroid\QrCode\RoundBlockSizeMode\RoundBlockSizeModeEnlarge; -use Endroid\QrCode\ErrorCorrectionLevel\ErrorCorrectionLevelHigh; +use Endroid\QrCode\Writer\PngWriter; +use Exception; +use Illuminate\Http\JsonResponse; +use Illuminate\Http\Request; +use Ramsey\Uuid\Uuid; +use Symfony\Component\HttpFoundation\Response; +use Throwable; + +class NonceController extends Controller { -class NonceController extends Controller -{ use JsonResponseTrait; private EventService $eventService; private TicketService $ticketService; private ICardanoClient $cardanoClient; - public function __construct( - EventService $eventService, - TicketService $ticketService, - ICardanoClient $cardanoClient, - ) - { - $this->eventService = $eventService; + public function __construct(EventService $eventService, TicketService $ticketService, ICardanoClient $cardanoClient,) { + $this->eventService = $eventService; $this->ticketService = $ticketService; $this->cardanoClient = $cardanoClient; } - public function generateNonce(Request $request): JsonResponse - { + public function generateNonce(Request $request): JsonResponse { try { $request->validate([ - 'event_uuid' => ['required', 'uuid'], - 'policy_id' => ['required', 'string'], - 'asset_id' => ['required', 'string'], - 'stake_key' => ['required', 'string'], + 'event_uuid' => [ + 'required', + 'uuid', + ], + 'policy_id' => [ + 'required', + 'string', + ], + 'asset_id' => [ + 'required', + 'string', + ], + 'stake_key' => [ + 'required', + 'string', + ], ]); $event = $this->eventService->findByUUID($request->event_uuid); if (!$event) { - return $this->errorResponse( - trans('Event not found'), - Response::HTTP_NOT_FOUND - ); + return $this->errorResponse(trans('Event not found'), Response::HTTP_NOT_FOUND); } $this->ensureEventIsActive($event); if (!$this->cardanoClient->assetHodled($request->policy_id, $request->asset_id, $request->stake_key)) { - return $this->errorResponse( - trans( - 'Asset :assetName not found in wallet', - [ - 'assetName' => hex2bin($request->asset_id), - ], - ), - Response::HTTP_BAD_REQUEST - ); + return $this->errorResponse(trans('Asset :assetName not found in wallet', [ + 'assetName' => hex2bin($request->asset_id), + ],), Response::HTTP_BAD_REQUEST); } - $ticket = $this->ticketService->findExistingTicket( - $event->id, - $request->policy_id, - $request->asset_id, - $request->stake_key, - ); + $ticket = $this->ticketService->findExistingTicket($event->id, $request->policy_id, $request->asset_id, + $request->stake_key,); if ($ticket && $ticket->isCheckedIn) { - return $this->errorResponse( - trans('Sorry, this asset has already checked in to this event'), - Response::HTTP_BAD_REQUEST, - ); + return $this->errorResponse(trans('Sorry, this asset has already checked in to this event'), + Response::HTTP_BAD_REQUEST,); } if ($this->ticketSignByExpired($event, $ticket)) { @@ -101,12 +92,8 @@ public function generateNonce(Request $request): JsonResponse } if (!$ticket) { - $ticket = $this->ticketService->createNewTicket( - $event->id, - $request->policy_id, - $request->asset_id, - $request->stake_key, - ); + $ticket = $this->ticketService->createNewTicket($event->id, $request->policy_id, $request->asset_id, + $request->stake_key,); } return $this->successResponse([ @@ -123,17 +110,14 @@ public function generateNonce(Request $request): JsonResponse /** * @throws AppException */ - private function ensureEventIsActive(Event $event): void - { + private function ensureEventIsActive(Event $event): void { $now = Carbon::now(); if (!empty($event->startDateTime) && $now->isBefore($event->startDateTime)) { - throw new AppException(trans( - 'Sorry, registration for this event has not started yet
Come back :tryAgainIn', + throw new AppException(trans('Sorry, registration for this event has not started yet
Come back :tryAgainIn', [ 'tryAgainIn' => $event->startDateTime->diffForHumans(), - ], - )); + ],)); } if ($now->isAfter($event->endDateTime)) { @@ -141,17 +125,12 @@ private function ensureEventIsActive(Event $event): void } } - private function ticketSignByExpired(Event $event, ?Ticket $ticket = null): bool - { - return ( - $ticket && - $ticket->created_at->diffInMinutes(Carbon::now()) > $event->nonceValidForMinutes - ); + private function ticketSignByExpired(Event $event, ?Ticket $ticket = null): bool { + return ($ticket && $ticket->created_at->diffInMinutes(Carbon::now()) > $event->nonceValidForMinutes); } /** * Signing canonical JSON -> CBOR format - * * { * "assetId": "tickets.assetId", * "createdAt": "tickets.created_at(ATOM_DATE_TIME_FORMAT)", @@ -164,42 +143,58 @@ private function ticketSignByExpired(Event $event, ?Ticket $ticket = null): bool * "type": "GateKeeperTicket", * "version": "1.0.0" * } + * * @throws \JsonException */ - private function generateSigningJson(Event $event, Ticket $ticket): string - { - $signBy = $ticket - ->created_at - ->clone() - ->addMinutes($event->nonceValidForMinutes) - ->format(ATOM_DATE_TIME_FORMAT) - ; + private function generateSigningJson(Event $event, Ticket $ticket): string { + $signBy = $ticket->created_at->clone() + ->addMinutes($event->nonceValidForMinutes) + ->format(ATOM_DATE_TIME_FORMAT); return json_encode([ - 'assetId' => $ticket->assetId, + 'assetId' => $ticket->assetId, 'createdAt' => $ticket->created_at->format(ATOM_DATE_TIME_FORMAT), - 'eventId' => $event->uuid, + 'eventId' => $event->uuid, 'eventName' => $event->name, - 'policyId' => $ticket->policyId, - 'signBy' => $signBy, - 'stakeKey' => $ticket->stakeKey, - 'ticketId' => Uuid::fromBytes($ticket->signatureNonce)->toString(), - 'type' => TICKET_TYPE, - 'version' => TICKET_VERSION + 'policyId' => $ticket->policyId, + 'signBy' => $signBy, + 'stakeKey' => $ticket->stakeKey, + 'ticketId' => Uuid::fromBytes($ticket->signatureNonce) + ->toString(), + 'type' => TICKET_TYPE, + 'version' => TICKET_VERSION, ], JSON_THROW_ON_ERROR); } - public function validateNonce(Request $request): JsonResponse - { + public function validateNonce(Request $request): JsonResponse { + try { $request->validate([ - 'event_uuid' => ['required', 'uuid'], - 'policy_id' => ['required', 'string'], - 'asset_id' => ['required', 'string'], - 'stake_key' => ['required', 'string'], - 'signature' => ['required', 'string'], - 'key' => ['required', 'string'], + 'event_uuid' => [ + 'required', + 'uuid', + ], + 'policy_id' => [ + 'required', + 'string', + ], + 'asset_id' => [ + 'required', + 'string', + ], + 'stake_key' => [ + 'required', + 'string', + ], + 'signature' => [ + 'required', + 'string', + ], + 'key' => [ + 'required', + 'string', + ], ]); $event = $this->eventService->findByUUID($request->event_uuid); @@ -208,39 +203,27 @@ public function validateNonce(Request $request): JsonResponse return $this->errorResponse(trans('Event not found'), Response::HTTP_NOT_FOUND); } - $this->ensureEventIsActive($event); - if (!$this->cardanoClient->assetHodled($request->policy_id, $request->asset_id, $request->stake_key)) { - return $this->errorResponse( - trans( - 'Asset :assetName not found in wallet', - [ - 'assetName' => hex2bin($request->asset_id), - ], - ), - Response::HTTP_BAD_REQUEST - ); + return $this->errorResponse(trans('Asset :assetName not found in wallet', [ + 'assetName' => hex2bin($request->asset_id), + ]), Response::HTTP_BAD_REQUEST); } - $ticket = $this->ticketService->findExistingTicket( - $event->id, - $request->policy_id, - $request->asset_id, - $request->stake_key, - ); + $ticket = $this->ticketService->findExistingTicket($event->id, $request->policy_id, $request->asset_id, + $request->stake_key,); if (!$ticket) { return $this->errorResponse(trans('Ticket not found'), Response::HTTP_NOT_FOUND); } - if ($this->ticketSignByExpired($event, $ticket)) { - return $this->errorResponse( - trans('Sorry, the signature request expired - please try again'), - Response::HTTP_BAD_REQUEST, - ); - } +// if ($this->ticketSignByExpired($event, $ticket)) { +// return $this->errorResponse(trans('Sorry, the signature request expired - please try again'), +// Response::HTTP_BAD_REQUEST,); +// } + + if (!$validation_response = $this->validSignature($request->signature, $request->key, + $this->generateSigningJson($event, $ticket), $ticket->stakeKey)) { - if (!$this->validSignature($request->signature, $request->key, $this->generateSigningJson($event, $ticket), $ticket->stakeKey)) { return $this->errorResponse(trans('Invalid signature'), Response::HTTP_BAD_REQUEST); } @@ -252,13 +235,17 @@ public function validateNonce(Request $request): JsonResponse $qrValue = implode('|', [ $ticket->assetId, - Uuid::fromBytes($ticket->ticketNonce)->toString(), + Uuid::fromBytes($ticket->ticketNonce) + ->toString(), ]); + $ticket_security_code = Uuid::fromBytes($ticket->ticketNonce) + ->toString(); + return $this->successResponse([ - 'assetId' => $ticket->assetId, - 'securityCode' => Uuid::fromBytes($ticket->ticketNonce)->toString(), - 'qr' => $this->generateQRCode($ticket->assetId, $qrValue), + 'assetId' => $ticket->assetId, + 'securityCode' => $ticket_security_code, + 'qr' => $this->generateQRCode($ticket->assetId, $qrValue), ]); } catch (Throwable $exception) { @@ -268,37 +255,29 @@ public function validateNonce(Request $request): JsonResponse } } - private function validSignature(string $signature, string $key, string $signatureNonce, string $stakeKey): bool - { - return trim(shell_exec(sprintf( - 'node %s %s %s %s %s', - resource_path('nodejs/validateNonce.js'), - $signature, - $key, - bin2hex($signatureNonce), - $stakeKey - ))) === 'true'; + private function validSignature(string $signature, string $key, string $signatureNonce, string $stakeKey): bool { + + return trim(shell_exec(sprintf('node %s %s %s %s %s %s', resource_path('nodejs/validateNonce.js'), $signature, + $key, bin2hex($signatureNonce), $stakeKey, env('CARDANO_NETWORK')))); } /** * @throws Exception */ - private function generateQRCode(string $assetId, string $qrValue): string - { + private function generateQRCode(string $assetId, string $qrValue): string { $qrCode = QrCode::create($qrValue) - ->setEncoding(new Encoding('ISO-8859-1')) - ->setErrorCorrectionLevel(new ErrorCorrectionLevelHigh()) - ->setSize(512) - ->setMargin(10) - ->setRoundBlockSizeMode(new RoundBlockSizeModeEnlarge()) - ->setForegroundColor(new Color(0, 0, 0)); + ->setEncoding(new Encoding('ISO-8859-1')) + ->setErrorCorrectionLevel(new ErrorCorrectionLevelHigh()) + ->setSize(512) + ->setMargin(10) + ->setRoundBlockSizeMode(new RoundBlockSizeModeEnlarge()) + ->setForegroundColor(new Color(0, 0, 0)); $label = Label::create(hex2bin($assetId)) - ->setFont(new NotoSans(20)) - ->setTextColor(new Color(0, 0, 0)); + ->setFont(new NotoSans(20)) + ->setTextColor(new Color(0, 0, 0)); - return (new PngWriter()) - ->write($qrCode, null, $label) - ->getDataUri(); + return (new PngWriter())->write($qrCode, null, $label) + ->getDataUri(); } } diff --git a/application/app/Http/Controllers/Admin/ManageEventsController.php b/application/app/Http/Controllers/Admin/ManageEventsController.php index c2a8615..d54f2eb 100644 --- a/application/app/Http/Controllers/Admin/ManageEventsController.php +++ b/application/app/Http/Controllers/Admin/ManageEventsController.php @@ -2,50 +2,44 @@ namespace App\Http\Controllers\Admin; -use Throwable; +use App\Http\Controllers\Controller; use App\Models\Event; -use Illuminate\Http\Request; use App\Services\EventService; -use App\Http\Controllers\Controller; -use Illuminate\Http\RedirectResponse; use Illuminate\Contracts\Support\Renderable; +use Illuminate\Http\RedirectResponse; +use Illuminate\Http\Request; +use Throwable; + +class ManageEventsController extends Controller { -class ManageEventsController extends Controller -{ private EventService $eventService; - public function __construct(EventService $eventService) - { + public function __construct(EventService $eventService) { $this->eventService = $eventService; } - public function index(): Renderable - { + public function index(): Renderable { $allEvents = $this->eventService->getEventList(true); - return view( - 'admin.manage-events.index', - compact('allEvents'), - ); + return view('admin.manage-events.index', compact('allEvents'),); } - public function create(): Renderable - { + public function create(): Renderable { $event = null; - return view( - 'admin.manage-events.form', - compact('event'), - ); + return view('admin.manage-events.form', compact('event'),); } - public function store(Request $request): RedirectResponse - { + public function store(Request $request): RedirectResponse { try { $payload = $request->only([ 'event_id', 'name', + 'location', + 'eventDate', + 'eventStart', + 'eventEnd', 'startDateTime', 'endDateTime', 'hodlAsset', @@ -53,43 +47,47 @@ public function store(Request $request): RedirectResponse 'nonceValidForMinutes', ]); + if ($request->file('image')) { + $payload['image'] = $request->file('image')->store('public'); + } + + $this->eventService->save($payload); return redirect() ->route('manage-events.index') - ->with('status', !empty($request->event_id) - ? trans('Event updated') - : trans('Event created') - ); + ->with('status', !empty($request->event_id) ? trans('Event updated') : trans('Event created')); } catch (Throwable $exception) { - return redirectBackWithError( - trans('Failed to save event'), - $exception, - ); + return redirectBackWithError(trans('Failed to save event'), $exception,); } } - public function show(Event $event): Renderable - { - return view( - 'admin.manage-events.view', - compact('event'), - ); + public function show(Event $event): Renderable { + $event_tickets = $event->tickets; + $tickets = [ + 'total' => count($event_tickets), + 'checked_in' => 0, + 'event_tickets' => $event_tickets, + ]; + + foreach ($event_tickets as $ticket) { + if ($ticket->isCheckedIn) { + $tickets['checked_in']++; + } + } + +// $tickets = $event->tickets; + return view('admin.manage-events.view', compact('event', 'tickets'),); } - public function edit(Event $event): Renderable - { - return view( - 'admin.manage-events.form', - compact('event'), - ); + public function edit(Event $event): Renderable { + return view('admin.manage-events.form', compact('event'),); } - public function destroy(Event $event): void - { + public function destroy(Event $event): void { dd('TODO'); } } diff --git a/application/app/Models/Event.php b/application/app/Models/Event.php index 99c3e0a..47695a4 100644 --- a/application/app/Models/Event.php +++ b/application/app/Models/Event.php @@ -4,9 +4,10 @@ use App\Casts\Json; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\HasMany; + +class Event extends Model { -class Event extends Model -{ /** * @var string[] $fillable */ @@ -18,6 +19,11 @@ class Event extends Model 'hodlAsset', 'startDateTime', 'endDateTime', + 'location', + 'eventStart', + 'eventEnd', + 'eventDate', + 'image', ]; /** @@ -38,4 +44,8 @@ class Event extends Model 'startDateTime', 'endDateTime', ]; + + public function tickets(): HasMany { + return $this->hasMany(Ticket::class, 'eventId'); + } } diff --git a/application/app/Models/Ticket.php b/application/app/Models/Ticket.php index 651b358..803079c 100644 --- a/application/app/Models/Ticket.php +++ b/application/app/Models/Ticket.php @@ -3,6 +3,7 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsTo; class Ticket extends Model { @@ -32,4 +33,8 @@ class Ticket extends Model protected $dates = [ 'checkInTime', ]; + + public function event(): BelongsTo { + return $this->belongsTo(Event::class, 'eventId'); + } } diff --git a/application/app/Services/EventService.php b/application/app/Services/EventService.php index a8231bc..c538732 100644 --- a/application/app/Services/EventService.php +++ b/application/app/Services/EventService.php @@ -2,16 +2,15 @@ namespace App\Services; -use App\Models\Event; use App\Exceptions\AppException; -use Illuminate\Support\Facades\Validator; +use App\Models\Event; use Illuminate\Database\Eloquent\Collection; +use Illuminate\Support\Facades\Validator; use Illuminate\Validation\ValidationException; -class EventService -{ - public function getEventList($fullInfo = false): Collection - { +class EventService { + + public function getEventList($fullInfo = false): Collection { $selectColumns = [ 'uuid', 'name', @@ -19,16 +18,13 @@ public function getEventList($fullInfo = false): Collection ]; if ($fullInfo) { - $selectColumns = array_merge( - $selectColumns, - [ - 'id', - 'nonceValidForMinutes', - 'hodlAsset', - 'startDateTime', - 'endDateTime', - ] - ); + $selectColumns = array_merge($selectColumns, [ + 'id', + 'nonceValidForMinutes', + 'hodlAsset', + 'startDateTime', + 'endDateTime', + ]); } return Event::all($selectColumns); @@ -37,8 +33,7 @@ public function getEventList($fullInfo = false): Collection /** * @throws AppException|ValidationException */ - public function save(array $payload): void - { + public function save(array $payload): void { $event = null; if (!empty($payload['event_id']) && !$event = $this->findById($payload['event_id'])) { throw new AppException(trans('Event not found')); @@ -47,21 +42,38 @@ public function save(array $payload): void $payload['policyIds'] = array_filter(preg_split("/\r\n|\n|\r/", $payload['policyIds'])); $validationRules = [ - 'name' => ['required', 'min:3'], - 'policyIds' => ['required', 'array', 'min:1'], - 'endDateTime' => ['required', 'date'], - 'startDateTime' => ['date'], - 'hodlAsset' => ['integer'], - 'nonceValidForMinutes' => ['required', 'integer', 'min:5'] + 'name' => [ + 'required', + 'min:3', + ], + 'policyIds' => [ + 'required', + 'array', + 'min:1', + ], + 'endDateTime' => [ + 'required', + 'date', + ], + 'startDateTime' => ['date'], + 'hodlAsset' => ['integer'], + 'nonceValidForMinutes' => [ + 'required', + 'integer', + 'min:5', + ], + 'location' => ['string'], + 'eventStart' => ['string'], + 'eventEnd' => ['string'], + 'eventDate' => ['date'], + 'image' => ['string'], ]; $validator = Validator::make($payload, $validationRules); if ($validator->fails()) { - throw new AppException(sprintf( - '%s: %s', - trans('validation errors'), implode(' ', $validator->errors()->all()) - )); + throw new AppException(sprintf('%s: %s', trans('validation errors'), implode(' ', $validator->errors() + ->all()))); } if (!$event) { @@ -78,15 +90,13 @@ public function save(array $payload): void $event->save(); } - public function findById(int $eventId): ?Event - { + public function findById(int $eventId): ?Event { return Event::where('id', $eventId) - ->first(); + ->first(); } - public function findByUUID(string $uuid): ?Event - { + public function findByUUID(string $uuid): ?Event { return Event::where('uuid', $uuid) - ->first(); + ->first(); } } diff --git a/application/app/ThirdParty/CardanoClients/BlockFrostClient.php b/application/app/ThirdParty/CardanoClients/BlockFrostClient.php index 214b129..49b7e5c 100644 --- a/application/app/ThirdParty/CardanoClients/BlockFrostClient.php +++ b/application/app/ThirdParty/CardanoClients/BlockFrostClient.php @@ -35,6 +35,8 @@ public function assetHodled(string $policyId, string $assetId, string $stakeKey) throw new AppException(trans('Asset not found in any wallets')); } + error_log("Blockfrost response:\r\n".print_r($assetAddresses,true)); + $firstAssetAddress = $assetAddresses[0]['address']; $addressInfo = $this->call( @@ -42,6 +44,9 @@ public function assetHodled(string $policyId, string $assetId, string $stakeKey) "addresses/{$firstAssetAddress}", ); +// error_log("Address details:\r\n".json_encode($addressInfo, JSON_PRETTY_PRINT|JSON_UNESCAPED_SLASHES)); + error_log("Got address details {$stakeKey} {$addressInfo['stake_address']}"); + return $addressInfo['stake_address'] === $stakeKey; } diff --git a/application/config/filesystems.php b/application/config/filesystems.php index e9d9dbd..9c5b1cc 100644 --- a/application/config/filesystems.php +++ b/application/config/filesystems.php @@ -32,28 +32,28 @@ 'local' => [ 'driver' => 'local', - 'root' => storage_path('app'), - 'throw' => false, + 'root' => storage_path('app'), + 'throw' => false, ], 'public' => [ - 'driver' => 'local', - 'root' => storage_path('app/public'), - 'url' => env('APP_URL').'/storage', + 'driver' => 'local', + 'root' => storage_path('app/public'), + 'url' => env('APP_URL') . '/storage', 'visibility' => 'public', - 'throw' => false, + 'throw' => false, ], 's3' => [ - 'driver' => 's3', - 'key' => env('AWS_ACCESS_KEY_ID'), - 'secret' => env('AWS_SECRET_ACCESS_KEY'), - 'region' => env('AWS_DEFAULT_REGION'), - 'bucket' => env('AWS_BUCKET'), - 'url' => env('AWS_URL'), - 'endpoint' => env('AWS_ENDPOINT'), + 'driver' => 's3', + 'key' => env('AWS_ACCESS_KEY_ID'), + 'secret' => env('AWS_SECRET_ACCESS_KEY'), + 'region' => env('AWS_DEFAULT_REGION'), + 'bucket' => env('AWS_BUCKET'), + 'url' => env('AWS_URL'), + 'endpoint' => env('AWS_ENDPOINT'), 'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false), - 'throw' => false, + 'throw' => false, ], ], @@ -71,6 +71,8 @@ 'links' => [ public_path('storage') => storage_path('app/public'), + public_path('public') => storage_path('app/public'), + // public_path('images') => storage_path('app/images'), ], ]; diff --git a/application/database/migrations/2023_09_23_042340_add_location_to_events_table.php b/application/database/migrations/2023_09_23_042340_add_location_to_events_table.php new file mode 100644 index 0000000..f8e41b1 --- /dev/null +++ b/application/database/migrations/2023_09_23_042340_add_location_to_events_table.php @@ -0,0 +1,39 @@ +string('location') + ->nullable(); + $table->string('eventStart') + ->nullable(); + $table->string('eventEnd') + ->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() { + Schema::table('events', function (Blueprint $table) { + $table->dropColumn([ + 'location', + 'eventStart', + 'eventEnd', + ]); + }); + } +}; diff --git a/application/database/migrations/2023_09_23_043453_add_event_date_to_events.php b/application/database/migrations/2023_09_23_043453_add_event_date_to_events.php new file mode 100644 index 0000000..2dac2ee --- /dev/null +++ b/application/database/migrations/2023_09_23_043453_add_event_date_to_events.php @@ -0,0 +1,32 @@ +date('eventDate')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('events', function (Blueprint $table) { + $table->dropColumn(['eventDate']); + }); + } +}; diff --git a/application/database/migrations/2023_09_23_043840_add_image_to_events.php b/application/database/migrations/2023_09_23_043840_add_image_to_events.php new file mode 100644 index 0000000..87ccbe3 --- /dev/null +++ b/application/database/migrations/2023_09_23_043840_add_image_to_events.php @@ -0,0 +1,31 @@ +string('image') + ->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() { + Schema::table('events', function (Blueprint $table) { + $table->dropColumn(['image']); + }); + } +}; diff --git a/application/resources/nodejs/validateNonce.js b/application/resources/nodejs/validateNonce.js index 5390cca..678368e 100644 --- a/application/resources/nodejs/validateNonce.js +++ b/application/resources/nodejs/validateNonce.js @@ -16,19 +16,23 @@ const publicKeyToStakeKey = (publicKey) => { return CSL.Address.from_bytes(toHexBuffer(stake_arg)); } -const verifyData = (sig_cbor, key, payload, stake_address) => { +const verifyData = (sig_cbor, key, payload, stake_address, network_mode) => { const publicKey = sigKeyToPublicKey(key); const stakeAddr = publicKeyToStakeKey(publicKey); const coseSign1_verify = EMS.COSESign1.from_bytes(toHexBuffer(sig_cbor)); const signedSigStruc_verify = coseSign1_verify.signed_data(); const sig = CSL.Ed25519Signature.from_bytes(coseSign1_verify.signature()); - const walletMatches = stakeAddr.to_bech32('stake') === stake_address; + const stake_prefix = network_mode === 'mainnet' ? 'stake' : 'stake_test'; + + const walletMatches = stakeAddr.to_bech32(stake_prefix) === stake_address; const validates = publicKey.verify(signedSigStruc_verify.to_bytes(), sig); const payloadMatches = toHexString(signedSigStruc_verify.payload()) === payload; + console.log(walletMatches, payloadMatches, validates, stake_prefix, network_mode); + return walletMatches && payloadMatches && validates; } diff --git a/application/resources/views/admin/manage-events/form.blade.php b/application/resources/views/admin/manage-events/form.blade.php index f5fe7a4..d080fad 100644 --- a/application/resources/views/admin/manage-events/form.blade.php +++ b/application/resources/views/admin/manage-events/form.blade.php @@ -22,26 +22,83 @@
-
+ @csrf @if ($event) @endif -
- + +
+
+
+ + +

+ Ideal images should be 1200px by 630px and contain no or minimal text. +

+
+ @if ($event->image) +
+ +
+ @endif +
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
+
+
+ + +
+
-
- +
@@ -49,17 +106,24 @@ - +
-
- hodlAsset ? 'checked' : '') }} id="hodlAsset" value="1" /> - + hodlAsset ? 'checked' : '') }} id="hodlAsset" + value="1"/> +
@@ -69,20 +133,23 @@ Signature Expiration Period
- + minutes
Default: 15 minutes
-
- -
Please list each eligible policy on a new line
+ +
Please list each eligible policy on a new line +
-
- TODO: Add event statistics and information here ... +
+
+
+

{{$tickets['total']}}

+

Total Tickets

+
+ +
+
+
+

{{$tickets['checked_in']}}

+

Checked In

+
+ +
+
+ + + + + + + + + + @foreach($tickets['event_tickets'] as $ticket) + + + + + + @endforeach + +
PolicyAssetChecked In
{{$ticket->policyId}}{{hex2bin($ticket->assetId)}}{{$ticket->isCheckedIn}}
+ + +@endsection + +@section('footer.scripts') + + + + + @endsection diff --git a/application/resources/views/event.blade.php b/application/resources/views/event.blade.php index e470aab..5dee559 100644 --- a/application/resources/views/event.blade.php +++ b/application/resources/views/event.blade.php @@ -1,4 +1,16 @@ -@extends('layouts.app') +@extends('layouts.app')@section('title', $event->name) + +@section('og') + + @if($event->description) + + @endif + + @if($event->image) + + @endif + +@endsection @section('content')