From aac990eddf0a3bcc2c68b30ebc23b51ed5d0a54e Mon Sep 17 00:00:00 2001
From: Joas Schilling <nickvergessen@owncloud.com>
Date: Wed, 4 May 2016 15:26:48 +0200
Subject: [PATCH] Add a background job that generates notifications when an
 update is available

---
 apps/updatenotification/appinfo/info.xml      |   6 +-
 .../lib/Notification/BackgroundJob.php        | 169 ++++++++++++++++++
 .../DependencyInjection/DIContainer.php       |   4 +
 3 files changed, 178 insertions(+), 1 deletion(-)
 create mode 100644 apps/updatenotification/lib/Notification/BackgroundJob.php

diff --git a/apps/updatenotification/appinfo/info.xml b/apps/updatenotification/appinfo/info.xml
index 5d7a647fd03..3ea2d1a13de 100644
--- a/apps/updatenotification/appinfo/info.xml
+++ b/apps/updatenotification/appinfo/info.xml
@@ -5,10 +5,14 @@
 	<description>Displays update notifications for ownCloud and provides the SSO for the updater.</description>
 	<licence>AGPL</licence>
 	<author>Lukas Reschke</author>
-	<version>0.2.0</version>
+	<version>0.2.1</version>
 	<namespace>UpdateNotification</namespace>
 	<default_enable/>
 	<dependencies>
 		<owncloud min-version="9.1" max-version="9.1" />
 	</dependencies>
+
+	<background-jobs>
+		<job>OCA\UpdateNotification\Notification\BackgroundJob</job>
+	</background-jobs>
 </info>
diff --git a/apps/updatenotification/lib/Notification/BackgroundJob.php b/apps/updatenotification/lib/Notification/BackgroundJob.php
new file mode 100644
index 00000000000..7661f073e7b
--- /dev/null
+++ b/apps/updatenotification/lib/Notification/BackgroundJob.php
@@ -0,0 +1,169 @@
+<?php
+/**
+ * @author Joas Schilling <nickvergessen@owncloud.com>
+ *
+ * @copyright Copyright (c) 2016, ownCloud, Inc.
+ * @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\UpdateNotification\Notification;
+
+
+use OC\BackgroundJob\TimedJob;
+use OC\Installer;
+use OC\Updater\VersionCheck;
+use OCP\App\IAppManager;
+use OCP\Http\Client\IClientService;
+use OCP\IConfig;
+use OCP\IGroupManager;
+use OCP\IUser;
+use OCP\Notification\IManager;
+
+class BackgroundJob extends TimedJob {
+
+	/** @var IConfig */
+	protected $config;
+
+	/** @var IManager */
+	protected $notificationManager;
+
+	/** @var IGroupManager */
+	protected $groupManager;
+
+	/** @var IAppManager */
+	protected $appManager;
+
+	/** @var IClientService */
+	protected $client;
+
+	/** @var IUser[] */
+	protected $users;
+
+	/**
+	 * NotificationBackgroundJob constructor.
+	 *
+	 * @param IConfig $config
+	 * @param IManager $notificationManager
+	 * @param IGroupManager $groupManager
+	 * @param IAppManager $appManager
+	 * @param IClientService $client
+	 */
+	public function __construct(IConfig $config, IManager $notificationManager, IGroupManager $groupManager, IAppManager $appManager, IClientService $client) {
+		// Run once a day
+		$this->setInterval(60 * 60 * 24);
+
+		$this->config = $config;
+		$this->notificationManager = $notificationManager;
+		$this->groupManager = $groupManager;
+		$this->appManager = $appManager;
+		$this->client = $client;
+	}
+
+	protected function run($argument) {
+		$this->checkCoreUpdate();
+		$this->checkAppUpdates();
+	}
+
+	/**
+	 * Check for ownCloud update
+	 */
+	protected function checkCoreUpdate() {
+		if (in_array(\OC_Util::getChannel(), ['daily', 'git'])) {
+			// "These aren't the update channels you're looking for." - Ben Obi-Wan Kenobi
+			return;
+		}
+
+		$updater = new VersionCheck(
+			$this->client,
+			$this->config
+		);
+
+		$status = $updater->check();
+		if (isset($status['version'])) {
+			$this->createNotifications('core', $status['version']);
+		}
+	}
+
+	/**
+	 * Check all installed apps for updates
+	 */
+	protected function checkAppUpdates() {
+		$apps = $this->appManager->getInstalledApps();
+		foreach ($apps as $app) {
+			$update = Installer::isUpdateAvailable($app);
+			if ($update !== false) {
+				$this->createNotifications($app, $update);
+			}
+		}
+	}
+
+	/**
+	 * Create notifications for this app version
+	 *
+	 * @param string $app
+	 * @param string $version
+	 */
+	protected function createNotifications($app, $version) {
+		$lastNotification = $this->config->getAppValue('updatenotification', $app, false);
+		if ($lastNotification === $version) {
+			// We already notified about this update
+			return;
+		} else if ($lastNotification !== false) {
+			// Delete old updates
+			$this->deleteOutdatedNotifications($app, $lastNotification);
+		}
+
+
+		$notification = $this->notificationManager->createNotification();
+		$notification->setApp('updatenotification')
+			->setDateTime(new \DateTime())
+			->setObject($app, $version)
+			->setSubject('update_available');
+
+		foreach ($this->getUsersToNotify() as $user) {
+			$notification->setUser($user->getUID());
+			$this->notificationManager->notify($notification);
+		}
+
+		$this->config->setAppValue('updatenotification', $app, $version);
+	}
+
+	/**
+	 * @return \OCP\IUser[]
+	 */
+	protected function getUsersToNotify() {
+		if ($this->users !== null) {
+			return $this->users;
+		}
+
+		$groupToNotify = $this->groupManager->get('admin');
+		$this->users = $groupToNotify->getUsers();
+		return $this->users;
+	}
+
+	/**
+	 * Delete notifications for old updates
+	 *
+	 * @param string $app
+	 * @param string $version
+	 */
+	protected function deleteOutdatedNotifications($app, $version) {
+		$notification = $this->notificationManager->createNotification();
+		$notification->setApp('updatenotification')
+			->setObject($app, $version);
+		$this->notificationManager->markProcessed($notification);
+	}
+}
diff --git a/lib/private/AppFramework/DependencyInjection/DIContainer.php b/lib/private/AppFramework/DependencyInjection/DIContainer.php
index e120479ac59..92c3f618bdc 100644
--- a/lib/private/AppFramework/DependencyInjection/DIContainer.php
+++ b/lib/private/AppFramework/DependencyInjection/DIContainer.php
@@ -157,6 +157,10 @@ class DIContainer extends SimpleContainer implements IAppContainer {
 			return $this->getServer()->getGroupManager();
 		});
 
+		$this->registerService('OCP\\Http\\Client\\IClientService', function() {
+			return $this->getServer()->getHTTPClientService();
+		});
+
 		$this->registerService('OCP\\IL10N', function($c) {
 			return $this->getServer()->getL10N($c->query('AppName'));
 		});
-- 
GitLab