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
4 changes: 2 additions & 2 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@
// Appointments
['name' => 'appointment#index', 'url' => '/appointments/{userId}', 'verb' => 'GET'],
['name' => 'appointment#show', 'url' => '/appointment/{token}', 'verb' => 'GET'],
['name' => 'booking#getBookableSlots', 'url' => '/appointment/{appointmentConfigId}/slots', 'verb' => 'GET'],
['name' => 'booking#bookSlot', 'url' => '/appointment/{appointmentConfigId}/book', 'verb' => 'POST'],
['name' => 'booking#getBookableSlots', 'url' => '/appointment/{appointmentConfigToken}/slots', 'verb' => 'GET'],
['name' => 'booking#bookSlot', 'url' => '/appointment/{appointmentConfigToken}/book', 'verb' => 'POST'],
['name' => 'booking#confirmBooking', 'url' => '/appointment/confirm/{token}', 'verb' => 'GET'],
// Public views
['name' => 'publicView#public_index_with_branding', 'url' => '/p/{token}', 'verb' => 'GET'],
Expand Down
18 changes: 9 additions & 9 deletions lib/Controller/BookingController.php
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,14 @@ public function __construct(string $appName,
* @NoAdminRequired
* @PublicPage
*
* @param int $appointmentConfigId
* @param string $appointmentConfigToken
* @param int $startTime UNIX time stamp for the start time in UTC
* @param string $timeZone
*
* @return JsonResponse
*/
public function getBookableSlots(
int $appointmentConfigId,
string $appointmentConfigToken,
string $dateSelected,
string $timeZone,
): JsonResponse {
Expand Down Expand Up @@ -120,9 +120,9 @@ public function getBookableSlots(
}

try {
$config = $this->appointmentConfigService->findById($appointmentConfigId);
$config = $this->appointmentConfigService->findByToken($appointmentConfigToken);
} catch (ServiceException $e) {
$this->logger->error('No appointment config found for id ' . $appointmentConfigId, ['exception' => $e]);
$this->logger->error('No appointment config found for ' . $appointmentConfigToken, ['exception' => $e]);
return JsonResponse::fail(null, Http::STATUS_NOT_FOUND);
}

Expand All @@ -135,7 +135,7 @@ public function getBookableSlots(
* @NoAdminRequired
* @PublicPage
*
* @param int $appointmentConfigId
* @param string $appointmentConfigToken
* @param int $start
* @param int $end
* @param string $displayName
Expand All @@ -149,7 +149,7 @@ public function getBookableSlots(
*/
#[AnonRateLimit(limit: 10, period: 1200)]
#[UserRateLimit(limit: 10, period: 300)]
public function bookSlot(int $appointmentConfigId,
public function bookSlot(string $appointmentConfigToken,
int $start,
int $end,
string $displayName,
Expand All @@ -165,15 +165,15 @@ public function bookSlot(int $appointmentConfigId,
}

try {
$config = $this->appointmentConfigService->findById($appointmentConfigId);
$config = $this->appointmentConfigService->findByToken($appointmentConfigToken);
} catch (ServiceException $e) {
$this->logger->error('No appointment config found for id ' . $appointmentConfigId, ['exception' => $e]);
$this->logger->error('No appointment config found for token ' . $appointmentConfigToken, ['exception' => $e]);
return JsonResponse::fail(null, Http::STATUS_NOT_FOUND);
}
try {
$booking = $this->bookingService->book($config, $start, $end, $timeZone, $displayName, $email, $description);
} catch (NoSlotFoundException $e) {
$this->logger->warning('No slot available for start: ' . $start . ', end: ' . $end . ', config id: ' . $appointmentConfigId, ['exception' => $e]);
$this->logger->warning('No slot available for start: ' . $start . ', end: ' . $end . ', config token: ' . $appointmentConfigToken, ['exception' => $e]);
return JsonResponse::fail(null, Http::STATUS_NOT_FOUND);
} catch (InvalidArgumentException $e) {
$this->logger->warning($e->getMessage(), ['exception' => $e]);
Expand Down
8 changes: 4 additions & 4 deletions src/services/appointmentService.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ import { generateUrl } from '@nextcloud/router'
* @param timeZone {String} target time zone for the time stamps
*/
export async function findSlots(config, date, timeZone) {
const url = generateUrl('/apps/calendar/appointment/{id}/slots?dateSelected={date}&timeZone={timeZone}', {
id: config.id,
const url = generateUrl('/apps/calendar/appointment/{token}/slots?dateSelected={date}&timeZone={timeZone}', {
token: config.token,
date,
timeZone,
})
Expand All @@ -32,8 +32,8 @@ export async function findSlots(config, date, timeZone) {
* @param timeZone
*/
export async function bookSlot(config, slot, displayName, email, description, timeZone) {
const url = generateUrl('/apps/calendar/appointment/{id}/book', {
id: config.id,
const url = generateUrl('/apps/calendar/appointment/{token}/book', {
token: config.token,
})

const response = await axios.post(url, {
Expand Down
73 changes: 40 additions & 33 deletions tests/php/unit/Controller/BookingControllerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,53 +114,56 @@ public function testGetBookableSlots(): void {

$apptConfg = new AppointmentConfig();
$apptConfg->setId(1);
$apptConfg->setToken('abc123');
$this->time->expects(self::once())
->method('getTime')
->willReturn($currentDate);
$this->apptService->expects(self::once())
->method('findById')
->with(1)
->method('findByToken')
->with($apptConfg->getToken())
->willReturn($apptConfg);
$this->bookingService->expects(self::once())
->method('getAvailableSlots')
->with($apptConfg, $sDT, $eDT);

$this->controller->getBookableSlots($apptConfg->getId(), $selectedDate, $selectedTz);
$this->controller->getBookableSlots($apptConfg->getToken(), $selectedDate, $selectedTz);
}

public function testGetBookableSlotsDatesInPast(): void {
$currentDate = (new DateTime('2024-7-2'))->getTimestamp();
$selectedDate = '2024-7-1';
$apptConfg = new AppointmentConfig();
$apptConfg->setId(1);
$apptConfg->setToken('abc123');
$this->time->expects(self::once())
->method('getTime')
->willReturn($currentDate);
$this->apptService->expects(self::never())
->method('findById')
->with(1);
->method('findByToken')
->with($apptConfg->getToken());
$this->bookingService->expects(self::never())
->method('getAvailableSlots');
$this->logger->expects(self::once())
->method('warning');

$this->controller->getBookableSlots($apptConfg->getId(), $selectedDate, 'Europe/Berlin');
$this->controller->getBookableSlots($apptConfg->getToken(), $selectedDate, 'Europe/Berlin');
}

public function testGetBookableSlotsInvalidTimezone(): void {
$selectedDate = '2024-7-1';
$apptConfg = new AppointmentConfig();
$apptConfg->setId(1);
$apptConfg->setToken('abc123');
$this->time->expects(self::never())
->method('getTime');
$this->apptService->expects(self::never())
->method('findById')
->with(1);
->method('findByToken')
->with($apptConfg->getToken());
$this->bookingService->expects(self::never())
->method('getAvailableSlots');
$this->expectException(Exception::class);

$this->controller->getBookableSlots($apptConfg->getId(), $selectedDate, 'Hook/Neverland');
$this->controller->getBookableSlots($apptConfg->getToken(), $selectedDate, 'Hook/Neverland');
}

public function testGetBookableSlotsTimezoneIdentical(): void {
Expand All @@ -173,18 +176,19 @@ public function testGetBookableSlotsTimezoneIdentical(): void {

$apptConfg = new AppointmentConfig();
$apptConfg->setId(1);
$apptConfg->setToken('abc123');
$this->time->expects(self::once())
->method('getTime')
->willReturn($currentDate);
$this->apptService->expects(self::once())
->method('findById')
->with(1)
->method('findByToken')
->with($apptConfg->getToken())
->willReturn($apptConfg);
$this->bookingService->expects(self::once())
->method('getAvailableSlots')
->with($apptConfg, $sDT, $eDT);

$this->controller->getBookableSlots($apptConfg->getId(), $selectedDate, $selectedTz);
$this->controller->getBookableSlots($apptConfg->getToken(), $selectedDate, $selectedTz);
}

public function testGetBookableSlotsTimezoneMinus10(): void {
Expand All @@ -197,18 +201,19 @@ public function testGetBookableSlotsTimezoneMinus10(): void {

$apptConfg = new AppointmentConfig();
$apptConfg->setId(1);
$apptConfg->setToken('abc123');
$this->time->expects(self::once())
->method('getTime')
->willReturn($currentDate);
$this->apptService->expects(self::once())
->method('findById')
->with(1)
->method('findByToken')
->with($apptConfg->getToken())
->willReturn($apptConfg);
$this->bookingService->expects(self::once())
->method('getAvailableSlots')
->with($apptConfg, $sDT, $eDT);

$this->controller->getBookableSlots($apptConfg->getId(), $selectedDate, $timezone);
$this->controller->getBookableSlots($apptConfg->getToken(), $selectedDate, $timezone);
}

public function testGetBookableSlotsTimezonePlus10(): void {
Expand All @@ -221,18 +226,19 @@ public function testGetBookableSlotsTimezonePlus10(): void {

$apptConfg = new AppointmentConfig();
$apptConfg->setId(1);
$apptConfg->setToken('abc123');
$this->time->expects(self::once())
->method('getTime')
->willReturn($currentDate);
$this->apptService->expects(self::once())
->method('findById')
->with(1)
->method('findByToken')
->with($apptConfg->getToken())
->willReturn($apptConfg);
$this->bookingService->expects(self::once())
->method('getAvailableSlots')
->with($apptConfg, $sDT, $eDT);

$this->controller->getBookableSlots($apptConfg->getId(), $selectedDate, $timezone);
$this->controller->getBookableSlots($apptConfg->getToken(), $selectedDate, $timezone);
}

public function testGetBookableSlotsTimezonePlus14(): void {
Expand All @@ -245,18 +251,19 @@ public function testGetBookableSlotsTimezonePlus14(): void {

$apptConfg = new AppointmentConfig();
$apptConfg->setId(1);
$apptConfg->setToken('abc123');
$this->time->expects(self::once())
->method('getTime')
->willReturn($currentDate);
$this->apptService->expects(self::once())
->method('findById')
->with(1)
->method('findByToken')
->with($apptConfg->getToken())
->willReturn($apptConfg);
$this->bookingService->expects(self::once())
->method('getAvailableSlots')
->with($apptConfg, $sDT, $eDT);

$this->controller->getBookableSlots($apptConfg->getId(), $selectedDate, $timezone);
$this->controller->getBookableSlots($apptConfg->getToken(), $selectedDate, $timezone);
}

public function testBook(): void {
Expand All @@ -268,14 +275,14 @@ public function testBook(): void {
->with($email)
->willReturn(true);
$this->apptService->expects(self::once())
->method('findById')
->method('findByToken')
->willReturn($config);
$this->bookingService->expects(self::once())
->method('book')
->with($config, 1, 1, 'Hook/Neverland', 'Test', $email, 'Test')
->willReturn(new Booking());

$this->controller->bookSlot(1, 1, 1, 'Test', $email, 'Test', 'Hook/Neverland');
$this->controller->bookSlot('abc123', 1, 1, 'Test', $email, 'Test', 'Hook/Neverland');
}


Expand All @@ -288,14 +295,14 @@ public function testBookInvalidTimeZone(): void {
->with($email)
->willReturn(true);
$this->apptService->expects(self::once())
->method('findById')
->method('findByToken')
->willReturn($config);
$this->bookingService->expects(self::once())
->method('book')
->with($config, 1, 1, 'Hook/Neverland', 'Test', $email, 'Test')
->willThrowException(new InvalidArgumentException());

$this->controller->bookSlot(1, 1, 1, 'Test', $email, 'Test', 'Hook/Neverland');
$this->controller->bookSlot('abc123', 1, 1, 'Test', $email, 'Test', 'Hook/Neverland');
}

public function testBookInvalidSlot(): void {
Expand All @@ -307,14 +314,14 @@ public function testBookInvalidSlot(): void {
->with($email)
->willReturn(true);
$this->apptService->expects(self::once())
->method('findById')
->method('findByToken')
->willReturn($config);
$this->bookingService->expects(self::once())
->method('book')
->with($config, 1, 1, 'Europe/Berlin', 'Test', $email, 'Test')
->willThrowException(new NoSlotFoundException());

$this->controller->bookSlot(1, 1, 1, 'Test', $email, 'Test', 'Europe/Berlin');
$this->controller->bookSlot('abc123', 1, 1, 'Test', $email, 'Test', 'Europe/Berlin');
}

public function testBookInvalidBooking(): void {
Expand All @@ -326,7 +333,7 @@ public function testBookInvalidBooking(): void {
->with($email)
->willReturn(true);
$this->apptService->expects(self::once())
->method('findById')
->method('findByToken')
->willReturn($config);
$this->bookingService->expects(self::once())
->method('book')
Expand All @@ -337,7 +344,7 @@ public function testBookInvalidBooking(): void {
->with('debug')
->willReturn(false);

$this->controller->bookSlot(1, 1, 1, 'Test', $email, 'Test', 'Europe/Berlin');
$this->controller->bookSlot('abc123', 1, 1, 'Test', $email, 'Test', 'Europe/Berlin');
}

public function testBookInvalidId(): void {
Expand All @@ -347,12 +354,12 @@ public function testBookInvalidId(): void {
->with($email)
->willReturn(true);
$this->apptService->expects(self::once())
->method('findById')
->method('findByToken')
->willThrowException(new ServiceException());
$this->bookingService->expects(self::never())
->method('book');

$this->controller->bookSlot(1, 1, 1, 'Test', $email, 'Test', 'Europe/Berlin');
$this->controller->bookSlot('abc123', 1, 1, 'Test', $email, 'Test', 'Europe/Berlin');
}


Expand All @@ -364,10 +371,10 @@ public function testBookInvalidEmail(): void {
->with($email)
->willReturn(false);
$this->apptService->expects(self::never())
->method('findById');
->method('findByToken');
$this->bookingService->expects(self::never())
->method('book');

$this->controller->bookSlot(1, 1, 1, 'Test', $email, 'Test', 'Europe/Berlin');
$this->controller->bookSlot('abc123', 1, 1, 'Test', $email, 'Test', 'Europe/Berlin');
}
}
Loading