Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update notifications for core and apps #24444

Merged
merged 8 commits into from
May 25, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions apps/updatenotification/appinfo/app.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,18 @@
\OC_App::registerAdmin('updatenotification', 'admin');
}
}

$manager = \OC::$server->getNotificationManager();
$manager->registerNotifier(function() use ($manager) {
return new \OCA\UpdateNotification\Notification\Notifier(
$manager,
\OC::$server->getL10NFactory()
);
}, function() {
$l = \OC::$server->getL10N('updatenotification');
return [
'id' => 'updatenotification',
'name' => $l->t('Update notifications'),
];
});
}
6 changes: 5 additions & 1 deletion apps/updatenotification/appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
16 changes: 16 additions & 0 deletions apps/updatenotification/js/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,16 @@ $(document).ready(function(){
});
});
});

$('#release-channel').change(function() {
var newChannel = $('#release-channel').find(":selected").val();

if (newChannel === 'git' || newChannel === 'daily') {
$('#oca_updatenotification_groups em').removeClass('hidden');
} else {
$('#oca_updatenotification_groups em').addClass('hidden');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

protip: $(...).toggleClass('hidden', boolValue)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can't toggle, because then I need to catch the case when you change from stable to product and not toggle...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same for beta, and then it's messier than now

Copy link
Contributor

@PVince81 PVince81 May 10, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not really, this code should behave the same as yours, but shorter:
$('#oca_updatenotification_groups em').toggleClass('hidden', !(newChannel === 'git' || newChannel === 'daily'))

Anyway, it's not a biggie.

}

$.post(
OC.generateUrl('/apps/updatenotification/channel'),
{
Expand All @@ -51,4 +59,12 @@ $(document).ready(function(){
}
);
});

var $notificationTargetGroups = $('#oca_updatenotification_groups_list');
OC.Settings.setupGroupsSelect($notificationTargetGroups);
$notificationTargetGroups.change(function(ev) {
var groups = ev.val || [];
groups = JSON.stringify(groups);
OC.AppConfig.setValue('updatenotification', 'notify_groups', groups);
});
});
5 changes: 5 additions & 0 deletions apps/updatenotification/lib/Controller/AdminController.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,12 +100,17 @@ public function displayPanel() {
unset($channels[$key]);
}
$updateState = $this->updateChecker->getUpdateState();

$notifyGroups = json_decode($this->config->getAppValue('updatenotification', 'notify_groups', '["admin"]'), true);

$params = [
'isNewVersionAvailable' => ($updateState === []) ? false : true,
'lastChecked' => $lastUpdateCheck,
'currentChannel' => $currentChannel,
'channels' => $channels,
'newVersionString' => ($updateState === []) ? '' : $updateState['updateVersion'],

'notify_groups' => implode('|', $notifyGroups),
];

return new TemplateResponse($this->appName, 'admin', $params, '');
Expand Down
213 changes: 213 additions & 0 deletions apps/updatenotification/lib/Notification/BackgroundJob.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
<?php
/**
* @author Joas Schilling <[email protected]>
*
* @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\IGroup;
use OCP\IGroupManager;
use OCP\IURLGenerator;
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 IURLGenerator */
protected $urlGenerator;

/** @var IUser[] */
protected $users;

/**
* NotificationBackgroundJob constructor.
*
* @param IConfig $config
* @param IManager $notificationManager
* @param IGroupManager $groupManager
* @param IAppManager $appManager
* @param IClientService $client
* @param IURLGenerator $urlGenerator
*/
public function __construct(IConfig $config, IManager $notificationManager, IGroupManager $groupManager, IAppManager $appManager, IClientService $client, IURLGenerator $urlGenerator) {
// Run once a day
$this->setInterval(60 * 60 * 24);

$this->config = $config;
$this->notificationManager = $notificationManager;
$this->groupManager = $groupManager;
$this->appManager = $appManager;
$this->client = $client;
$this->urlGenerator = $urlGenerator;
}

protected function run($argument) {
$this->checkCoreUpdate();
$this->checkAppUpdates();
}

/**
* Check for ownCloud update
*/
protected function checkCoreUpdate() {
if (in_array($this->getChannel(), ['daily', 'git'])) {
// "These aren't the update channels you're looking for." - Ben Obi-Wan Kenobi
return;
}

$updater = $this->createVersionCheck();

$status = $updater->check();
if (isset($status['version'])) {
$url = $this->urlGenerator->linkToRouteAbsolute('settings_admin') . '#updater';
$this->createNotifications('core', $status['version'], $url);
}
}

/**
* Check all installed apps for updates
*/
protected function checkAppUpdates() {
$apps = $this->appManager->getInstalledApps();
foreach ($apps as $app) {
$update = $this->isUpdateAvailable($app);
if ($update !== false) {
$url = $this->urlGenerator->linkToRouteAbsolute('settings.AppSettings.viewApps') . '#app-' . $app;
$this->createNotifications($app, $update, $url);
}
}
}

/**
* Create notifications for this app version
*
* @param string $app
* @param string $version
* @param string $url
*/
protected function createNotifications($app, $version, $url) {
$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')
->setLink($url);

foreach ($this->getUsersToNotify() as $uid) {
$notification->setUser($uid);
$this->notificationManager->notify($notification);
}

$this->config->setAppValue('updatenotification', $app, $version);
}

/**
* @return string[]
*/
protected function getUsersToNotify() {
if ($this->users !== null) {
return $this->users;
}

$notifyGroups = json_decode($this->config->getAppValue('updatenotification', 'notify_groups', '["admin"]'), true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if no groups were selected, disable the background job completely (or make it no-op)
In some scenarios an admin might not want to have a bkg job pinging the app store for every app regularily.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, maybe one can just disable the update notification app

$this->users = [];
foreach ($notifyGroups as $group) {
$groupToNotify = $this->groupManager->get($group);
if ($groupToNotify instanceof IGroup) {
foreach ($groupToNotify->getUsers() as $user) {
$this->users[$user->getUID()] = true;
}
}
}

$this->users = array_keys($this->users);

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);
}

/**
* @return VersionCheck
*/
protected function createVersionCheck() {
return new VersionCheck(
$this->client,
$this->config
);
}

/**
* @return string
*/
protected function getChannel() {
return \OC_Util::getChannel();
}

/**
* @param string $app
* @return string|false
*/
protected function isUpdateAvailable($app) {
return Installer::isUpdateAvailable($app);
}
}
Loading