diff --git a/appinfo/routes.php b/appinfo/routes.php index 4225f18e..675b6623 100644 --- a/appinfo/routes.php +++ b/appinfo/routes.php @@ -17,6 +17,7 @@ ['name' => 'Endpoint#deleteAllNotifications', 'url' => '/api/{apiVersion}/notifications', 'verb' => 'DELETE', 'requirements' => ['apiVersion' => '(v1|v2)']], ['name' => 'API#generateNotification', 'url' => '/api/{apiVersion}/admin_notifications/{userId}', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v1|v2)']], + ['name' => 'API#generateNotificationV3', 'url' => '/api/{apiVersion}/admin_notifications/{userId}', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v3)']], ['name' => 'Settings#personal', 'url' => '/api/{apiVersion}/settings', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], ['name' => 'Settings#admin', 'url' => '/api/{apiVersion}/settings/admin', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v2)']], diff --git a/lib/Controller/APIController.php b/lib/Controller/APIController.php index 21b1bb07..ec1d8ffa 100644 --- a/lib/Controller/APIController.php +++ b/lib/Controller/APIController.php @@ -9,6 +9,7 @@ namespace OCA\Notifications\Controller; +use OCA\Notifications\App; use OCP\AppFramework\Http; use OCP\AppFramework\Http\Attribute\OpenAPI; use OCP\AppFramework\Http\DataResponse; @@ -19,8 +20,9 @@ use OCP\IUserManager; use OCP\Notification\IManager; use OCP\Notification\InvalidValueException; -use OCP\RichObjectStrings\IValidator; use OCP\RichObjectStrings\InvalidObjectExeption; +use OCP\RichObjectStrings\IValidator; +use Psr\Log\LoggerInterface; class APIController extends OCSController { public function __construct( @@ -29,60 +31,88 @@ public function __construct( protected ITimeFactory $timeFactory, protected IUserManager $userManager, protected IManager $notificationManager, + protected App $notificationApp, protected IValidator $richValidator, + protected LoggerInterface $logger, ) { parent::__construct($appName, $request); } /** - * Generate a notification for a user + * Generate a notification for a user (deprecated, use v3 instead) * * @param string $userId ID of the user * @param string $shortMessage Subject of the notification * @param string $longMessage Message of the notification - * @param string $richSubject Subject of the notification with placeholders - * @param string $richSubjectParameters Rich objects to fill the subject placeholders, {@see \OCP\RichObjectStrings\Definitions} - * @param string $richMessage Message of the notification with placeholders - * @param string $richMessageParameters Rich objects to fill the message placeholders, {@see \OCP\RichObjectStrings\Definitions} * @return DataResponse, array{}>|DataResponse + * @deprecated 30.0.0 * * 200: Notification generated successfully * 400: Generating notification is not possible * 404: User not found */ #[OpenAPI(scope: OpenAPI::SCOPE_ADMINISTRATION)] - public function generateNotification( + public function generateNotification(string $userId, string $shortMessage, string $longMessage = ''): DataResponse { + $response = $this->generateNotificationV3($userId, $shortMessage, $longMessage); + if ($response->getStatus() === Http::STATUS_OK) { + return new DataResponse(); + } + + // Translate to old status code + $error = $response->getData()['error'] ?? null; + $code = match($error) { + 'user' => Http::STATUS_NOT_FOUND, + 'subject', + 'message' => Http::STATUS_BAD_REQUEST, + default => Http::STATUS_INTERNAL_SERVER_ERROR, + }; + return new DataResponse(null, $code); + } + + /** + * Generate a notification with rich object parameters for a user + * + * @param string $userId ID of the user + * @param string $subject Subject of the notification + * @param string $message Message of the notification + * @param array $subjectParameters Rich objects to fill the subject placeholders, {@see \OCP\RichObjectStrings\Definitions} + * @param array $messageParameters Rich objects to fill the message placeholders, {@see \OCP\RichObjectStrings\Definitions} + * @return DataResponse>|DataResponse> + * + * 200: Notification generated successfully, returned id is the notification ID for future delete requests + * 400: Provided data was invalid, check error field of the response of log file for details + */ + #[OpenAPI(scope: OpenAPI::SCOPE_ADMINISTRATION)] + public function generateNotificationV3( string $userId, - string $shortMessage = '', - string $longMessage = '', - string $richSubject = '', - array $richSubjectParameters = [], - string $richMessage = '', - array $richMessageParameters = [], + string $subject = '', + string $message = '', + array $subjectParameters = [], + array $messageParameters = [], ): DataResponse { $user = $this->userManager->get($userId); if (!$user instanceof IUser) { - return new DataResponse(null, Http::STATUS_NOT_FOUND); + return new DataResponse(['error' => 'user'], Http::STATUS_BAD_REQUEST); } - if (($shortMessage === '' && $richSubject === '') || strlen($shortMessage) > 255) { - return new DataResponse(null, Http::STATUS_BAD_REQUEST); + if ($subject === '' || strlen($subject) > 255) { + return new DataResponse(['error' => 'subject'], Http::STATUS_BAD_REQUEST); } - if ($longMessage !== '' && strlen($longMessage) > 4000) { - return new DataResponse(null, Http::STATUS_BAD_REQUEST); + if ($message !== '' && strlen($message) > 4000) { + return new DataResponse(['error' => 'message'], Http::STATUS_BAD_REQUEST); } $notification = $this->notificationManager->createNotification(); $datetime = $this->timeFactory->getDateTime(); try { - if ($richSubject !== '') { - $this->richValidator->validate($richSubject, $richSubjectParameters); + if (!empty($subjectParameters)) { + $this->richValidator->validate($subject, $subjectParameters); } - if ($richMessage !== '') { - $this->richValidator->validate($richMessage, $richMessageParameters); + if ($message !== '' && !empty($messageParameters)) { + $this->richValidator->validate($message, $messageParameters); } $notification->setApp('admin_notifications') ->setUser($user->getUID()) @@ -91,32 +121,30 @@ public function generateNotification( ->setSubject( 'ocs', [ - 'parsed' => $shortMessage, - 'rich' => $richSubject, - 'parameters' => $richSubjectParameters, + 'subject' => $subject, + 'parameters' => $subjectParameters, ] ); - if ($longMessage !== '' || $richMessage !== '') { + if ($message !== '') { $notification->setMessage( 'ocs', [ - 'parsed' => $longMessage, - 'rich' => $richMessage, - 'parameters' => $richMessageParameters, + 'message' => $message, + 'parameters' => $messageParameters, ] ); } $this->notificationManager->notify($notification); } catch (InvalidObjectExeption $e) { - return new DataResponse('Invalid rich object: '.$e->getMessage(), Http::STATUS_BAD_REQUEST); + $this->logger->error('Invalid rich object parameter provided: ' . $e->getMessage(), ['exception' => $e]); + return new DataResponse(['error' => 'parameters'], Http::STATUS_BAD_REQUEST); } catch (InvalidValueException $e) { - return new DataResponse($e->getMessage(), Http::STATUS_BAD_REQUEST); - } catch (\InvalidArgumentException) { - return new DataResponse(null, Http::STATUS_INTERNAL_SERVER_ERROR); + $this->logger->error('Invalid value for notification provided: ' . $e->getMessage(), ['exception' => $e]); + return new DataResponse(['error' => $e->getMessage()], Http::STATUS_BAD_REQUEST); } - return new DataResponse(); + return new DataResponse(['id' => (int) $this->notificationApp->getLastInsertedId()]); } }