@ -27,8 +27,10 @@ declare(strict_types=1);
namespace OC\Notification;
use OC\AppFramework\Bootstrap\Coordinator;
use OCP\AppFramework\QueryException;
use OCP\ILogger;
use OCP\AppFramework\Utility\ITimeFactory;
use OCP\ICache;
use OCP\ICacheFactory;
use OCP\IUserManager;
use OCP\Notification\AlreadyProcessedException;
use OCP\Notification\IApp;
use OCP\Notification\IDeferrableApp;
@ -37,11 +39,22 @@ use OCP\Notification\IManager;
use OCP\Notification\INotification;
use OCP\Notification\INotifier;
use OCP\RichObjectStrings\IValidator;
use OCP\Support\Subscription\IRegistry;
use Psr\Container\ContainerExceptionInterface;
use Psr\Log\LoggerInterface;
class Manager implements IManager {
/** @var IValidator */
protected $validator;
/** @var ILogger */
/** @var IUserManager */
private $userManager;
/** @var ICache */
protected $cache;
/** @var ITimeFactory */
protected $timeFactory;
/** @var IRegistry */
protected $subscription;
/** @var LoggerInterface */
protected $logger;
/** @var Coordinator */
private $coordinator;
@ -64,9 +77,17 @@ class Manager implements IManager {
private $parsedRegistrationContext;
public function __construct(IValidator $validator,
ILogger $logger,
IUserManager $userManager,
ICacheFactory $cacheFactory,
ITimeFactory $timeFactory,
IRegistry $subscription,
LoggerInterface $logger,
Coordinator $coordinator) {
$this->validator = $validator;
$this->userManager = $userManager;
$this->cache = $cacheFactory->createDistributed('notifications');
$this->timeFactory = $timeFactory;
$this->subscription = $subscription;
$this->logger = $logger;
$this->coordinator = $coordinator;
@ -97,9 +118,10 @@ class Manager implements IManager {
*/
public function registerNotifier(\Closure $service, \Closure $info) {
$infoData = $info();
$this->logger->logException( new \InvalidArgumentException(
$exception = new \InvalidArgumentException(
'Notifier ' . $infoData['name'] . ' (id: ' . $infoData['id'] . ') is not considered because it is using the old way to register.'
));
);
$this->logger->error($exception->getMessage(), ['exception' => $exception]);
}
/**
@ -121,10 +143,10 @@ class Manager implements IManager {
foreach ($this->appClasses as $appClass) {
try {
$app = \OC::$server->query ($appClass);
} catch (QueryException $e) {
$this->logger->logException($e , [
'message' => 'Failed to load notification app class: ' . $appClass ,
$app = \OC::$server->get ($appClass);
} catch (ContainerExceptionInterface $e) {
$this->logger->error('Failed to load notification app class: ' . $appClass , [
'exception' => $e ,
'app' => 'notifications',
]);
continue;
@ -153,10 +175,10 @@ class Manager implements IManager {
$notifierServices = $this->coordinator->getRegistrationContext()->getNotifierServices();
foreach ($notifierServices as $notifierService) {
try {
$notifier = \OC::$server->query ($notifierService->getService());
} catch (QueryException $e) {
$this->logger->logException($e , [
'message' => 'Failed to load notification notifier class: ' . $notifierService->getService() ,
$notifier = \OC::$server->get ($notifierService->getService());
} catch (ContainerExceptionInterface $e) {
$this->logger->error('Failed to load notification notifier class: ' . $notifierService->getService() , [
'exception' => $e ,
'app' => 'notifications',
]);
continue;
@ -181,10 +203,10 @@ class Manager implements IManager {
foreach ($this->notifierClasses as $notifierClass) {
try {
$notifier = \OC::$server->query ($notifierClass);
} catch (QueryException $e) {
$this->logger->logException($e , [
'message' => 'Failed to load notification notifier class: ' . $notifierClass ,
$notifier = \OC::$server->get ($notifierClass);
} catch (ContainerExceptionInterface $e) {
$this->logger->error('Failed to load notification notifier class: ' . $notifierClass , [
'exception' => $e ,
'app' => 'notifications',
]);
continue;
@ -277,6 +299,28 @@ class Manager implements IManager {
$this->deferPushing = false;
}
/**
* {@inheritDoc}
*/
public function isFairUseOfFreePushService(): bool {
$pushAllowed = $this->cache->get('push_fair_use');
if ($pushAllowed === null) {
/**
* 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 setting up your
* own push server or using Nextcloud Enterprise.
*/
// TODO Remove time check after 1st March 2022
$isFairUse = $this->timeFactory->getTime() < 1646089200
|| $this->subscription->delegateHasValidSubscription()
|| $this->userManager->countSeenUsers() < 5000 ;
$pushAllowed = $isFairUse ? 'yes' : 'no';
$this->cache->set('push_fair_use', $pushAllowed, 3600);
}
return $pushAllowed === 'yes';
}
/**
* @param INotification $notification
* @throws \InvalidArgumentException When the notification is not valid