Skip to content

Commit

Permalink
feat(push): Add option to send a self-test
Browse files Browse the repository at this point in the history
Signed-off-by: Joas Schilling <coding@schilljs.com>
  • Loading branch information
nickvergessen committed Nov 29, 2024
1 parent 69665d9 commit 428e2a2
Show file tree
Hide file tree
Showing 4 changed files with 307 additions and 0 deletions.
1 change: 1 addition & 0 deletions appinfo/routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

['name' => 'API#generateNotification', 'url' => '/api/{apiVersion}/admin_notifications/{userId}', 'verb' => 'POST', 'requirements' => ['apiVersion' => '(v1|v2)']],
['name' => 'API#generateNotificationV3', 'url' => '/api/{apiVersion3}/admin_notifications/{userId}', 'verb' => 'POST', 'requirements' => ['apiVersion3' => '(v3)']],
['name' => 'API#selfTestPush', 'url' => '/api/{apiVersion3}/test/self', 'verb' => 'POST', 'requirements' => ['apiVersion3' => '(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)']],
Expand Down
74 changes: 74 additions & 0 deletions lib/Controller/APIController.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,23 @@
use OCA\Notifications\App;
use OCA\Notifications\ResponseDefinitions;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\Attribute\NoAdminRequired;
use OCP\AppFramework\Http\Attribute\OpenAPI;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCSController;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IL10N;
use OCP\IRequest;
use OCP\IUser;
use OCP\IUserManager;
use OCP\IUserSession;
use OCP\Notification\IManager;
use OCP\Notification\IncompleteNotificationException;
use OCP\Notification\InvalidValueException;
use OCP\RichObjectStrings\InvalidObjectExeption;
use OCP\RichObjectStrings\IValidator;
use Psr\Log\LoggerInterface;
use Symfony\Component\Console\Output\BufferedOutput;

/**
* @psalm-import-type NotificationsRichObjectParameter from ResponseDefinitions
Expand All @@ -36,9 +40,11 @@ public function __construct(
IRequest $request,
protected ITimeFactory $timeFactory,
protected IUserManager $userManager,
protected IUserSession $userSession,
protected IManager $notificationManager,
protected App $notificationApp,
protected IValidator $richValidator,
protected IL10N $l,
protected LoggerInterface $logger,
) {
parent::__construct($appName, $request);
Expand Down Expand Up @@ -153,4 +159,72 @@ public function generateNotificationV3(

return new DataResponse(['id' => (int)$this->notificationApp->getLastInsertedId()]);
}

/**
* Send a test notification to push registered mobile apps
*
* @return DataResponse<Http::STATUS_OK|Http::STATUS_BAD_REQUEST, array{message: string}, array{}>
*
* 200: Test notification generated successfully, but the device should still show the message to the user
* 400: Test notification could not be generated, show the message to the user
*/
#[NoAdminRequired]
#[OpenAPI(scope: 'push')]
public function selfTestPush(): DataResponse {
if (!$this->notificationManager->isFairUseOfFreePushService()) {
$message = $this->l->t('We want to keep offering our push notification service for free, but large users overload our infrastructure. For this reason we have to rate-limit the use of push notifications. If you need this feature, consider using Nextcloud Enterprise.');
return new DataResponse(
['message' => $message],
Http::STATUS_BAD_REQUEST,
);
}

$user = $this->userSession->getUser();
if (!$user instanceof IUser) {
return new DataResponse(
['message' => $this->l->t('User not found')],
Http::STATUS_BAD_REQUEST,
);
}

if (!$this->request->isUserAgent([
IRequest::USER_AGENT_TALK_ANDROID,
IRequest::USER_AGENT_TALK_IOS,
IRequest::USER_AGENT_CLIENT_ANDROID,
IRequest::USER_AGENT_CLIENT_IOS,
])) {
return new DataResponse(
['message' => $this->l->t('The device does not seem to be supported')],
Http::STATUS_BAD_REQUEST,
);
}

$notification = $this->notificationManager->createNotification();
$datetime = $this->timeFactory->getDateTime();
$isTalkApp = $this->request->isUserAgent([
IRequest::USER_AGENT_TALK_ANDROID,
IRequest::USER_AGENT_TALK_IOS,
]);
$app = $isTalkApp ? 'admin_notification_talk' : 'admin_notifications';

$output = new BufferedOutput();
try {
$notification->setApp($app)
->setUser($user->getUID())
->setDateTime($datetime)
->setObject('admin_notifications', dechex($datetime->getTimestamp()))
->setSubject('self', ['Testing push notifications']);

$this->notificationApp->setOutput($output);
$this->notificationManager->notify($notification);
} catch (\InvalidArgumentException $e) {
$this->logger->error('Self testing push notification failed: ' . $e->getMessage(), ['exception' => $e]);
return new DataResponse(
['message' => $this->l->t('An unexpected error occurred, ask your administration to check the logs.')],
Http::STATUS_BAD_REQUEST,
);
}

return new DataResponse(['message' => $output->fetch()]);
}
}
116 changes: 116 additions & 0 deletions openapi-full.json
Original file line number Diff line number Diff line change
Expand Up @@ -1453,6 +1453,122 @@
}
}
},
"/ocs/v2.php/apps/notifications/api/{apiVersion3}/test/self": {
"post": {
"operationId": "api-self-test-push",
"summary": "Send a test notification to push registered mobile apps",
"tags": [
"api"
],
"security": [
{
"bearer_auth": []
},
{
"basic_auth": []
}
],
"parameters": [
{
"name": "apiVersion3",
"in": "path",
"required": true,
"schema": {
"type": "string",
"pattern": "^(v3)$"
}
},
{
"name": "OCS-APIRequest",
"in": "header",
"description": "Required to be true for the API request to pass",
"required": true,
"schema": {
"type": "boolean",
"default": true
}
}
],
"responses": {
"200": {
"description": "Test notification generated successfully, but the device should still show the message to the user",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
}
}
}
}
}
}
}
}
}
},
"400": {
"description": "Test notification could not be generated, show the message to the user",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
}
}
}
}
}
}
}
}
}
}
}
}
},
"/ocs/v2.php/apps/notifications/api/{apiVersion}/push": {
"post": {
"operationId": "push-register-device",
Expand Down
116 changes: 116 additions & 0 deletions openapi-push.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,122 @@
}
},
"paths": {
"/ocs/v2.php/apps/notifications/api/{apiVersion3}/test/self": {
"post": {
"operationId": "api-self-test-push",
"summary": "Send a test notification to push registered mobile apps",
"tags": [
"api"
],
"security": [
{
"bearer_auth": []
},
{
"basic_auth": []
}
],
"parameters": [
{
"name": "apiVersion3",
"in": "path",
"required": true,
"schema": {
"type": "string",
"pattern": "^(v3)$"
}
},
{
"name": "OCS-APIRequest",
"in": "header",
"description": "Required to be true for the API request to pass",
"required": true,
"schema": {
"type": "boolean",
"default": true
}
}
],
"responses": {
"200": {
"description": "Test notification generated successfully, but the device should still show the message to the user",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
}
}
}
}
}
}
}
}
}
},
"400": {
"description": "Test notification could not be generated, show the message to the user",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": [
"ocs"
],
"properties": {
"ocs": {
"type": "object",
"required": [
"meta",
"data"
],
"properties": {
"meta": {
"$ref": "#/components/schemas/OCSMeta"
},
"data": {
"type": "object",
"required": [
"message"
],
"properties": {
"message": {
"type": "string"
}
}
}
}
}
}
}
}
}
}
}
}
},
"/ocs/v2.php/apps/notifications/api/{apiVersion}/push": {
"post": {
"operationId": "push-register-device",
Expand Down

0 comments on commit 428e2a2

Please sign in to comment.