Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
1.7.0-beta
v1.7.1-beta
1 change: 1 addition & 0 deletions backend/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ APP_HOMEPAGE_VIEWS_UPDATE_BATCH_SIZE=8
APP_DISABLE_REGISTRATION=false
APP_STRIPE_CONNECT_ACCOUNT_TYPE=express
APP_PLATFORM_SUPPORT_EMAIL=support@your-website.com
APP_ALLOWED_INTERNAL_WEBHOOK_HOSTS=

STRIPE_PUBLIC_KEY=
STRIPE_SECRET_KEY=
Expand Down
32 changes: 31 additions & 1 deletion backend/app/DomainObjects/ProductCategoryDomainObject.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,40 @@

namespace HiEvents\DomainObjects;

use HiEvents\DomainObjects\Interfaces\IsSortable;
use HiEvents\DomainObjects\SortingAndFiltering\AllowedSorts;
use Illuminate\Support\Collection;

class ProductCategoryDomainObject extends Generated\ProductCategoryDomainObjectAbstract
class ProductCategoryDomainObject extends Generated\ProductCategoryDomainObjectAbstract implements IsSortable
{
public static function getDefaultSort(): string
{
return self::ORDER;
}

public static function getDefaultSortDirection(): string
{
return 'asc';
}

public static function getAllowedSorts(): AllowedSorts
{
return new AllowedSorts([
self::ORDER => [
'asc' => __('Order Ascending'),
'desc' => __('Order Descending'),
],
self::CREATED_AT => [
'asc' => __('Oldest First'),
'desc' => __('Newest First'),
],
self::NAME => [
'asc' => __('Name A-Z'),
'desc' => __('Name Z-A'),
],
]);
}

public ?Collection $products = null;

public function setProducts(Collection $products): void
Expand Down
4 changes: 2 additions & 2 deletions backend/app/Repository/Eloquent/AffiliateRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ public function findByEventId(int $eventId, QueryParamsDTO $params): LengthAware
}

$this->model = $this->model->orderBy(
column: $params->sort_by ?? AffiliateDomainObject::getDefaultSort(),
direction: $params->sort_direction ?? 'desc',
column: $this->validateSortColumn($params->sort_by, AffiliateDomainObject::class),
direction: $this->validateSortDirection($params->sort_direction, AffiliateDomainObject::class),
);

return $this->paginateWhere(
Expand Down
4 changes: 2 additions & 2 deletions backend/app/Repository/Eloquent/AttendeeRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,8 @@ public function findByEventId(int $eventId, QueryParamsDTO $params): LengthAware
$this->applyFilterFields($params, AttendeeDomainObject::getAllowedFilterFields(), prefix: 'attendees');
}

$sortBy = $params->sort_by ?? AttendeeDomainObject::getDefaultSort();
$sortDirection = $params->sort_direction ?? AttendeeDomainObject::getDefaultSortDirection();
$sortBy = $this->validateSortColumn($params->sort_by, AttendeeDomainObject::class);
$sortDirection = $this->validateSortDirection($params->sort_direction, AttendeeDomainObject::class);

if ($sortBy === AttendeeDomainObject::TICKET_NAME_SORT_KEY) {
$this->model = $this->model
Expand Down
23 changes: 23 additions & 0 deletions backend/app/Repository/Eloquent/BaseRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use BadMethodCallException;
use Carbon\Carbon;
use HiEvents\DomainObjects\Interfaces\DomainObjectInterface;
use HiEvents\DomainObjects\Interfaces\IsSortable;
use HiEvents\Http\DTO\QueryParamsDTO;
use HiEvents\Models\BaseModel;
use HiEvents\Repository\Eloquent\Value\Relationship;
Expand Down Expand Up @@ -54,6 +55,28 @@ public function __construct(Application $application, DatabaseManager $db)
*/
abstract protected function getModel(): string;

/**
* @param class-string<IsSortable> $domainObjectClass
*/
protected function validateSortColumn(?string $sortBy, string $domainObjectClass): string
{
$allowedColumns = array_keys($domainObjectClass::getAllowedSorts()->toArray());
$default = $domainObjectClass::getDefaultSort();

if ($sortBy === null || !in_array($sortBy, $allowedColumns, true)) {
return $default;
}

return $sortBy;
}

protected function validateSortDirection(?string $sortDirection, string $domainObjectClass): string
{
return in_array(strtolower($sortDirection ?? ''), ['asc', 'desc'], true)
? $sortDirection
: $domainObjectClass::getDefaultSortDirection();
}

public function setMaxPerPage(int $maxPerPage): static
{
$this->maxPerPage = $maxPerPage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ public function findByEventId(int $eventId, QueryParamsDTO $params): LengthAware
}

$this->model = $this->model->orderBy(
$params->sort_by ?? CapacityAssignmentDomainObject::getDefaultSort(),
$params->sort_direction ?? CapacityAssignmentDomainObject::getDefaultSortDirection(),
$this->validateSortColumn($params->sort_by, CapacityAssignmentDomainObject::class),
$this->validateSortDirection($params->sort_direction, CapacityAssignmentDomainObject::class),
);

return $this->paginateWhere(
Expand Down
4 changes: 2 additions & 2 deletions backend/app/Repository/Eloquent/CheckInListRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,8 @@ public function findByEventId(int $eventId, QueryParamsDTO $params): LengthAware
}

$this->model = $this->model->orderBy(
$params->sort_by ?? CheckInListDomainObject::getDefaultSort(),
$params->sort_direction ?? CheckInListDomainObject::getDefaultSortDirection(),
$this->validateSortColumn($params->sort_by, CheckInListDomainObject::class),
$this->validateSortDirection($params->sort_direction, CheckInListDomainObject::class),
);

return $this->paginateWhere(
Expand Down
4 changes: 2 additions & 2 deletions backend/app/Repository/Eloquent/EventRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,8 @@ public function findEvents(array $where, QueryParamsDTO $params): LengthAwarePag
}

$this->model = $this->model->orderBy(
$params->sort_by ?? EventDomainObject::getDefaultSort(),
$params->sort_direction ?? EventDomainObject::getDefaultSortDirection(),
$this->validateSortColumn($params->sort_by, EventDomainObject::class),
$this->validateSortDirection($params->sort_direction, EventDomainObject::class),
);

return $this->paginateWhere(
Expand Down
4 changes: 2 additions & 2 deletions backend/app/Repository/Eloquent/MessageRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ public function findByEventId(int $eventId, QueryParamsDTO $params): LengthAware
}

$this->model = $this->model->orderBy(
$params->sort_by ?? MessageDomainObject::getDefaultSort(),
$params->sort_direction ?? 'desc',
$this->validateSortColumn($params->sort_by, MessageDomainObject::class),
$this->validateSortDirection($params->sort_direction, MessageDomainObject::class),
);

return $this->paginateWhere(
Expand Down
9 changes: 5 additions & 4 deletions backend/app/Repository/Eloquent/OrderRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ public function findByEventId(int $eventId, QueryParamsDTO $params): LengthAware
}

$this->model = $this->model->orderBy(
column: $params->sort_by ?? OrderDomainObject::getDefaultSort(),
direction: $params->sort_direction ?? 'desc',
column: $this->validateSortColumn($params->sort_by, OrderDomainObject::class),
direction: $this->validateSortDirection($params->sort_direction, OrderDomainObject::class),
);

return $this->paginateWhere(
Expand Down Expand Up @@ -102,9 +102,10 @@ public function findByOrganizerId(int $organizerId, int $accountId, QueryParamsD
->where('events.organizer_id', $organizerId)
->where('events.account_id', $accountId);

$sortBy = $this->validateSortColumn($params->sort_by, OrderDomainObject::class);
$this->model = $this->model->orderBy(
column: $params->sort_by ? 'orders.' . $params->sort_by : 'orders.' . OrderDomainObject::getDefaultSort(),
direction: $params->sort_direction ?? 'desc',
column: 'orders.' . $sortBy,
direction: $this->validateSortDirection($params->sort_direction, OrderDomainObject::class),
);

return $this->paginateWhere(
Expand Down
8 changes: 4 additions & 4 deletions backend/app/Repository/Eloquent/ProductCategoryRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ public function findByEventId(int $eventId, QueryParamsDTO $queryParamsDTO): Col
}
}

// Apply sorting from QueryParamsDTO
if (!empty($queryParamsDTO->sort_by)) {
$query->orderBy($queryParamsDTO->sort_by, $queryParamsDTO->sort_direction ?? 'asc');
}
$query->orderBy(
$this->validateSortColumn($queryParamsDTO->sort_by, ProductCategoryDomainObject::class),
$this->validateSortDirection($queryParamsDTO->sort_direction, ProductCategoryDomainObject::class),
);

return $query->get();
}
Expand Down
4 changes: 2 additions & 2 deletions backend/app/Repository/Eloquent/ProductRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ public function findByEventId(int $eventId, QueryParamsDTO $params): LengthAware
}

$this->model = $this->model->orderBy(
$params->sort_by ?? ProductDomainObject::getDefaultSort(),
$params->sort_direction ?? ProductDomainObject::getDefaultSortDirection(),
$this->validateSortColumn($params->sort_by, ProductDomainObject::class),
$this->validateSortDirection($params->sort_direction, ProductDomainObject::class),
);

return $this->paginateWhere(
Expand Down
4 changes: 2 additions & 2 deletions backend/app/Repository/Eloquent/PromoCodeRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ public function findByEventId(int $eventId, QueryParamsDTO $params): LengthAware
}

$this->model = $this->model->orderBy(
column: $params->sort_by ?? PromoCodeDomainObject::getDefaultSort(),
direction: $params->sort_direction ?? 'desc',
column: $this->validateSortColumn($params->sort_by, PromoCodeDomainObject::class),
direction: $this->validateSortDirection($params->sort_direction, PromoCodeDomainObject::class),
);

return $this->paginateWhere(
Expand Down
4 changes: 2 additions & 2 deletions backend/app/Repository/Eloquent/WaitlistEntryRepository.php
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,8 @@ public function findByEventId(int $eventId, QueryParamsDTO $params): LengthAware
}

$this->model = $this->model->orderBy(
column: $params->sort_by ?? WaitlistEntryDomainObject::getDefaultSort(),
direction: $params->sort_direction ?? WaitlistEntryDomainObject::getDefaultSortDirection(),
column: $this->validateSortColumn($params->sort_by, WaitlistEntryDomainObject::class),
direction: $this->validateSortDirection($params->sort_direction, WaitlistEntryDomainObject::class),
);

return $this->loadRelation(new Relationship(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ private function clonePerOrderQuestions(EventDomainObject $event, int $newEventI
$this->createQuestionService->createQuestion(
(new QuestionDomainObject())
->setTitle($question->getTitle())
->setDescription($question->getDescription())
->setEventId($newEventId)
->setBelongsTo($question->getBelongsTo())
->setType($question->getType())
Expand Down
20 changes: 19 additions & 1 deletion backend/app/Validators/Rules/NoInternalUrlRule.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Closure;
use Illuminate\Contracts\Validation\ValidationRule;
use Illuminate\Support\Facades\Config;

class NoInternalUrlRule implements ValidationRule
{
Expand Down Expand Up @@ -52,6 +53,11 @@ public function validate(string $attribute, mixed $value, Closure $fail): void
$host = substr($host, 1, -1);
}

// Handle NoInternalIP/Host Exceptions
if ($this->isWhitelistedHost($host)) {
return;
}

if ($this->isBlockedHost($host)) {
$fail(__('The :attribute cannot point to localhost or internal addresses.'));
return;
Expand Down Expand Up @@ -145,4 +151,16 @@ private function resolveAndNormalize(string $host): string|false

return $ip;
}
}

private function isWhitelistedHost(string $host): bool
{
$whitelistedHosts = Config::string('app.allowed_internal_webhook_hosts');
if (!empty($whitelistedHosts)) {
$allowedList = array_filter(array_map('trim', explode(',', $whitelistedHosts)));
if (in_array($host, $allowedList) || in_array(gethostbyname($host), $allowedList)) {
return true;
}
}
return false;
}
}
2 changes: 1 addition & 1 deletion backend/composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "hi.events - Ticket selling and event management.",
"keywords": ["ticketing", "events"],
"license": "AGPL-3.0",
"version": "1.7.0-beta",
"version": "v1.7.1-beta",
"require": {
"php": "^8.2",
"ext-intl": "*",
Expand Down
1 change: 1 addition & 0 deletions backend/config/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
'stripe_connect_account_type' => env('APP_STRIPE_CONNECT_ACCOUNT_TYPE', 'express'),
'platform_support_email' => env('APP_PLATFORM_SUPPORT_EMAIL', 'support@example.com'),
'enforce_email_confirmation_during_registration' => env('APP_ENFORCE_EMAIL_CONFIRMATION_DURING_REGISTRATION', false),
'allowed_internal_webhook_hosts' => env('APP_ALLOWED_INTERNAL_WEBHOOK_HOSTS', ''),

/**
* The number of page views to batch before updating the database
Expand Down
2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "hievents-frontend",
"private": true,
"version": "1.7.0-beta",
"version": "v1.7.1-beta",
"type": "module",
"scripts": {
"dev:csr": "vite --port 5678 --host 0.0.0.0",
Expand Down
Loading