migrate therinaldos.com data
Build & Deploy to DigitalOcean Space / build (push) Failing after 2m38s

This commit is contained in:
2024-05-05 15:50:45 -04:00
commit ef1ff240d4
23182 changed files with 3801898 additions and 0 deletions
@@ -0,0 +1,110 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2017, Joas Schilling <coding@schilljs.com>
*
* @author Joas Schilling <coding@schilljs.com>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Notifications\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCSController;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IRequest;
use OCP\IUser;
use OCP\IUserManager;
use OCP\Notification\IManager;
class APIController extends OCSController {
/** @var ITimeFactory */
protected $timeFactory;
/** @var IUserManager */
protected $userManager;
/** @var IManager */
protected $notificationManager;
public function __construct(
string $appName,
IRequest $request,
ITimeFactory $timeFactory,
IUserManager $userManager,
IManager $notificationManager,
) {
parent::__construct($appName, $request);
$this->timeFactory = $timeFactory;
$this->userManager = $userManager;
$this->notificationManager = $notificationManager;
}
/**
* Generate a notification for a user
*
* @param string $userId ID of the user
* @param string $shortMessage Subject of the notification
* @param string $longMessage Message of the notification
* @return DataResponse<Http::STATUS_OK, array<empty>, array{}>|DataResponse<Http::STATUS_BAD_REQUEST|Http::STATUS_NOT_FOUND|Http::STATUS_INTERNAL_SERVER_ERROR, null, array{}>
*
* 200: Notification generated successfully
* 400: Generating notification is not possible
* 404: User not found
*/
public function generateNotification(string $userId, string $shortMessage, string $longMessage = ''): DataResponse {
$user = $this->userManager->get($userId);
if (!$user instanceof IUser) {
return new DataResponse(null, Http::STATUS_NOT_FOUND);
}
if ($shortMessage === '' || strlen($shortMessage) > 255) {
return new DataResponse(null, Http::STATUS_BAD_REQUEST);
}
if ($longMessage !== '' && strlen($longMessage) > 4000) {
return new DataResponse(null, Http::STATUS_BAD_REQUEST);
}
$notification = $this->notificationManager->createNotification();
$datetime = $this->timeFactory->getDateTime();
try {
$notification->setApp('admin_notifications')
->setUser($user->getUID())
->setDateTime($datetime)
->setObject('admin_notifications', dechex($datetime->getTimestamp()))
->setSubject('ocs', [$shortMessage]);
if ($longMessage !== '') {
$notification->setMessage('ocs', [$longMessage]);
}
$this->notificationManager->notify($notification);
} catch (\InvalidArgumentException) {
return new DataResponse(null, Http::STATUS_INTERNAL_SERVER_ERROR);
}
return new DataResponse();
}
}
@@ -0,0 +1,365 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2023, Joas Schilling <coding@schilljs.com>
* @copyright Copyright (c) 2016, ownCloud, Inc.
*
* @author Joas Schilling <coding@schilljs.com>
*
* @license AGPL-3.0
*
* This code is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License, version 3,
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
*/
namespace OCA\Notifications\Controller;
use OCA\Notifications\Exceptions\NotificationNotFoundException;
use OCA\Notifications\Handler;
use OCA\Notifications\Push;
use OCA\Notifications\ResponseDefinitions;
use OCA\Notifications\Service\ClientService;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCSController;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\IRequest;
use OCP\IUser;
use OCP\IUserSession;
use OCP\L10N\IFactory;
use OCP\Notification\IAction;
use OCP\Notification\IManager;
use OCP\Notification\INotification;
use OCP\UserStatus\IManager as IUserStatusManager;
use OCP\UserStatus\IUserStatus;
/**
* @psalm-import-type NotificationsNotification from ResponseDefinitions
* @psalm-import-type NotificationsNotificationAction from ResponseDefinitions
*/
class EndpointController extends OCSController {
public function __construct(
string $appName,
IRequest $request,
protected Handler $handler,
protected IManager $manager,
protected IFactory $l10nFactory,
protected IUserSession $session,
protected ITimeFactory $timeFactory,
protected IUserStatusManager $userStatusManager,
protected ClientService $clientService,
protected Push $push,
) {
parent::__construct($appName, $request);
}
/**
* @NoAdminRequired
* @NoCSRFRequired
*
* Get all notifications
*
* @param string $apiVersion Version of the API to use
* @return DataResponse<Http::STATUS_OK, NotificationsNotification[], array{'X-Nextcloud-User-Status': string}>|DataResponse<Http::STATUS_NO_CONTENT, null, array{X-Nextcloud-User-Status: string}>
*
* 200: Notifications returned
* 204: No app uses notifications
*/
public function listNotifications(string $apiVersion): DataResponse {
$userStatus = $this->userStatusManager->getUserStatuses([
$this->getCurrentUser(),
]);
$headers = ['X-Nextcloud-User-Status' => IUserStatus::ONLINE];
if (isset($userStatus[$this->getCurrentUser()])) {
$userStatus = $userStatus[$this->getCurrentUser()];
$headers['X-Nextcloud-User-Status'] = $userStatus->getStatus();
}
// When there are no apps registered that use the notifications
// We stop polling for them.
if (!$this->manager->hasNotifiers()) {
return new DataResponse(null, Http::STATUS_NO_CONTENT, $headers);
}
$user = $this->session->getUser();
$filter = $this->manager->createNotification();
$filter->setUser($this->getCurrentUser());
$language = $this->l10nFactory->getUserLanguage($user);
$notifications = $this->handler->get($filter);
$shouldFlush = $this->manager->defer();
$hasActiveTalkDesktop = false;
if ($user instanceof IUser) {
$hasActiveTalkDesktop = $this->clientService->hasTalkDesktop(
$user->getUID(),
$this->timeFactory->getTime() - ClientService::DESKTOP_CLIENT_TIMEOUT
);
}
$data = [];
$notificationIds = [];
foreach ($notifications as $notificationId => $notification) {
/** @var INotification $notification */
try {
$notification = $this->manager->prepare($notification, $language);
} catch (\InvalidArgumentException) {
// The app was disabled, skip the notification
continue;
}
$notificationIds[] = $notificationId;
$data[] = $this->notificationToArray($notificationId, $notification, $apiVersion, $hasActiveTalkDesktop);
}
if ($shouldFlush) {
$this->manager->flush();
}
$eTag = $this->generateETag($notificationIds);
$response = new DataResponse($data, Http::STATUS_OK, $headers);
if ($apiVersion !== 'v1') {
$response->setETag($eTag);
}
return $response;
}
/**
* @NoAdminRequired
* @NoCSRFRequired
*
* Get a notification
*
* @param string $apiVersion Version of the API to use
* @param int $id ID of the notification
* @return DataResponse<Http::STATUS_OK, NotificationsNotification, array{}>|DataResponse<Http::STATUS_NOT_FOUND, null, array{}>
*
* 200: Notification returned
* 404: Notification not found
*/
public function getNotification(string $apiVersion, int $id): DataResponse {
if (!$this->manager->hasNotifiers()) {
return new DataResponse(null, Http::STATUS_NOT_FOUND);
}
if ($id === 0) {
return new DataResponse(null, Http::STATUS_NOT_FOUND);
}
try {
$notification = $this->handler->getById($id, $this->getCurrentUser());
} catch (NotificationNotFoundException $e) {
return new DataResponse(null, Http::STATUS_NOT_FOUND);
}
$user = $this->session->getUser();
$language = $this->l10nFactory->getUserLanguage($user);
try {
$notification = $this->manager->prepare($notification, $language);
} catch (\InvalidArgumentException $e) {
// The app was disabled
return new DataResponse(null, Http::STATUS_NOT_FOUND);
}
$hasActiveTalkDesktop = false;
if ($user instanceof IUser) {
$hasActiveTalkDesktop = $this->clientService->hasTalkDesktop(
$user->getUID(),
$this->timeFactory->getTime() - ClientService::DESKTOP_CLIENT_TIMEOUT
);
}
return new DataResponse($this->notificationToArray($id, $notification, $apiVersion, $hasActiveTalkDesktop));
}
/**
* @NoAdminRequired
*
* Check if notification IDs exist
*
* @param string $apiVersion Version of the API to use
* @param int[] $ids IDs of the notifications to check
* @return DataResponse<Http::STATUS_OK|Http::STATUS_BAD_REQUEST, int[], array{}>
*
* 200: Existing notification IDs returned
* 400: Too many notification IDs requested
*/
public function confirmIdsForUser(string $apiVersion, array $ids): DataResponse {
if (!$this->manager->hasNotifiers()) {
return new DataResponse([], Http::STATUS_OK);
}
if (empty($ids)) {
return new DataResponse([], Http::STATUS_OK);
}
if (count($ids) > 200) {
return new DataResponse([], Http::STATUS_BAD_REQUEST);
}
$ids = array_unique(array_filter(array_map(
static fn ($id) => is_numeric($id) ? (int) $id : 0,
$ids
)));
$existingIds = $this->handler->confirmIdsForUser($this->getCurrentUser(), $ids);
return new DataResponse($existingIds, Http::STATUS_OK);
}
/**
* @NoAdminRequired
*
* Delete a notification
*
* @param int $id ID of the notification
* @return DataResponse<Http::STATUS_OK, array<empty>, array{}>|DataResponse<Http::STATUS_FORBIDDEN|Http::STATUS_NOT_FOUND, null, array{}>
*
* 200: Notification deleted successfully
* 403: Deleting notification for impersonated user is not allowed
* 404: Notification not found
*/
public function deleteNotification(int $id): DataResponse {
if ($id === 0) {
return new DataResponse(null, Http::STATUS_NOT_FOUND);
}
if ($this->session->getImpersonatingUserID() !== null) {
return new DataResponse(null, Http::STATUS_FORBIDDEN);
}
try {
$notification = $this->handler->getById($id, $this->getCurrentUser());
$deleted = $this->handler->deleteById($id, $this->getCurrentUser(), $notification);
if ($deleted) {
$this->push->pushDeleteToDevice($this->getCurrentUser(), [$id], $notification->getApp());
}
} catch (NotificationNotFoundException $e) {
}
return new DataResponse();
}
/**
* @NoAdminRequired
*
* Delete all notifications
*
* @return DataResponse<Http::STATUS_OK, array<empty>, array{}>|DataResponse<Http::STATUS_FORBIDDEN, null, array{}>
*
* 200: All notifications deleted successfully
* 403: Deleting notification for impersonated user is not allowed
*/
public function deleteAllNotifications(): DataResponse {
if ($this->session->getImpersonatingUserID() !== null) {
return new DataResponse(null, Http::STATUS_FORBIDDEN);
}
$shouldFlush = $this->manager->defer();
$deletedSomething = $this->handler->deleteByUser($this->getCurrentUser());
if ($deletedSomething) {
$this->push->pushDeleteToDevice($this->getCurrentUser(), null);
}
if ($shouldFlush) {
$this->manager->flush();
}
return new DataResponse();
}
/**
* Get an ETag for the notification ids
*
* @param array $notifications
* @return string
*/
protected function generateETag(array $notifications): string {
return md5(json_encode($notifications));
}
/**
* @param int $notificationId
* @param INotification $notification
* @param string $apiVersion
* @param bool $hasActiveTalkDesktop
* @return NotificationsNotification
*/
protected function notificationToArray(int $notificationId, INotification $notification, string $apiVersion, bool $hasActiveTalkDesktop = false): array {
$data = [
'notification_id' => $notificationId,
'app' => $notification->getApp(),
'user' => $notification->getUser(),
'datetime' => $notification->getDateTime()->format('c'),
'object_type' => $notification->getObjectType(),
'object_id' => $notification->getObjectId(),
'subject' => $notification->getParsedSubject(),
'message' => $notification->getParsedMessage(),
'link' => $notification->getLink(),
];
if ($apiVersion !== 'v1') {
if ($this->request->isUserAgent([IRequest::USER_AGENT_TALK_DESKTOP])) {
$shouldNotify = $notification->getApp() === 'spreed';
} else {
$shouldNotify = !$hasActiveTalkDesktop || $notification->getApp() !== 'spreed';
}
$data = array_merge($data, [
'subjectRich' => $notification->getRichSubject(),
'subjectRichParameters' => $notification->getRichSubjectParameters(),
'messageRich' => $notification->getRichMessage(),
'messageRichParameters' => $notification->getRichMessageParameters(),
'icon' => $notification->getIcon(),
'shouldNotify' => $shouldNotify,
]);
}
$data['actions'] = [];
foreach ($notification->getParsedActions() as $action) {
$data['actions'][] = $this->actionToArray($action);
}
return $data;
}
/**
* @param IAction $action
* @return NotificationsNotificationAction
*/
protected function actionToArray(IAction $action): array {
return [
'label' => $action->getParsedLabel(),
'link' => $action->getLink(),
'type' => $action->getRequestType(),
'primary' => $action->isPrimary(),
];
}
/**
* @return string
*/
protected function getCurrentUser(): string {
$user = $this->session->getUser();
if ($user instanceof IUser) {
$user = $user->getUID();
}
return (string) $user;
}
}
@@ -0,0 +1,305 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2017, Joas Schilling <coding@schilljs.com>
*
* @author Joas Schilling <coding@schilljs.com>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Notifications\Controller;
use OC\Authentication\Exceptions\InvalidTokenException;
use OC\Authentication\Token\IProvider;
use OC\Authentication\Token\IToken;
use OC\Security\IdentityProof\Manager;
use OCA\Notifications\ResponseDefinitions;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCSController;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IDBConnection;
use OCP\IRequest;
use OCP\ISession;
use OCP\IUser;
use OCP\IUserSession;
/**
* @psalm-import-type NotificationsPushDevice from ResponseDefinitions
*/
class PushController extends OCSController {
/** @var IDBConnection */
private $db;
/** @var ISession */
private $session;
/** @var IUserSession */
private $userSession;
/** @var IProvider */
private $tokenProvider;
/** @var Manager */
private $identityProof;
public function __construct(string $appName,
IRequest $request,
IDBConnection $db,
ISession $session,
IUserSession $userSession,
IProvider $tokenProvider,
Manager $identityProof) {
parent::__construct($appName, $request);
$this->db = $db;
$this->session = $session;
$this->userSession = $userSession;
$this->tokenProvider = $tokenProvider;
$this->identityProof = $identityProof;
}
/**
* @NoAdminRequired
*
* Register device for push notifications
*
* @param string $pushTokenHash Hash of the push token
* @param string $devicePublicKey Public key of the device
* @param string $proxyServer Proxy server to be used
* @return DataResponse<Http::STATUS_OK|Http::STATUS_CREATED, NotificationsPushDevice, array{}>|DataResponse<Http::STATUS_BAD_REQUEST, array{message: string}, array{}>|DataResponse<Http::STATUS_UNAUTHORIZED, array<empty>, array{}>
*
* 200: Device was already registered
* 201: Device registered successfully
* 400: Registering device is not possible
* 401: Missing permissions to register device
*/
public function registerDevice(string $pushTokenHash, string $devicePublicKey, string $proxyServer): DataResponse {
$user = $this->userSession->getUser();
if (!$user instanceof IUser) {
return new DataResponse([], Http::STATUS_UNAUTHORIZED);
}
if (!preg_match('/^([a-f0-9]{128})$/', $pushTokenHash)) {
return new DataResponse(['message' => 'INVALID_PUSHTOKEN_HASH'], Http::STATUS_BAD_REQUEST);
}
if (
strpos($devicePublicKey, '-----BEGIN PUBLIC KEY-----' . "\n") !== 0 ||
((\strlen($devicePublicKey) !== 450 || strpos($devicePublicKey, "\n" . '-----END PUBLIC KEY-----') !== 425) &&
(\strlen($devicePublicKey) !== 451 || strpos($devicePublicKey, "\n" . '-----END PUBLIC KEY-----' . "\n") !== 425))
) {
return new DataResponse(['message' => 'INVALID_DEVICE_KEY'], Http::STATUS_BAD_REQUEST);
}
if (
!filter_var($proxyServer, FILTER_VALIDATE_URL) ||
\strlen($proxyServer) > 256 ||
!preg_match('/^(https\:\/\/|http\:\/\/(localhost|[a-z0-9\.-]*\.(internal|local))(\:\d{0,5})?\/)/', $proxyServer)
) {
return new DataResponse(['message' => 'INVALID_PROXY_SERVER'], Http::STATUS_BAD_REQUEST);
}
$tokenId = $this->session->get('token-id');
if (!\is_int($tokenId)) {
return new DataResponse(['message' => 'INVALID_SESSION_TOKEN'], Http::STATUS_BAD_REQUEST);
}
try {
$token = $this->tokenProvider->getTokenById($tokenId);
} catch (InvalidTokenException $e) {
return new DataResponse(['message' => 'INVALID_SESSION_TOKEN'], Http::STATUS_BAD_REQUEST);
}
$key = $this->identityProof->getKey($user);
$deviceIdentifier = json_encode([$user->getCloudId(), $token->getId()]);
openssl_sign($deviceIdentifier, $signature, $key->getPrivate(), OPENSSL_ALGO_SHA512);
/**
* For some reason the push proxy's golang code needs the signature
* of the deviceIdentifier before the sha512 hashing. Assumption is that
* openssl_sign already does the sha512 internally.
*/
$deviceIdentifier = base64_encode(hash('sha512', $deviceIdentifier, true));
$appType = 'unknown';
if ($this->request->isUserAgent([
IRequest::USER_AGENT_TALK_ANDROID,
IRequest::USER_AGENT_TALK_IOS,
])) {
$appType = 'talk';
} elseif ($this->request->isUserAgent([
IRequest::USER_AGENT_CLIENT_ANDROID,
IRequest::USER_AGENT_CLIENT_IOS,
])) {
$appType = 'nextcloud';
}
$created = $this->savePushToken($user, $token, $deviceIdentifier, $devicePublicKey, $pushTokenHash, $proxyServer, $appType);
return new DataResponse([
'publicKey' => $key->getPublic(),
'deviceIdentifier' => $deviceIdentifier,
'signature' => base64_encode($signature),
], $created ? Http::STATUS_CREATED : Http::STATUS_OK);
}
/**
* @NoAdminRequired
*
* Remove a device from push notifications
*
* @return DataResponse<Http::STATUS_OK|Http::STATUS_ACCEPTED|Http::STATUS_UNAUTHORIZED, array<empty>, array{}>|DataResponse<Http::STATUS_BAD_REQUEST, array{message: string}, array{}>
*
* 200: No device registered
* 202: Device removed successfully
* 400: Removing device is not possible
* 401: Missing permissions to remove device
*/
public function removeDevice(): DataResponse {
$user = $this->userSession->getUser();
if (!$user instanceof IUser) {
return new DataResponse([], Http::STATUS_UNAUTHORIZED);
}
$tokenId = (int)$this->session->get('token-id');
try {
$token = $this->tokenProvider->getTokenById($tokenId);
} catch (InvalidTokenException $e) {
return new DataResponse(['message' => 'INVALID_SESSION_TOKEN'], Http::STATUS_BAD_REQUEST);
}
if ($this->deletePushToken($user, $token)) {
return new DataResponse([], Http::STATUS_ACCEPTED);
}
return new DataResponse([], Http::STATUS_OK);
}
/**
* @param IUser $user
* @param IToken $token
* @param string $deviceIdentifier
* @param string $devicePublicKey
* @param string $pushTokenHash
* @param string $proxyServer
* @param string $appType
* @return bool If the hash was new to the database
*/
protected function savePushToken(IUser $user, IToken $token, string $deviceIdentifier, string $devicePublicKey, string $pushTokenHash, string $proxyServer, string $appType): bool {
$query = $this->db->getQueryBuilder();
$query->select('*')
->from('notifications_pushhash')
->where($query->expr()->eq('uid', $query->createNamedParameter($user->getUID())))
->andWhere($query->expr()->eq('token', $query->createNamedParameter($token->getId())));
$result = $query->execute();
$row = $result->fetch();
$result->closeCursor();
if (!$row) {
// In case the auth token is new, delete potentially old entries for the same device (push token) by this user
$this->deletePushTokenByHash($user, $pushTokenHash);
return $this->insertPushToken($user, $token, $deviceIdentifier, $devicePublicKey, $pushTokenHash, $proxyServer, $appType);
}
return $this->updatePushToken($user, $token, $devicePublicKey, $pushTokenHash, $proxyServer, $appType);
}
/**
* @param IUser $user
* @param IToken $token
* @param string $deviceIdentifier
* @param string $devicePublicKey
* @param string $pushTokenHash
* @param string $proxyServer
* @param string $appType
* @return bool If the entry was created
*/
protected function insertPushToken(IUser $user, IToken $token, string $deviceIdentifier, string $devicePublicKey, string $pushTokenHash, string $proxyServer, string $appType): bool {
$devicePublicKeyHash = hash('sha512', $devicePublicKey);
$query = $this->db->getQueryBuilder();
$query->insert('notifications_pushhash')
->values([
'uid' => $query->createNamedParameter($user->getUID()),
'token' => $query->createNamedParameter($token->getId(), IQueryBuilder::PARAM_INT),
'deviceidentifier' => $query->createNamedParameter($deviceIdentifier),
'devicepublickey' => $query->createNamedParameter($devicePublicKey),
'devicepublickeyhash' => $query->createNamedParameter($devicePublicKeyHash),
'pushtokenhash' => $query->createNamedParameter($pushTokenHash),
'proxyserver' => $query->createNamedParameter($proxyServer),
'apptype' => $query->createNamedParameter($appType),
]);
return $query->executeStatement() > 0;
}
/**
* @param IUser $user
* @param IToken $token
* @param string $devicePublicKey
* @param string $pushTokenHash
* @param string $proxyServer
* @param string $appType
* @return bool If the entry was updated
*/
protected function updatePushToken(IUser $user, IToken $token, string $devicePublicKey, string $pushTokenHash, string $proxyServer, string $appType): bool {
$devicePublicKeyHash = hash('sha512', $devicePublicKey);
$query = $this->db->getQueryBuilder();
$query->update('notifications_pushhash')
->set('devicepublickey', $query->createNamedParameter($devicePublicKey))
->set('devicepublickeyhash', $query->createNamedParameter($devicePublicKeyHash))
->set('pushtokenhash', $query->createNamedParameter($pushTokenHash))
->set('proxyserver', $query->createNamedParameter($proxyServer))
->set('apptype', $query->createNamedParameter($appType))
->where($query->expr()->eq('uid', $query->createNamedParameter($user->getUID())))
->andWhere($query->expr()->eq('token', $query->createNamedParameter($token->getId(), IQueryBuilder::PARAM_INT)));
return $query->executeStatement() !== 0;
}
/**
* @param IUser $user
* @param IToken $token
* @return bool If the entry was deleted
*/
protected function deletePushToken(IUser $user, IToken $token): bool {
$query = $this->db->getQueryBuilder();
$query->delete('notifications_pushhash')
->where($query->expr()->eq('uid', $query->createNamedParameter($user->getUID())))
->andWhere($query->expr()->eq('token', $query->createNamedParameter($token->getId(), IQueryBuilder::PARAM_INT)));
return $query->executeStatement() !== 0;
}
/**
* @param IUser $user
* @param string $pushTokenHash
* @return bool If the entry was deleted
*/
protected function deletePushTokenByHash(IUser $user, string $pushTokenHash): bool {
$query = $this->db->getQueryBuilder();
$query->delete('notifications_pushhash')
->where($query->expr()->eq('uid', $query->createNamedParameter($user->getUID())))
->andWhere($query->expr()->eq('pushtokenhash', $query->createNamedParameter($pushTokenHash)));
return $query->executeStatement() !== 0;
}
}
@@ -0,0 +1,93 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2021, Julien Barnoin <julien@barnoin.com>
*
* @author Julien Barnoin <julien@barnoin.com>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\Notifications\Controller;
use OCA\Notifications\AppInfo\Application;
use OCA\Notifications\Model\SettingsMapper;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\DataResponse;
use OCP\AppFramework\OCSController;
use OCP\IConfig;
use OCP\IRequest;
class SettingsController extends OCSController {
protected IConfig $config;
protected SettingsMapper $settingsMapper;
protected string $userId;
public function __construct(string $appName,
IRequest $request,
IConfig $config,
SettingsMapper $settingsMapper,
string $userId) {
parent::__construct($appName, $request);
$this->config = $config;
$this->settingsMapper = $settingsMapper;
$this->userId = $userId;
}
/**
* @NoAdminRequired
*
* Update personal notification settings
*
* @param int $batchSetting How often E-mails about missed notifications should be sent (hourly: 1; every three hours: 2; daily: 3; weekly: 4)
* @param string $soundNotification Enable sound for notifications ('yes' or 'no')
* @param string $soundTalk Enable sound for Talk notifications ('yes' or 'no')
* @return DataResponse<Http::STATUS_OK, array<empty>, array{}>
*
* 200: Personal settings updated
*/
public function personal(int $batchSetting, string $soundNotification, string $soundTalk): DataResponse {
$this->settingsMapper->setBatchSettingForUser($this->userId, $batchSetting);
$this->config->setUserValue($this->userId, Application::APP_ID, 'sound_notification', $soundNotification !== 'no' ? 'yes' : 'no');
$this->config->setUserValue($this->userId, Application::APP_ID, 'sound_talk', $soundTalk !== 'no' ? 'yes' : 'no');
return new DataResponse();
}
/**
* @AuthorizedAdminSetting(settings=OCA\Notifications\Settings\Admin)
*
* Update default notification settings for new users
*
* @param int $batchSetting How often E-mails about missed notifications should be sent (hourly: 1; every three hours: 2; daily: 3; weekly: 4)
* @param string $soundNotification Enable sound for notifications ('yes' or 'no')
* @param string $soundTalk Enable sound for Talk notifications ('yes' or 'no')
* @return DataResponse<Http::STATUS_OK, array<empty>, array{}>
*
* 200: Admin settings updated
*/
public function admin(int $batchSetting, string $soundNotification, string $soundTalk): DataResponse {
$this->config->setAppValue(Application::APP_ID, 'setting_batchtime', (string) $batchSetting);
$this->config->setAppValue(Application::APP_ID, 'sound_notification', $soundNotification !== 'no' ? 'yes' : 'no');
$this->config->setAppValue(Application::APP_ID, 'sound_talk', $soundTalk !== 'no' ? 'yes' : 'no');
return new DataResponse();
}
}