mirror of
https://github.com/nextcloud/server.git
synced 2026-05-28 04:32:30 -04:00
Merge pull request #47865 from nextcloud/admin_audit/enh/move-to-event-listeners-v2
Move admin_audit to proper event listeners v2
This commit is contained in:
commit
dfa994ef28
37 changed files with 1174 additions and 1030 deletions
|
|
@ -8,20 +8,22 @@ $baseDir = $vendorDir;
|
|||
return array(
|
||||
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||
'OCA\\AdminAudit\\Actions\\Action' => $baseDir . '/../lib/Actions/Action.php',
|
||||
'OCA\\AdminAudit\\Actions\\AppManagement' => $baseDir . '/../lib/Actions/AppManagement.php',
|
||||
'OCA\\AdminAudit\\Actions\\Auth' => $baseDir . '/../lib/Actions/Auth.php',
|
||||
'OCA\\AdminAudit\\Actions\\Console' => $baseDir . '/../lib/Actions/Console.php',
|
||||
'OCA\\AdminAudit\\Actions\\Files' => $baseDir . '/../lib/Actions/Files.php',
|
||||
'OCA\\AdminAudit\\Actions\\GroupManagement' => $baseDir . '/../lib/Actions/GroupManagement.php',
|
||||
'OCA\\AdminAudit\\Actions\\Security' => $baseDir . '/../lib/Actions/Security.php',
|
||||
'OCA\\AdminAudit\\Actions\\Sharing' => $baseDir . '/../lib/Actions/Sharing.php',
|
||||
'OCA\\AdminAudit\\Actions\\TagManagement' => $baseDir . '/../lib/Actions/TagManagement.php',
|
||||
'OCA\\AdminAudit\\Actions\\Trashbin' => $baseDir . '/../lib/Actions/Trashbin.php',
|
||||
'OCA\\AdminAudit\\Actions\\UserManagement' => $baseDir . '/../lib/Actions/UserManagement.php',
|
||||
'OCA\\AdminAudit\\Actions\\Versions' => $baseDir . '/../lib/Actions/Versions.php',
|
||||
'OCA\\AdminAudit\\AppInfo\\Application' => $baseDir . '/../lib/AppInfo/Application.php',
|
||||
'OCA\\AdminAudit\\AuditLogger' => $baseDir . '/../lib/AuditLogger.php',
|
||||
'OCA\\AdminAudit\\BackgroundJobs\\Rotate' => $baseDir . '/../lib/BackgroundJobs/Rotate.php',
|
||||
'OCA\\AdminAudit\\IAuditLogger' => $baseDir . '/../lib/IAuditLogger.php',
|
||||
'OCA\\AdminAudit\\Listener\\AppManagementEventListener' => $baseDir . '/../lib/Listener/AppManagementEventListener.php',
|
||||
'OCA\\AdminAudit\\Listener\\AuthEventListener' => $baseDir . '/../lib/Listener/AuthEventListener.php',
|
||||
'OCA\\AdminAudit\\Listener\\ConsoleEventListener' => $baseDir . '/../lib/Listener/ConsoleEventListener.php',
|
||||
'OCA\\AdminAudit\\Listener\\CriticalActionPerformedEventListener' => $baseDir . '/../lib/Listener/CriticalActionPerformedEventListener.php',
|
||||
'OCA\\AdminAudit\\Listener\\FileEventListener' => $baseDir . '/../lib/Listener/FileEventListener.php',
|
||||
'OCA\\AdminAudit\\Listener\\GroupManagementEventListener' => $baseDir . '/../lib/Listener/GroupManagementEventListener.php',
|
||||
'OCA\\AdminAudit\\Listener\\SecurityEventListener' => $baseDir . '/../lib/Listener/SecurityEventListener.php',
|
||||
'OCA\\AdminAudit\\Listener\\SharingEventListener' => $baseDir . '/../lib/Listener/SharingEventListener.php',
|
||||
'OCA\\AdminAudit\\Listener\\UserManagementEventListener' => $baseDir . '/../lib/Listener/UserManagementEventListener.php',
|
||||
);
|
||||
|
|
|
|||
|
|
@ -23,22 +23,24 @@ class ComposerStaticInitAdminAudit
|
|||
public static $classMap = array (
|
||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||
'OCA\\AdminAudit\\Actions\\Action' => __DIR__ . '/..' . '/../lib/Actions/Action.php',
|
||||
'OCA\\AdminAudit\\Actions\\AppManagement' => __DIR__ . '/..' . '/../lib/Actions/AppManagement.php',
|
||||
'OCA\\AdminAudit\\Actions\\Auth' => __DIR__ . '/..' . '/../lib/Actions/Auth.php',
|
||||
'OCA\\AdminAudit\\Actions\\Console' => __DIR__ . '/..' . '/../lib/Actions/Console.php',
|
||||
'OCA\\AdminAudit\\Actions\\Files' => __DIR__ . '/..' . '/../lib/Actions/Files.php',
|
||||
'OCA\\AdminAudit\\Actions\\GroupManagement' => __DIR__ . '/..' . '/../lib/Actions/GroupManagement.php',
|
||||
'OCA\\AdminAudit\\Actions\\Security' => __DIR__ . '/..' . '/../lib/Actions/Security.php',
|
||||
'OCA\\AdminAudit\\Actions\\Sharing' => __DIR__ . '/..' . '/../lib/Actions/Sharing.php',
|
||||
'OCA\\AdminAudit\\Actions\\TagManagement' => __DIR__ . '/..' . '/../lib/Actions/TagManagement.php',
|
||||
'OCA\\AdminAudit\\Actions\\Trashbin' => __DIR__ . '/..' . '/../lib/Actions/Trashbin.php',
|
||||
'OCA\\AdminAudit\\Actions\\UserManagement' => __DIR__ . '/..' . '/../lib/Actions/UserManagement.php',
|
||||
'OCA\\AdminAudit\\Actions\\Versions' => __DIR__ . '/..' . '/../lib/Actions/Versions.php',
|
||||
'OCA\\AdminAudit\\AppInfo\\Application' => __DIR__ . '/..' . '/../lib/AppInfo/Application.php',
|
||||
'OCA\\AdminAudit\\AuditLogger' => __DIR__ . '/..' . '/../lib/AuditLogger.php',
|
||||
'OCA\\AdminAudit\\BackgroundJobs\\Rotate' => __DIR__ . '/..' . '/../lib/BackgroundJobs/Rotate.php',
|
||||
'OCA\\AdminAudit\\IAuditLogger' => __DIR__ . '/..' . '/../lib/IAuditLogger.php',
|
||||
'OCA\\AdminAudit\\Listener\\AppManagementEventListener' => __DIR__ . '/..' . '/../lib/Listener/AppManagementEventListener.php',
|
||||
'OCA\\AdminAudit\\Listener\\AuthEventListener' => __DIR__ . '/..' . '/../lib/Listener/AuthEventListener.php',
|
||||
'OCA\\AdminAudit\\Listener\\ConsoleEventListener' => __DIR__ . '/..' . '/../lib/Listener/ConsoleEventListener.php',
|
||||
'OCA\\AdminAudit\\Listener\\CriticalActionPerformedEventListener' => __DIR__ . '/..' . '/../lib/Listener/CriticalActionPerformedEventListener.php',
|
||||
'OCA\\AdminAudit\\Listener\\FileEventListener' => __DIR__ . '/..' . '/../lib/Listener/FileEventListener.php',
|
||||
'OCA\\AdminAudit\\Listener\\GroupManagementEventListener' => __DIR__ . '/..' . '/../lib/Listener/GroupManagementEventListener.php',
|
||||
'OCA\\AdminAudit\\Listener\\SecurityEventListener' => __DIR__ . '/..' . '/../lib/Listener/SecurityEventListener.php',
|
||||
'OCA\\AdminAudit\\Listener\\SharingEventListener' => __DIR__ . '/..' . '/../lib/Listener/SharingEventListener.php',
|
||||
'OCA\\AdminAudit\\Listener\\UserManagementEventListener' => __DIR__ . '/..' . '/../lib/Listener/UserManagementEventListener.php',
|
||||
);
|
||||
|
||||
public static function getInitializer(ClassLoader $loader)
|
||||
|
|
|
|||
|
|
@ -1,42 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCA\AdminAudit\Actions;
|
||||
|
||||
class AppManagement extends Action {
|
||||
|
||||
/**
|
||||
* @param string $appName
|
||||
*/
|
||||
public function enableApp(string $appName): void {
|
||||
$this->log('App "%s" enabled',
|
||||
['app' => $appName],
|
||||
['app']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $appName
|
||||
* @param string[] $groups
|
||||
*/
|
||||
public function enableAppForGroups(string $appName, array $groups): void {
|
||||
$this->log('App "%1$s" enabled for groups: %2$s',
|
||||
['app' => $appName, 'groups' => implode(', ', $groups)],
|
||||
['app', 'groups']
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $appName
|
||||
*/
|
||||
public function disableApp(string $appName): void {
|
||||
$this->log('App "%s" disabled',
|
||||
['app' => $appName],
|
||||
['app']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCA\AdminAudit\Actions;
|
||||
|
||||
/**
|
||||
* Class Auth logs all auth related actions
|
||||
*
|
||||
* @package OCA\AdminAudit\Actions
|
||||
*/
|
||||
class Auth extends Action {
|
||||
public function loginAttempt(array $params): void {
|
||||
$this->log(
|
||||
'Login attempt: "%s"',
|
||||
$params,
|
||||
[
|
||||
'uid',
|
||||
],
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
public function loginSuccessful(array $params): void {
|
||||
$this->log(
|
||||
'Login successful: "%s"',
|
||||
$params,
|
||||
[
|
||||
'uid',
|
||||
],
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
public function logout(array $params): void {
|
||||
$this->log(
|
||||
'Logout occurred',
|
||||
[],
|
||||
[]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,28 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCA\AdminAudit\Actions;
|
||||
|
||||
class Console extends Action {
|
||||
/**
|
||||
* @param array $arguments
|
||||
*/
|
||||
public function runCommand(array $arguments): void {
|
||||
if (!isset($arguments[1]) || $arguments[1] === '_completion') {
|
||||
// Don't log autocompletion
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove `./occ`
|
||||
array_shift($arguments);
|
||||
|
||||
$this->log('Console command executed: %s',
|
||||
['arguments' => implode(' ', $arguments)],
|
||||
['arguments']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -18,7 +18,6 @@ use OCP\Files\Events\Node\NodeRenamedEvent;
|
|||
use OCP\Files\Events\Node\NodeWrittenEvent;
|
||||
use OCP\Files\InvalidPathException;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\Preview\BeforePreviewFetchedEvent;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
|
|
@ -229,33 +228,4 @@ class Files extends Action {
|
|||
array_keys($params)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs preview access to a file
|
||||
*
|
||||
* @param BeforePreviewFetchedEvent $event
|
||||
*/
|
||||
public function preview(BeforePreviewFetchedEvent $event): void {
|
||||
try {
|
||||
$file = $event->getNode();
|
||||
$params = [
|
||||
'id' => $file->getId(),
|
||||
'width' => $event->getWidth(),
|
||||
'height' => $event->getHeight(),
|
||||
'crop' => $event->isCrop(),
|
||||
'mode' => $event->getMode(),
|
||||
'path' => mb_substr($file->getInternalPath(), 5)
|
||||
];
|
||||
} catch (InvalidPathException|NotFoundException $e) {
|
||||
\OCP\Server::get(LoggerInterface::class)->error(
|
||||
'Exception thrown in file preview: '.$e->getMessage(), ['app' => 'admin_audit', 'exception' => $e]
|
||||
);
|
||||
return;
|
||||
}
|
||||
$this->log(
|
||||
'Preview accessed: (id: "%s", width: "%s", height: "%s" crop: "%s", mode: "%s", path: "%s")',
|
||||
$params,
|
||||
array_keys($params)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,87 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCA\AdminAudit\Actions;
|
||||
|
||||
use OCP\IGroup;
|
||||
use OCP\IUser;
|
||||
|
||||
/**
|
||||
* Class GroupManagement logs all group manager related events
|
||||
*
|
||||
* @package OCA\AdminAudit\Actions
|
||||
*/
|
||||
class GroupManagement extends Action {
|
||||
|
||||
/**
|
||||
* log add user to group event
|
||||
*
|
||||
* @param IGroup $group
|
||||
* @param IUser $user
|
||||
*/
|
||||
public function addUser(IGroup $group, IUser $user): void {
|
||||
$this->log('User "%s" added to group "%s"',
|
||||
[
|
||||
'group' => $group->getGID(),
|
||||
'user' => $user->getUID()
|
||||
],
|
||||
[
|
||||
'user', 'group'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* log remove user from group event
|
||||
*
|
||||
* @param IGroup $group
|
||||
* @param IUser $user
|
||||
*/
|
||||
public function removeUser(IGroup $group, IUser $user): void {
|
||||
$this->log('User "%s" removed from group "%s"',
|
||||
[
|
||||
'group' => $group->getGID(),
|
||||
'user' => $user->getUID()
|
||||
],
|
||||
[
|
||||
'user', 'group'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* log create group to group event
|
||||
*
|
||||
* @param IGroup $group
|
||||
*/
|
||||
public function createGroup(IGroup $group): void {
|
||||
$this->log('Group created: "%s"',
|
||||
[
|
||||
'group' => $group->getGID()
|
||||
],
|
||||
[
|
||||
'group'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* log delete group to group event
|
||||
*
|
||||
* @param IGroup $group
|
||||
*/
|
||||
public function deleteGroup(IGroup $group): void {
|
||||
$this->log('Group deleted: "%s"',
|
||||
[
|
||||
'group' => $group->getGID()
|
||||
],
|
||||
[
|
||||
'group'
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,60 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCA\AdminAudit\Actions;
|
||||
|
||||
use OCP\Authentication\TwoFactorAuth\IProvider;
|
||||
use OCP\IUser;
|
||||
|
||||
/**
|
||||
* Class Sharing logs the sharing actions
|
||||
*
|
||||
* @package OCA\AdminAudit\Actions
|
||||
*/
|
||||
class Security extends Action {
|
||||
/**
|
||||
* Logs failed twofactor challenge
|
||||
*/
|
||||
public function twofactorFailed(IUser $user, IProvider $provider): void {
|
||||
$params = [
|
||||
'displayName' => $user->getDisplayName(),
|
||||
'uid' => $user->getUID(),
|
||||
'provider' => $provider->getDisplayName(),
|
||||
];
|
||||
|
||||
$this->log(
|
||||
'Failed two factor attempt by user %s (%s) with provider %s',
|
||||
$params,
|
||||
[
|
||||
'displayName',
|
||||
'uid',
|
||||
'provider',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs successful twofactor challenge
|
||||
*/
|
||||
public function twofactorSuccess(IUser $user, IProvider $provider): void {
|
||||
$params = [
|
||||
'displayName' => $user->getDisplayName(),
|
||||
'uid' => $user->getUID(),
|
||||
'provider' => $provider->getDisplayName(),
|
||||
];
|
||||
|
||||
$this->log(
|
||||
'Successful two factor attempt by user %s (%s) with provider %s',
|
||||
$params,
|
||||
[
|
||||
'displayName',
|
||||
'uid',
|
||||
'provider',
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -7,279 +7,12 @@ declare(strict_types=1);
|
|||
*/
|
||||
namespace OCA\AdminAudit\Actions;
|
||||
|
||||
use OCP\Share\IShare;
|
||||
|
||||
/**
|
||||
* Class Sharing logs the sharing actions
|
||||
*
|
||||
* @package OCA\AdminAudit\Actions
|
||||
*/
|
||||
class Sharing extends Action {
|
||||
/**
|
||||
* Logs sharing of data
|
||||
*
|
||||
* @param array $params
|
||||
*/
|
||||
public function shared(array $params): void {
|
||||
if ($params['shareType'] === IShare::TYPE_LINK) {
|
||||
$this->log(
|
||||
'The %s "%s" with ID "%s" has been shared via link with permissions "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'path',
|
||||
'itemSource',
|
||||
'permissions',
|
||||
'id',
|
||||
]
|
||||
);
|
||||
} elseif ($params['shareType'] === IShare::TYPE_USER) {
|
||||
$this->log(
|
||||
'The %s "%s" with ID "%s" has been shared to the user "%s" with permissions "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'path',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'permissions',
|
||||
'id',
|
||||
]
|
||||
);
|
||||
} elseif ($params['shareType'] === IShare::TYPE_GROUP) {
|
||||
$this->log(
|
||||
'The %s "%s" with ID "%s" has been shared to the group "%s" with permissions "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'path',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'permissions',
|
||||
'id',
|
||||
]
|
||||
);
|
||||
} elseif ($params['shareType'] === IShare::TYPE_ROOM) {
|
||||
$this->log(
|
||||
'The %s "%s" with ID "%s" has been shared to the room "%s" with permissions "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'path',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'permissions',
|
||||
'id',
|
||||
]
|
||||
);
|
||||
} elseif ($params['shareType'] === IShare::TYPE_EMAIL) {
|
||||
$this->log(
|
||||
'The %s "%s" with ID "%s" has been shared to the email recipient "%s" with permissions "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'path',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'permissions',
|
||||
'id',
|
||||
]
|
||||
);
|
||||
} elseif ($params['shareType'] === IShare::TYPE_CIRCLE) {
|
||||
$this->log(
|
||||
'The %s "%s" with ID "%s" has been shared to the circle "%s" with permissions "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'path',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'permissions',
|
||||
'id',
|
||||
]
|
||||
);
|
||||
} elseif ($params['shareType'] === IShare::TYPE_REMOTE) {
|
||||
$this->log(
|
||||
'The %s "%s" with ID "%s" has been shared to the remote user "%s" with permissions "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'path',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'permissions',
|
||||
'id',
|
||||
]
|
||||
);
|
||||
} elseif ($params['shareType'] === IShare::TYPE_REMOTE_GROUP) {
|
||||
$this->log(
|
||||
'The %s "%s" with ID "%s" has been shared to the remote group "%s" with permissions "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'path',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'permissions',
|
||||
'id',
|
||||
]
|
||||
);
|
||||
} elseif ($params['shareType'] === IShare::TYPE_DECK) {
|
||||
$this->log(
|
||||
'The %s "%s" with ID "%s" has been shared to the deck card "%s" with permissions "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'path',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'permissions',
|
||||
'id',
|
||||
]
|
||||
);
|
||||
} elseif ($params['shareType'] === IShare::TYPE_SCIENCEMESH) {
|
||||
$this->log(
|
||||
'The %s "%s" with ID "%s" has been shared to the ScienceMesh user "%s" with permissions "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'path',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'permissions',
|
||||
'id',
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs unsharing of data
|
||||
*
|
||||
* @param array $params
|
||||
*/
|
||||
public function unshare(array $params): void {
|
||||
if ($params['shareType'] === IShare::TYPE_LINK) {
|
||||
$this->log(
|
||||
'The %s "%s" with ID "%s" has been unshared (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'fileTarget',
|
||||
'itemSource',
|
||||
'id',
|
||||
]
|
||||
);
|
||||
} elseif ($params['shareType'] === IShare::TYPE_USER) {
|
||||
$this->log(
|
||||
'The %s "%s" with ID "%s" has been unshared from the user "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'fileTarget',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'id',
|
||||
]
|
||||
);
|
||||
} elseif ($params['shareType'] === IShare::TYPE_GROUP) {
|
||||
$this->log(
|
||||
'The %s "%s" with ID "%s" has been unshared from the group "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'fileTarget',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'id',
|
||||
]
|
||||
);
|
||||
} elseif ($params['shareType'] === IShare::TYPE_ROOM) {
|
||||
$this->log(
|
||||
'The %s "%s" with ID "%s" has been unshared from the room "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'fileTarget',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'id',
|
||||
]
|
||||
);
|
||||
} elseif ($params['shareType'] === IShare::TYPE_EMAIL) {
|
||||
$this->log(
|
||||
'The %s "%s" with ID "%s" has been unshared from the email recipient "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'fileTarget',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'id',
|
||||
]
|
||||
);
|
||||
} elseif ($params['shareType'] === IShare::TYPE_CIRCLE) {
|
||||
$this->log(
|
||||
'The %s "%s" with ID "%s" has been unshared from the circle "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'fileTarget',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'id',
|
||||
]
|
||||
);
|
||||
} elseif ($params['shareType'] === IShare::TYPE_REMOTE) {
|
||||
$this->log(
|
||||
'The %s "%s" with ID "%s" has been unshared from the remote user "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'fileTarget',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'id',
|
||||
]
|
||||
);
|
||||
} elseif ($params['shareType'] === IShare::TYPE_REMOTE_GROUP) {
|
||||
$this->log(
|
||||
'The %s "%s" with ID "%s" has been unshared from the remote group "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'fileTarget',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'id',
|
||||
]
|
||||
);
|
||||
} elseif ($params['shareType'] === IShare::TYPE_DECK) {
|
||||
$this->log(
|
||||
'The %s "%s" with ID "%s" has been unshared from the deck card "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'fileTarget',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'id',
|
||||
]
|
||||
);
|
||||
} elseif ($params['shareType'] === IShare::TYPE_SCIENCEMESH) {
|
||||
$this->log(
|
||||
'The %s "%s" with ID "%s" has been unshared from the ScienceMesh user "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'fileTarget',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'id',
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the updating of permission changes for shares
|
||||
|
|
|
|||
|
|
@ -1,122 +0,0 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCA\AdminAudit\Actions;
|
||||
|
||||
use OCP\IUser;
|
||||
|
||||
/**
|
||||
* Class UserManagement logs all user management related actions.
|
||||
*
|
||||
* @package OCA\AdminAudit\Actions
|
||||
*/
|
||||
class UserManagement extends Action {
|
||||
/**
|
||||
* Log creation of users
|
||||
*
|
||||
* @param array $params
|
||||
*/
|
||||
public function create(array $params): void {
|
||||
$this->log(
|
||||
'User created: "%s"',
|
||||
$params,
|
||||
[
|
||||
'uid',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log assignments of users (typically user backends)
|
||||
*
|
||||
* @param string $uid
|
||||
*/
|
||||
public function assign(string $uid): void {
|
||||
$this->log(
|
||||
'UserID assigned: "%s"',
|
||||
[ 'uid' => $uid ],
|
||||
[ 'uid' ]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log deletion of users
|
||||
*
|
||||
* @param array $params
|
||||
*/
|
||||
public function delete(array $params): void {
|
||||
$this->log(
|
||||
'User deleted: "%s"',
|
||||
$params,
|
||||
[
|
||||
'uid',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log unassignments of users (typically user backends, no data removed)
|
||||
*
|
||||
* @param string $uid
|
||||
*/
|
||||
public function unassign(string $uid): void {
|
||||
$this->log(
|
||||
'UserID unassigned: "%s"',
|
||||
[ 'uid' => $uid ],
|
||||
[ 'uid' ]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log enabling of users
|
||||
*
|
||||
* @param array $params
|
||||
*/
|
||||
public function change(array $params): void {
|
||||
switch ($params['feature']) {
|
||||
case 'enabled':
|
||||
$this->log(
|
||||
$params['value'] === true
|
||||
? 'User enabled: "%s"'
|
||||
: 'User disabled: "%s"',
|
||||
['user' => $params['user']->getUID()],
|
||||
[
|
||||
'user',
|
||||
]
|
||||
);
|
||||
break;
|
||||
case 'eMailAddress':
|
||||
$this->log(
|
||||
'Email address changed for user %s',
|
||||
['user' => $params['user']->getUID()],
|
||||
[
|
||||
'user',
|
||||
]
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs changing of the user scope
|
||||
*
|
||||
* @param IUser $user
|
||||
*/
|
||||
public function setPassword(IUser $user): void {
|
||||
if ($user->getBackendClassName() === 'Database') {
|
||||
$this->log(
|
||||
'Password of user "%s" has been changed',
|
||||
[
|
||||
'user' => $user->getUID(),
|
||||
],
|
||||
[
|
||||
'user',
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,29 +1,35 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\AdminAudit\AppInfo;
|
||||
|
||||
use OC\Group\Manager as GroupManager;
|
||||
use OC\User\Session as UserSession;
|
||||
use OCA\AdminAudit\Actions\AppManagement;
|
||||
use OCA\AdminAudit\Actions\Auth;
|
||||
use OCA\AdminAudit\Actions\Console;
|
||||
use OCA\AdminAudit\Actions\Files;
|
||||
use OCA\AdminAudit\Actions\GroupManagement;
|
||||
use OCA\AdminAudit\Actions\Security;
|
||||
use OCA\AdminAudit\Actions\Sharing;
|
||||
use OCA\AdminAudit\Actions\TagManagement;
|
||||
use OCA\AdminAudit\Actions\Trashbin;
|
||||
use OCA\AdminAudit\Actions\UserManagement;
|
||||
use OCA\AdminAudit\Actions\Versions;
|
||||
use OCA\AdminAudit\AuditLogger;
|
||||
use OCA\AdminAudit\IAuditLogger;
|
||||
use OCA\AdminAudit\Listener\AppManagementEventListener;
|
||||
use OCA\AdminAudit\Listener\AuthEventListener;
|
||||
use OCA\AdminAudit\Listener\ConsoleEventListener;
|
||||
use OCA\AdminAudit\Listener\CriticalActionPerformedEventListener;
|
||||
use OCP\App\ManagerEvent;
|
||||
use OCA\AdminAudit\Listener\FileEventListener;
|
||||
use OCA\AdminAudit\Listener\GroupManagementEventListener;
|
||||
use OCA\AdminAudit\Listener\SecurityEventListener;
|
||||
use OCA\AdminAudit\Listener\SharingEventListener;
|
||||
use OCA\AdminAudit\Listener\UserManagementEventListener;
|
||||
use OCP\App\Events\AppDisableEvent;
|
||||
use OCP\App\Events\AppEnableEvent;
|
||||
use OCP\App\Events\AppUpdateEvent;
|
||||
use OCP\AppFramework\App;
|
||||
use OCP\AppFramework\Bootstrap\IBootContext;
|
||||
use OCP\AppFramework\Bootstrap\IBootstrap;
|
||||
|
|
@ -40,21 +46,31 @@ use OCP\Files\Events\Node\NodeCreatedEvent;
|
|||
use OCP\Files\Events\Node\NodeDeletedEvent;
|
||||
use OCP\Files\Events\Node\NodeRenamedEvent;
|
||||
use OCP\Files\Events\Node\NodeWrittenEvent;
|
||||
use OCP\Group\Events\GroupCreatedEvent;
|
||||
use OCP\Group\Events\GroupDeletedEvent;
|
||||
use OCP\Group\Events\UserAddedEvent;
|
||||
use OCP\Group\Events\UserRemovedEvent;
|
||||
use OCP\IConfig;
|
||||
use OCP\IGroupManager;
|
||||
use OCP\IUserSession;
|
||||
use OCP\Log\Audit\CriticalActionPerformedEvent;
|
||||
use OCP\Log\ILogFactory;
|
||||
use OCP\Preview\BeforePreviewFetchedEvent;
|
||||
use OCP\Share;
|
||||
use OCP\Share\Events\ShareCreatedEvent;
|
||||
use OCP\Share\Events\ShareDeletedEvent;
|
||||
use OCP\User\Events\BeforeUserLoggedInEvent;
|
||||
use OCP\User\Events\BeforeUserLoggedOutEvent;
|
||||
use OCP\User\Events\PasswordUpdatedEvent;
|
||||
use OCP\User\Events\UserChangedEvent;
|
||||
use OCP\User\Events\UserCreatedEvent;
|
||||
use OCP\User\Events\UserDeletedEvent;
|
||||
use OCP\User\Events\UserIdAssignedEvent;
|
||||
use OCP\User\Events\UserIdUnassignedEvent;
|
||||
use OCP\User\Events\UserLoggedInEvent;
|
||||
use OCP\User\Events\UserLoggedInWithCookieEvent;
|
||||
use OCP\Util;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
class Application extends App implements IBootstrap {
|
||||
/** @var LoggerInterface */
|
||||
protected $logger;
|
||||
|
||||
public function __construct() {
|
||||
parent::__construct('admin_audit');
|
||||
}
|
||||
|
|
@ -65,6 +81,45 @@ class Application extends App implements IBootstrap {
|
|||
});
|
||||
|
||||
$context->registerEventListener(CriticalActionPerformedEvent::class, CriticalActionPerformedEventListener::class);
|
||||
|
||||
// User management events
|
||||
$context->registerEventListener(UserCreatedEvent::class, UserManagementEventListener::class);
|
||||
$context->registerEventListener(UserDeletedEvent::class, UserManagementEventListener::class);
|
||||
$context->registerEventListener(UserChangedEvent::class, UserManagementEventListener::class);
|
||||
$context->registerEventListener(PasswordUpdatedEvent::class, UserManagementEventListener::class);
|
||||
$context->registerEventListener(UserIdAssignedEvent::class, UserManagementEventListener::class);
|
||||
$context->registerEventListener(UserIdUnassignedEvent::class, UserManagementEventListener::class);
|
||||
|
||||
// Group management events
|
||||
$context->registerEventListener(UserAddedEvent::class, GroupManagementEventListener::class);
|
||||
$context->registerEventListener(UserRemovedEvent::class, GroupManagementEventListener::class);
|
||||
$context->registerEventListener(GroupCreatedEvent::class, GroupManagementEventListener::class);
|
||||
$context->registerEventListener(GroupDeletedEvent::class, GroupManagementEventListener::class);
|
||||
|
||||
// Sharing events
|
||||
$context->registerEventListener(ShareCreatedEvent::class, SharingEventListener::class);
|
||||
$context->registerEventListener(ShareDeletedEvent::class, SharingEventListener::class);
|
||||
|
||||
// Auth events
|
||||
$context->registerEventListener(BeforeUserLoggedInEvent::class, AuthEventListener::class);
|
||||
$context->registerEventListener(UserLoggedInWithCookieEvent::class, AuthEventListener::class);
|
||||
$context->registerEventListener(UserLoggedInEvent::class, AuthEventListener::class);
|
||||
$context->registerEventListener(BeforeUserLoggedOutEvent::class, AuthEventListener::class);
|
||||
|
||||
// File events
|
||||
$context->registerEventListener(BeforePreviewFetchedEvent::class, FileEventListener::class);
|
||||
|
||||
// Security events
|
||||
$context->registerEventListener(TwoFactorProviderChallengePassed::class, SecurityEventListener::class);
|
||||
$context->registerEventListener(TwoFactorProviderChallengeFailed::class, SecurityEventListener::class);
|
||||
|
||||
// App management events
|
||||
$context->registerEventListener(AppEnableEvent::class, AppManagementEventListener::class);
|
||||
$context->registerEventListener(AppDisableEvent::class, AppManagementEventListener::class);
|
||||
$context->registerEventListener(AppUpdateEvent::class, AppManagementEventListener::class);
|
||||
|
||||
// Console events
|
||||
$context->registerEventListener(ConsoleEvent::class, ConsoleEventListener::class);
|
||||
}
|
||||
|
||||
public function boot(IBootContext $context): void {
|
||||
|
|
@ -75,102 +130,31 @@ class Application extends App implements IBootstrap {
|
|||
* TODO: once the hooks are migrated to lazy events, this should be done
|
||||
* in \OCA\AdminAudit\AppInfo\Application::register
|
||||
*/
|
||||
$this->registerHooks($logger, $context->getServerContainer());
|
||||
$this->registerLegacyHooks($logger, $context->getServerContainer());
|
||||
}
|
||||
|
||||
/**
|
||||
* Register hooks in order to log them
|
||||
*/
|
||||
private function registerHooks(IAuditLogger $logger,
|
||||
ContainerInterface $serverContainer): void {
|
||||
$this->userManagementHooks($logger, $serverContainer->get(IUserSession::class));
|
||||
$this->groupHooks($logger, $serverContainer->get(IGroupManager::class));
|
||||
$this->authHooks($logger);
|
||||
|
||||
|
||||
private function registerLegacyHooks(IAuditLogger $logger, ContainerInterface $serverContainer): void {
|
||||
/** @var IEventDispatcher $eventDispatcher */
|
||||
$eventDispatcher = $serverContainer->get(IEventDispatcher::class);
|
||||
$this->consoleHooks($logger, $eventDispatcher);
|
||||
$this->appHooks($logger, $eventDispatcher);
|
||||
|
||||
$this->sharingHooks($logger);
|
||||
|
||||
$this->sharingLegacyHooks($logger);
|
||||
$this->fileHooks($logger, $eventDispatcher);
|
||||
$this->trashbinHooks($logger);
|
||||
$this->versionsHooks($logger);
|
||||
|
||||
$this->securityHooks($logger, $eventDispatcher);
|
||||
$this->tagHooks($logger, $eventDispatcher);
|
||||
}
|
||||
|
||||
private function userManagementHooks(IAuditLogger $logger,
|
||||
IUserSession $userSession): void {
|
||||
$userActions = new UserManagement($logger);
|
||||
|
||||
Util::connectHook('OC_User', 'post_createUser', $userActions, 'create');
|
||||
Util::connectHook('OC_User', 'post_deleteUser', $userActions, 'delete');
|
||||
Util::connectHook('OC_User', 'changeUser', $userActions, 'change');
|
||||
|
||||
assert($userSession instanceof UserSession);
|
||||
$userSession->listen('\OC\User', 'postSetPassword', [$userActions, 'setPassword']);
|
||||
$userSession->listen('\OC\User', 'assignedUserId', [$userActions, 'assign']);
|
||||
$userSession->listen('\OC\User', 'postUnassignedUserId', [$userActions, 'unassign']);
|
||||
}
|
||||
|
||||
private function groupHooks(IAuditLogger $logger,
|
||||
IGroupManager $groupManager): void {
|
||||
$groupActions = new GroupManagement($logger);
|
||||
|
||||
assert($groupManager instanceof GroupManager);
|
||||
$groupManager->listen('\OC\Group', 'postRemoveUser', [$groupActions, 'removeUser']);
|
||||
$groupManager->listen('\OC\Group', 'postAddUser', [$groupActions, 'addUser']);
|
||||
$groupManager->listen('\OC\Group', 'postDelete', [$groupActions, 'deleteGroup']);
|
||||
$groupManager->listen('\OC\Group', 'postCreate', [$groupActions, 'createGroup']);
|
||||
}
|
||||
|
||||
private function sharingHooks(IAuditLogger $logger): void {
|
||||
private function sharingLegacyHooks(IAuditLogger $logger): void {
|
||||
$shareActions = new Sharing($logger);
|
||||
|
||||
Util::connectHook(Share::class, 'post_shared', $shareActions, 'shared');
|
||||
Util::connectHook(Share::class, 'post_unshare', $shareActions, 'unshare');
|
||||
Util::connectHook(Share::class, 'post_unshareFromSelf', $shareActions, 'unshare');
|
||||
Util::connectHook(Share::class, 'post_update_permissions', $shareActions, 'updatePermissions');
|
||||
Util::connectHook(Share::class, 'post_update_password', $shareActions, 'updatePassword');
|
||||
Util::connectHook(Share::class, 'post_set_expiration_date', $shareActions, 'updateExpirationDate');
|
||||
Util::connectHook(Share::class, 'share_link_access', $shareActions, 'shareAccessed');
|
||||
}
|
||||
|
||||
private function authHooks(IAuditLogger $logger): void {
|
||||
$authActions = new Auth($logger);
|
||||
|
||||
Util::connectHook('OC_User', 'pre_login', $authActions, 'loginAttempt');
|
||||
Util::connectHook('OC_User', 'post_login', $authActions, 'loginSuccessful');
|
||||
Util::connectHook('OC_User', 'logout', $authActions, 'logout');
|
||||
}
|
||||
|
||||
private function appHooks(IAuditLogger $logger,
|
||||
IEventDispatcher $eventDispatcher): void {
|
||||
$eventDispatcher->addListener(ManagerEvent::EVENT_APP_ENABLE, function (ManagerEvent $event) use ($logger) {
|
||||
$appActions = new AppManagement($logger);
|
||||
$appActions->enableApp($event->getAppID());
|
||||
});
|
||||
$eventDispatcher->addListener(ManagerEvent::EVENT_APP_ENABLE_FOR_GROUPS, function (ManagerEvent $event) use ($logger) {
|
||||
$appActions = new AppManagement($logger);
|
||||
$appActions->enableAppForGroups($event->getAppID(), $event->getGroups());
|
||||
});
|
||||
$eventDispatcher->addListener(ManagerEvent::EVENT_APP_DISABLE, function (ManagerEvent $event) use ($logger) {
|
||||
$appActions = new AppManagement($logger);
|
||||
$appActions->disableApp($event->getAppID());
|
||||
});
|
||||
}
|
||||
|
||||
private function consoleHooks(IAuditLogger $logger,
|
||||
IEventDispatcher $eventDispatcher): void {
|
||||
$eventDispatcher->addListener(ConsoleEvent::class, function (ConsoleEvent $event) use ($logger) {
|
||||
$appActions = new Console($logger);
|
||||
$appActions->runCommand($event->getArguments());
|
||||
});
|
||||
}
|
||||
private function tagHooks(IAuditLogger $logger,
|
||||
IEventDispatcher $eventDispatcher): void {
|
||||
$eventDispatcher->addListener(\OCP\SystemTag\ManagerEvent::EVENT_CREATE, function (\OCP\SystemTag\ManagerEvent $event) use ($logger) {
|
||||
|
|
@ -179,15 +163,8 @@ class Application extends App implements IBootstrap {
|
|||
});
|
||||
}
|
||||
|
||||
private function fileHooks(IAuditLogger $logger,
|
||||
IEventDispatcher $eventDispatcher): void {
|
||||
private function fileHooks(IAuditLogger $logger, IEventDispatcher $eventDispatcher): void {
|
||||
$fileActions = new Files($logger);
|
||||
$eventDispatcher->addListener(
|
||||
BeforePreviewFetchedEvent::class,
|
||||
function (BeforePreviewFetchedEvent $event) use ($fileActions) {
|
||||
$fileActions->preview($event);
|
||||
}
|
||||
);
|
||||
|
||||
$eventDispatcher->addListener(
|
||||
BeforeNodeRenamedEvent::class,
|
||||
|
|
@ -257,16 +234,4 @@ class Application extends App implements IBootstrap {
|
|||
Util::connectHook('\OCP\Trashbin', 'preDelete', $trashActions, 'delete');
|
||||
Util::connectHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', $trashActions, 'restore');
|
||||
}
|
||||
|
||||
private function securityHooks(IAuditLogger $logger,
|
||||
IEventDispatcher $eventDispatcher): void {
|
||||
$eventDispatcher->addListener(TwoFactorProviderChallengePassed::class, function (TwoFactorProviderChallengePassed $event) use ($logger) {
|
||||
$security = new Security($logger);
|
||||
$security->twofactorSuccess($event->getUser(), $event->getProvider());
|
||||
});
|
||||
$eventDispatcher->addListener(TwoFactorProviderChallengeFailed::class, function (TwoFactorProviderChallengeFailed $event) use ($logger) {
|
||||
$security = new Security($logger);
|
||||
$security->twofactorFailed($event->getUser(), $event->getProvider());
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,12 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2022 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\AdminAudit;
|
||||
|
||||
use OCP\IConfig;
|
||||
|
|
|
|||
60
apps/admin_audit/lib/Listener/AppManagementEventListener.php
Normal file
60
apps/admin_audit/lib/Listener/AppManagementEventListener.php
Normal file
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\AdminAudit\Listener;
|
||||
|
||||
use OCA\AdminAudit\Actions\Action;
|
||||
use OCP\App\Events\AppDisableEvent;
|
||||
use OCP\App\Events\AppEnableEvent;
|
||||
use OCP\App\Events\AppUpdateEvent;
|
||||
use OCP\EventDispatcher\Event;
|
||||
use OCP\EventDispatcher\IEventListener;
|
||||
|
||||
/**
|
||||
* @template-implements IEventListener<AppEnableEvent|AppDisableEvent|AppUpdateEvent>
|
||||
*/
|
||||
class AppManagementEventListener extends Action implements IEventListener {
|
||||
public function handle(Event $event): void {
|
||||
if ($event instanceof AppEnableEvent) {
|
||||
$this->appEnable($event);
|
||||
} elseif ($event instanceof AppDisableEvent) {
|
||||
$this->appDisable($event);
|
||||
} elseif ($event instanceof AppUpdateEvent) {
|
||||
$this->appUpdate($event);
|
||||
}
|
||||
}
|
||||
|
||||
private function appEnable(AppEnableEvent $event): void {
|
||||
if (empty($event->getGroupIds())) {
|
||||
$this->log('App "%s" enabled',
|
||||
['app' => $event->getAppId()],
|
||||
['app']
|
||||
);
|
||||
} else {
|
||||
$this->log('App "%1$s" enabled for groups: %2$s',
|
||||
['app' => $event->getAppId(), 'groups' => implode(', ', $event->getGroupIds())],
|
||||
['app', 'groups']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private function appDisable(AppDisableEvent $event): void {
|
||||
$this->log('App "%s" disabled',
|
||||
['app' => $event->getAppId()],
|
||||
['app']
|
||||
);
|
||||
}
|
||||
|
||||
private function appUpdate(AppUpdateEvent $event): void {
|
||||
$this->log('App "%s" updated',
|
||||
['app' => $event->getAppId()],
|
||||
['app']
|
||||
);
|
||||
}
|
||||
}
|
||||
67
apps/admin_audit/lib/Listener/AuthEventListener.php
Normal file
67
apps/admin_audit/lib/Listener/AuthEventListener.php
Normal file
|
|
@ -0,0 +1,67 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\AdminAudit\Listener;
|
||||
|
||||
use OCA\AdminAudit\Actions\Action;
|
||||
use OCP\EventDispatcher\Event;
|
||||
use OCP\EventDispatcher\IEventListener;
|
||||
use OCP\User\Events\BeforeUserLoggedInEvent;
|
||||
use OCP\User\Events\BeforeUserLoggedOutEvent;
|
||||
use OCP\User\Events\UserLoggedInEvent;
|
||||
use OCP\User\Events\UserLoggedInWithCookieEvent;
|
||||
|
||||
/**
|
||||
* @template-implements IEventListener<BeforeUserLoggedInEvent|UserLoggedInWithCookieEvent|UserLoggedInEvent|BeforeUserLoggedOutEvent>
|
||||
*/
|
||||
class AuthEventListener extends Action implements IEventListener {
|
||||
public function handle(Event $event): void {
|
||||
if ($event instanceof BeforeUserLoggedInEvent) {
|
||||
$this->beforeUserLoggedIn($event);
|
||||
} elseif ($event instanceof UserLoggedInWithCookieEvent || $event instanceof UserLoggedInEvent) {
|
||||
$this->userLoggedIn($event);
|
||||
} elseif ($event instanceof BeforeUserLoggedOutEvent) {
|
||||
$this->beforeUserLogout($event);
|
||||
}
|
||||
}
|
||||
|
||||
private function beforeUserLoggedIn(BeforeUserLoggedInEvent $event): void {
|
||||
$this->log(
|
||||
'Login attempt: "%s"',
|
||||
[
|
||||
'uid' => $event->getUsername()
|
||||
],
|
||||
[
|
||||
'uid',
|
||||
],
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
private function userLoggedIn(UserLoggedInWithCookieEvent|UserLoggedInEvent $event): void {
|
||||
$this->log(
|
||||
'Login successful: "%s"',
|
||||
[
|
||||
'uid' => $event->getUser()->getUID()
|
||||
],
|
||||
[
|
||||
'uid',
|
||||
],
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
private function beforeUserLogout(BeforeUserLoggedOutEvent $event): void {
|
||||
$this->log(
|
||||
'Logout occurred',
|
||||
[],
|
||||
[]
|
||||
);
|
||||
}
|
||||
}
|
||||
42
apps/admin_audit/lib/Listener/ConsoleEventListener.php
Normal file
42
apps/admin_audit/lib/Listener/ConsoleEventListener.php
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\AdminAudit\Listener;
|
||||
|
||||
use OCA\AdminAudit\Actions\Action;
|
||||
use OCP\Console\ConsoleEvent;
|
||||
use OCP\EventDispatcher\Event;
|
||||
use OCP\EventDispatcher\IEventListener;
|
||||
|
||||
/**
|
||||
* @template-implements IEventListener<ConsoleEvent>
|
||||
*/
|
||||
class ConsoleEventListener extends Action implements IEventListener {
|
||||
public function handle(Event $event): void {
|
||||
if ($event instanceof ConsoleEvent) {
|
||||
$this->runCommand($event);
|
||||
}
|
||||
}
|
||||
|
||||
private function runCommand(ConsoleEvent $event): void {
|
||||
$arguments = $event->getArguments();
|
||||
if (!isset($arguments[1]) || $arguments[1] === '_completion') {
|
||||
// Don't log autocompletion
|
||||
return;
|
||||
}
|
||||
|
||||
// Remove `./occ`
|
||||
array_shift($arguments);
|
||||
|
||||
$this->log('Console command executed: %s',
|
||||
['arguments' => implode(' ', $arguments)],
|
||||
['arguments']
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +1,12 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2021 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\AdminAudit\Listener;
|
||||
|
||||
use OCA\AdminAudit\Actions\Action;
|
||||
|
|
|
|||
56
apps/admin_audit/lib/Listener/FileEventListener.php
Normal file
56
apps/admin_audit/lib/Listener/FileEventListener.php
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\AdminAudit\Listener;
|
||||
|
||||
use OCA\AdminAudit\Actions\Action;
|
||||
use OCP\EventDispatcher\Event;
|
||||
use OCP\EventDispatcher\IEventListener;
|
||||
use OCP\Files\InvalidPathException;
|
||||
use OCP\Files\NotFoundException;
|
||||
use OCP\Preview\BeforePreviewFetchedEvent;
|
||||
use Psr\Log\LoggerInterface;
|
||||
|
||||
/**
|
||||
* @template-implements IEventListener<BeforePreviewFetchedEvent>
|
||||
*/
|
||||
class FileEventListener extends Action implements IEventListener {
|
||||
public function handle(Event $event): void {
|
||||
if ($event instanceof BeforePreviewFetchedEvent) {
|
||||
$this->beforePreviewFetched($event);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs preview access to a file
|
||||
*/
|
||||
private function beforePreviewFetched(BeforePreviewFetchedEvent $event): void {
|
||||
try {
|
||||
$file = $event->getNode();
|
||||
$params = [
|
||||
'id' => $file->getId(),
|
||||
'width' => $event->getWidth(),
|
||||
'height' => $event->getHeight(),
|
||||
'crop' => $event->isCrop(),
|
||||
'mode' => $event->getMode(),
|
||||
'path' => mb_substr($file->getInternalPath(), 5)
|
||||
];
|
||||
$this->log(
|
||||
'Preview accessed: (id: "%s", width: "%s", height: "%s" crop: "%s", mode: "%s", path: "%s")',
|
||||
$params,
|
||||
array_keys($params)
|
||||
);
|
||||
} catch (InvalidPathException|NotFoundException $e) {
|
||||
\OCP\Server::get(LoggerInterface::class)->error(
|
||||
'Exception thrown in file preview: '.$e->getMessage(), ['app' => 'admin_audit', 'exception' => $e]
|
||||
);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\AdminAudit\Listener;
|
||||
|
||||
use OCA\AdminAudit\Actions\Action;
|
||||
use OCP\EventDispatcher\Event;
|
||||
use OCP\EventDispatcher\IEventListener;
|
||||
use OCP\Group\Events\GroupCreatedEvent;
|
||||
use OCP\Group\Events\GroupDeletedEvent;
|
||||
use OCP\Group\Events\UserAddedEvent;
|
||||
use OCP\Group\Events\UserRemovedEvent;
|
||||
|
||||
/**
|
||||
* @template-implements IEventListener<UserAddedEvent|UserRemovedEvent|GroupCreatedEvent|GroupDeletedEvent>
|
||||
*/
|
||||
class GroupManagementEventListener extends Action implements IEventListener {
|
||||
public function handle(Event $event): void {
|
||||
if ($event instanceof UserAddedEvent) {
|
||||
$this->userAdded($event);
|
||||
} elseif ($event instanceof UserRemovedEvent) {
|
||||
$this->userRemoved($event);
|
||||
} elseif ($event instanceof GroupCreatedEvent) {
|
||||
$this->groupCreated($event);
|
||||
} elseif ($event instanceof GroupDeletedEvent) {
|
||||
$this->groupDeleted($event);
|
||||
}
|
||||
}
|
||||
|
||||
private function userAdded(UserAddedEvent $event): void {
|
||||
$this->log('User "%s" added to group "%s"',
|
||||
[
|
||||
'group' => $event->getGroup()->getGID(),
|
||||
'user' => $event->getUser()->getUID()
|
||||
],
|
||||
[
|
||||
'user', 'group'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
private function userRemoved(UserRemovedEvent $event): void {
|
||||
$this->log('User "%s" removed from group "%s"',
|
||||
[
|
||||
'group' => $event->getGroup()->getGID(),
|
||||
'user' => $event->getUser()->getUID()
|
||||
],
|
||||
[
|
||||
'user', 'group'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
private function groupCreated(GroupCreatedEvent $event): void {
|
||||
$this->log('Group created: "%s"',
|
||||
[
|
||||
'group' => $event->getGroup()->getGID()
|
||||
],
|
||||
[
|
||||
'group'
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
private function groupDeleted(GroupDeletedEvent $event): void {
|
||||
$this->log('Group deleted: "%s"',
|
||||
[
|
||||
'group' => $event->getGroup()->getGID()
|
||||
],
|
||||
[
|
||||
'group'
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
61
apps/admin_audit/lib/Listener/SecurityEventListener.php
Normal file
61
apps/admin_audit/lib/Listener/SecurityEventListener.php
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\AdminAudit\Listener;
|
||||
|
||||
use OCA\AdminAudit\Actions\Action;
|
||||
use OCP\Authentication\TwoFactorAuth\TwoFactorProviderChallengeFailed;
|
||||
use OCP\Authentication\TwoFactorAuth\TwoFactorProviderChallengePassed;
|
||||
use OCP\EventDispatcher\Event;
|
||||
use OCP\EventDispatcher\IEventListener;
|
||||
|
||||
/**
|
||||
* @template-implements IEventListener<TwoFactorProviderChallengePassed|TwoFactorProviderChallengeFailed>
|
||||
*/
|
||||
class SecurityEventListener extends Action implements IEventListener {
|
||||
public function handle(Event $event): void {
|
||||
if ($event instanceof TwoFactorProviderChallengePassed) {
|
||||
$this->twoFactorProviderChallengePassed($event);
|
||||
} elseif ($event instanceof TwoFactorProviderChallengeFailed) {
|
||||
$this->twoFactorProviderChallengeFailed($event);
|
||||
}
|
||||
}
|
||||
|
||||
private function twoFactorProviderChallengePassed(TwoFactorProviderChallengePassed $event): void {
|
||||
$this->log(
|
||||
'Successful two factor attempt by user %s (%s) with provider %s',
|
||||
[
|
||||
'uid' => $event->getUser()->getUID(),
|
||||
'displayName' => $event->getUser()->getDisplayName(),
|
||||
'provider' => $event->getProvider()->getDisplayName()
|
||||
],
|
||||
[
|
||||
'displayName',
|
||||
'uid',
|
||||
'provider',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
private function twoFactorProviderChallengeFailed(TwoFactorProviderChallengeFailed $event): void {
|
||||
$this->log(
|
||||
'Failed two factor attempt by user %s (%s) with provider %s',
|
||||
[
|
||||
'uid' => $event->getUser()->getUID(),
|
||||
'displayName' => $event->getUser()->getDisplayName(),
|
||||
'provider' => $event->getProvider()->getDisplayName()
|
||||
],
|
||||
[
|
||||
'displayName',
|
||||
'uid',
|
||||
'provider',
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
291
apps/admin_audit/lib/Listener/SharingEventListener.php
Normal file
291
apps/admin_audit/lib/Listener/SharingEventListener.php
Normal file
|
|
@ -0,0 +1,291 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\AdminAudit\Listener;
|
||||
|
||||
use OCA\AdminAudit\Actions\Action;
|
||||
use OCP\EventDispatcher\Event;
|
||||
use OCP\EventDispatcher\IEventListener;
|
||||
use OCP\Share\Events\ShareCreatedEvent;
|
||||
use OCP\Share\Events\ShareDeletedEvent;
|
||||
use OCP\Share\IShare;
|
||||
|
||||
/**
|
||||
* @template-implements IEventListener<ShareCreatedEvent|ShareDeletedEvent>
|
||||
*/
|
||||
class SharingEventListener extends Action implements IEventListener {
|
||||
public function handle(Event $event): void {
|
||||
if ($event instanceof ShareCreatedEvent) {
|
||||
$this->shareCreated($event);
|
||||
} elseif ($event instanceof ShareDeletedEvent) {
|
||||
$this->shareDeleted($event);
|
||||
}
|
||||
}
|
||||
|
||||
private function shareCreated(ShareCreatedEvent $event): void {
|
||||
$share = $event->getShare();
|
||||
|
||||
$params = [
|
||||
'itemType' => $share->getNodeType(),
|
||||
'path' => $share->getNode()->getPath(),
|
||||
'itemSource' => $share->getNodeId(),
|
||||
'shareWith' => $share->getSharedWith(),
|
||||
'permissions' => $share->getPermissions(),
|
||||
'id' => $share->getId()
|
||||
];
|
||||
|
||||
match ($share->getShareType()) {
|
||||
IShare::TYPE_LINK => $this->log(
|
||||
'The %s "%s" with ID "%s" has been shared via link with permissions "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'path',
|
||||
'itemSource',
|
||||
'permissions',
|
||||
'id',
|
||||
]
|
||||
),
|
||||
IShare::TYPE_USER => $this->log(
|
||||
'The %s "%s" with ID "%s" has been shared to the user "%s" with permissions "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'path',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'permissions',
|
||||
'id',
|
||||
]
|
||||
),
|
||||
IShare::TYPE_GROUP => $this->log(
|
||||
'The %s "%s" with ID "%s" has been shared to the group "%s" with permissions "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'path',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'permissions',
|
||||
'id',
|
||||
]
|
||||
),
|
||||
IShare::TYPE_ROOM => $this->log(
|
||||
'The %s "%s" with ID "%s" has been shared to the room "%s" with permissions "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'path',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'permissions',
|
||||
'id',
|
||||
]
|
||||
),
|
||||
IShare::TYPE_EMAIL => $this->log(
|
||||
'The %s "%s" with ID "%s" has been shared to the email recipient "%s" with permissions "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'path',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'permissions',
|
||||
'id',
|
||||
]
|
||||
),
|
||||
IShare::TYPE_CIRCLE => $this->log(
|
||||
'The %s "%s" with ID "%s" has been shared to the circle "%s" with permissions "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'path',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'permissions',
|
||||
'id',
|
||||
]
|
||||
),
|
||||
IShare::TYPE_REMOTE => $this->log(
|
||||
'The %s "%s" with ID "%s" has been shared to the remote user "%s" with permissions "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'path',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'permissions',
|
||||
'id',
|
||||
]
|
||||
),
|
||||
IShare::TYPE_REMOTE_GROUP => $this->log(
|
||||
'The %s "%s" with ID "%s" has been shared to the remote group "%s" with permissions "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'path',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'permissions',
|
||||
'id',
|
||||
]
|
||||
),
|
||||
IShare::TYPE_DECK => $this->log(
|
||||
'The %s "%s" with ID "%s" has been shared to the deck card "%s" with permissions "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'path',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'permissions',
|
||||
'id',
|
||||
]
|
||||
),
|
||||
IShare::TYPE_SCIENCEMESH => $this->log(
|
||||
'The %s "%s" with ID "%s" has been shared to the sciencemesh user "%s" with permissions "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'path',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'permissions',
|
||||
'id',
|
||||
]
|
||||
),
|
||||
default => null
|
||||
};
|
||||
}
|
||||
|
||||
private function shareDeleted(ShareDeletedEvent $event): void {
|
||||
$share = $event->getShare();
|
||||
|
||||
$params = [
|
||||
'itemType' => $share->getNodeType(),
|
||||
'fileTarget' => $share->getTarget(),
|
||||
'itemSource' => $share->getNodeId(),
|
||||
'shareWith' => $share->getSharedWith(),
|
||||
'id' => $share->getId()
|
||||
];
|
||||
|
||||
match ($share->getShareType()) {
|
||||
IShare::TYPE_LINK => $this->log(
|
||||
'The %s "%s" with ID "%s" has been unshared (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'fileTarget',
|
||||
'itemSource',
|
||||
'id',
|
||||
]
|
||||
),
|
||||
IShare::TYPE_USER => $this->log(
|
||||
'The %s "%s" with ID "%s" has been unshared from the user "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'fileTarget',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'id',
|
||||
]
|
||||
),
|
||||
IShare::TYPE_GROUP => $this->log(
|
||||
'The %s "%s" with ID "%s" has been unshared from the group "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'fileTarget',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'id',
|
||||
]
|
||||
),
|
||||
IShare::TYPE_ROOM => $this->log(
|
||||
'The %s "%s" with ID "%s" has been unshared from the room "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'fileTarget',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'id',
|
||||
]
|
||||
),
|
||||
IShare::TYPE_EMAIL => $this->log(
|
||||
'The %s "%s" with ID "%s" has been unshared from the email recipient "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'fileTarget',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'id',
|
||||
]
|
||||
),
|
||||
IShare::TYPE_CIRCLE => $this->log(
|
||||
'The %s "%s" with ID "%s" has been unshared from the circle "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'fileTarget',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'id',
|
||||
]
|
||||
),
|
||||
IShare::TYPE_REMOTE => $this->log(
|
||||
'The %s "%s" with ID "%s" has been unshared from the remote user "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'fileTarget',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'id',
|
||||
]
|
||||
),
|
||||
IShare::TYPE_REMOTE_GROUP => $this->log(
|
||||
'The %s "%s" with ID "%s" has been unshared from the remote group "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'fileTarget',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'id',
|
||||
]
|
||||
),
|
||||
IShare::TYPE_DECK => $this->log(
|
||||
'The %s "%s" with ID "%s" has been unshared from the deck card "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'fileTarget',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'id',
|
||||
]
|
||||
),
|
||||
IShare::TYPE_SCIENCEMESH => $this->log(
|
||||
'The %s "%s" with ID "%s" has been unshared from the sciencemesh user "%s" (Share ID: %s)',
|
||||
$params,
|
||||
[
|
||||
'itemType',
|
||||
'fileTarget',
|
||||
'itemSource',
|
||||
'shareWith',
|
||||
'id',
|
||||
]
|
||||
),
|
||||
default => null
|
||||
};
|
||||
}
|
||||
}
|
||||
126
apps/admin_audit/lib/Listener/UserManagementEventListener.php
Normal file
126
apps/admin_audit/lib/Listener/UserManagementEventListener.php
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\AdminAudit\Listener;
|
||||
|
||||
use OCA\AdminAudit\Actions\Action;
|
||||
use OCP\EventDispatcher\Event;
|
||||
use OCP\EventDispatcher\IEventListener;
|
||||
use OCP\User\Events\PasswordUpdatedEvent;
|
||||
use OCP\User\Events\UserChangedEvent;
|
||||
use OCP\User\Events\UserCreatedEvent;
|
||||
use OCP\User\Events\UserDeletedEvent;
|
||||
use OCP\User\Events\UserIdAssignedEvent;
|
||||
use OCP\User\Events\UserIdUnassignedEvent;
|
||||
|
||||
/**
|
||||
* @template-implements IEventListener<UserCreatedEvent|UserDeletedEvent|UserChangedEvent|PasswordUpdatedEvent|UserIdAssignedEvent|UserIdUnassignedEvent>
|
||||
*/
|
||||
class UserManagementEventListener extends Action implements IEventListener {
|
||||
public function handle(Event $event): void {
|
||||
if ($event instanceof UserCreatedEvent) {
|
||||
$this->userCreated($event);
|
||||
} elseif ($event instanceof UserDeletedEvent) {
|
||||
$this->userDeleted($event);
|
||||
} elseif ($event instanceof UserChangedEvent) {
|
||||
$this->userChanged($event);
|
||||
} elseif ($event instanceof PasswordUpdatedEvent) {
|
||||
$this->passwordUpdated($event);
|
||||
} elseif ($event instanceof UserIdAssignedEvent) {
|
||||
$this->userIdAssigned($event);
|
||||
} elseif ($event instanceof UserIdUnassignedEvent) {
|
||||
$this->userIdUnassigned($event);
|
||||
}
|
||||
}
|
||||
|
||||
private function userCreated(UserCreatedEvent $event): void {
|
||||
$this->log(
|
||||
'User created: "%s"',
|
||||
[
|
||||
'uid' => $event->getUid()
|
||||
],
|
||||
[
|
||||
'uid',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
private function userDeleted(UserDeletedEvent $event): void {
|
||||
$this->log(
|
||||
'User deleted: "%s"',
|
||||
[
|
||||
'uid' => $event->getUser()->getUID()
|
||||
],
|
||||
[
|
||||
'uid',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
private function userChanged(UserChangedEvent $event): void {
|
||||
switch ($event->getFeature()) {
|
||||
case 'enabled':
|
||||
$this->log(
|
||||
$event->getValue() === true
|
||||
? 'User enabled: "%s"'
|
||||
: 'User disabled: "%s"',
|
||||
['user' => $event->getUser()->getUID()],
|
||||
[
|
||||
'user',
|
||||
]
|
||||
);
|
||||
break;
|
||||
case 'eMailAddress':
|
||||
$this->log(
|
||||
'Email address changed for user %s',
|
||||
['user' => $event->getUser()->getUID()],
|
||||
[
|
||||
'user',
|
||||
]
|
||||
);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private function passwordUpdated(PasswordUpdatedEvent $event): void {
|
||||
if ($event->getUser()->getBackendClassName() === 'Database') {
|
||||
$this->log(
|
||||
'Password of user "%s" has been changed',
|
||||
[
|
||||
'user' => $event->getUser()->getUID(),
|
||||
],
|
||||
[
|
||||
'user',
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log assignments of users (typically user backends)
|
||||
*/
|
||||
private function userIdAssigned(UserIdAssignedEvent $event): void {
|
||||
$this->log(
|
||||
'UserID assigned: "%s"',
|
||||
[ 'uid' => $event->getUserId() ],
|
||||
[ 'uid' ]
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log unassignments of users (typically user backends, no data removed)
|
||||
*/
|
||||
private function userIdUnassigned(UserIdUnassignedEvent $event): void {
|
||||
$this->log(
|
||||
'UserID unassigned: "%s"',
|
||||
[ 'uid' => $event->getUserId() ],
|
||||
[ 'uid' ]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,38 +1,47 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2018 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
namespace OCA\AdminAudit\Tests\Actions;
|
||||
|
||||
use OCA\AdminAudit\Actions\Security;
|
||||
namespace OCA\AdminAudit\Tests\Listener;
|
||||
|
||||
use OCA\AdminAudit\AuditLogger;
|
||||
use OCA\AdminAudit\Listener\SecurityEventListener;
|
||||
use OCP\Authentication\TwoFactorAuth\IProvider;
|
||||
use OCP\Authentication\TwoFactorAuth\TwoFactorProviderChallengeFailed;
|
||||
use OCP\Authentication\TwoFactorAuth\TwoFactorProviderChallengePassed;
|
||||
use OCP\IUser;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Test\TestCase;
|
||||
|
||||
class SecurityTest extends TestCase {
|
||||
class SecurityEventListenerTest extends TestCase {
|
||||
private AuditLogger|MockObject $logger;
|
||||
|
||||
private Security $security;
|
||||
private SecurityEventListener $security;
|
||||
|
||||
private MockObject|IUser $user;
|
||||
|
||||
/** @var IProvider&MockObject */
|
||||
private $provider;
|
||||
|
||||
protected function setUp(): void {
|
||||
parent::setUp();
|
||||
|
||||
$this->logger = $this->createMock(AuditLogger::class);
|
||||
$this->security = new Security($this->logger);
|
||||
$this->security = new SecurityEventListener($this->logger);
|
||||
|
||||
$this->user = $this->createMock(IUser::class);
|
||||
$this->user->method('getUID')->willReturn('myuid');
|
||||
$this->user->method('getDisplayName')->willReturn('mydisplayname');
|
||||
$this->provider = $this->createMock(IProvider::class);
|
||||
$this->provider->method('getDisplayName')->willReturn('myprovider');
|
||||
}
|
||||
|
||||
public function testTwofactorFailed() {
|
||||
public function testTwofactorFailed(): void {
|
||||
$this->logger->expects($this->once())
|
||||
->method('info')
|
||||
->with(
|
||||
|
|
@ -40,14 +49,10 @@ class SecurityTest extends TestCase {
|
|||
['app' => 'admin_audit']
|
||||
);
|
||||
|
||||
$provider = $this->createMock(IProvider::class);
|
||||
$provider->method('getDisplayName')
|
||||
->willReturn('myprovider');
|
||||
|
||||
$this->security->twofactorFailed($this->user, $provider);
|
||||
$this->security->handle(new twoFactorProviderChallengeFailed($this->user, $this->provider));
|
||||
}
|
||||
|
||||
public function testTwofactorSuccess() {
|
||||
public function testTwofactorSuccess(): void {
|
||||
$this->logger->expects($this->once())
|
||||
->method('info')
|
||||
->with(
|
||||
|
|
@ -55,10 +60,6 @@ class SecurityTest extends TestCase {
|
|||
['app' => 'admin_audit']
|
||||
);
|
||||
|
||||
$provider = $this->createMock(IProvider::class);
|
||||
$provider->method('getDisplayName')
|
||||
->willReturn('myprovider');
|
||||
|
||||
$this->security->twofactorSuccess($this->user, $provider);
|
||||
$this->security->handle(new TwoFactorProviderChallengePassed($this->user, $this->provider));
|
||||
}
|
||||
}
|
||||
|
|
@ -5,8 +5,13 @@
|
|||
* SPDX-FileCopyrightText: 2016 ownCloud, Inc.
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
use OCA\User_LDAP\Mapping\GroupMapping;
|
||||
use OCA\User_LDAP\Mapping\UserMapping;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\Server;
|
||||
use OCP\User\Events\BeforeUserIdUnassignedEvent;
|
||||
use OCP\User\Events\UserIdUnassignedEvent;
|
||||
|
||||
// Check user and app status
|
||||
\OC_JSON::checkAdminUser();
|
||||
|
|
@ -17,12 +22,16 @@ $subject = (string)$_POST['ldap_clear_mapping'];
|
|||
$mapping = null;
|
||||
try {
|
||||
if ($subject === 'user') {
|
||||
$mapping = \OCP\Server::get(UserMapping::class);
|
||||
$mapping = Server::get(UserMapping::class);
|
||||
/** @var IEventDispatcher $dispatcher */
|
||||
$dispatcher = Server::get(IEventDispatcher::class);
|
||||
$result = $mapping->clearCb(
|
||||
function ($uid) {
|
||||
function (string $uid) use ($dispatcher): void {
|
||||
$dispatcher->dispatchTyped(new BeforeUserIdUnassignedEvent($uid));
|
||||
\OC::$server->getUserManager()->emit('\OC\User', 'preUnassignedUserId', [$uid]);
|
||||
},
|
||||
function ($uid) {
|
||||
function (string $uid) use ($dispatcher): void {
|
||||
$dispatcher->dispatchTyped(new UserIdUnassignedEvent($uid));
|
||||
\OC::$server->getUserManager()->emit('\OC\User', 'postUnassignedUserId', [$uid]);
|
||||
}
|
||||
);
|
||||
|
|
|
|||
|
|
@ -15,10 +15,12 @@ use OCA\User_LDAP\Exceptions\NoMoreResults;
|
|||
use OCA\User_LDAP\Mapping\AbstractMapping;
|
||||
use OCA\User_LDAP\User\Manager;
|
||||
use OCA\User_LDAP\User\OfflineUser;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\HintException;
|
||||
use OCP\IAppConfig;
|
||||
use OCP\IConfig;
|
||||
use OCP\IUserManager;
|
||||
use OCP\User\Events\UserIdAssignedEvent;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use function strlen;
|
||||
use function substr;
|
||||
|
|
@ -42,6 +44,7 @@ class Access extends LDAPUtility {
|
|||
|
||||
/** @var ?AbstractMapping */
|
||||
protected $groupMapper;
|
||||
|
||||
private string $lastCookie = '';
|
||||
|
||||
public function __construct(
|
||||
|
|
@ -53,15 +56,10 @@ class Access extends LDAPUtility {
|
|||
private IUserManager $ncUserManager,
|
||||
private LoggerInterface $logger,
|
||||
private IAppConfig $appConfig,
|
||||
private IEventDispatcher $dispatcher,
|
||||
) {
|
||||
parent::__construct($ldap);
|
||||
$this->connection = $connection;
|
||||
$this->userManager = $userManager;
|
||||
$this->userManager->setLdapAccess($this);
|
||||
$this->helper = $helper;
|
||||
$this->config = $config;
|
||||
$this->ncUserManager = $ncUserManager;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -629,10 +627,13 @@ class Access extends LDAPUtility {
|
|||
bool $isUser
|
||||
): bool {
|
||||
if ($mapper->map($fdn, $name, $uuid)) {
|
||||
if ($this->ncUserManager instanceof PublicEmitter && $isUser) {
|
||||
if ($isUser) {
|
||||
$this->cacheUserExists($name);
|
||||
$this->ncUserManager->emit('\OC\User', 'assignedUserId', [$name]);
|
||||
} elseif (!$isUser) {
|
||||
$this->dispatcher->dispatchTyped(new UserIdAssignedEvent($name));
|
||||
if ($this->ncUserManager instanceof PublicEmitter) {
|
||||
$this->ncUserManager->emit('\OC\User', 'assignedUserId', [$name]);
|
||||
}
|
||||
} else {
|
||||
$this->cacheGroupExists($name);
|
||||
}
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
namespace OCA\User_LDAP;
|
||||
|
||||
use OCA\User_LDAP\User\Manager;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\IAppConfig;
|
||||
use OCP\IConfig;
|
||||
use OCP\IUserManager;
|
||||
|
|
@ -21,12 +22,8 @@ class AccessFactory {
|
|||
private IAppConfig $appConfig,
|
||||
private IUserManager $ncUserManager,
|
||||
private LoggerInterface $logger,
|
||||
private IEventDispatcher $dispatcher,
|
||||
) {
|
||||
$this->ldap = $ldap;
|
||||
$this->helper = $helper;
|
||||
$this->config = $config;
|
||||
$this->ncUserManager = $ncUserManager;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function get(Connection $connection): Access {
|
||||
|
|
@ -40,6 +37,7 @@ class AccessFactory {
|
|||
$this->ncUserManager,
|
||||
$this->logger,
|
||||
$this->appConfig,
|
||||
$this->dispatcher,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2017 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCA\User_LDAP\Jobs;
|
||||
|
||||
use OC\ServerNotAvailableException;
|
||||
|
|
@ -14,6 +16,7 @@ use OCA\User_LDAP\LDAP;
|
|||
use OCA\User_LDAP\Mapping\UserMapping;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\BackgroundJob\TimedJob;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\IAvatarManager;
|
||||
use OCP\IConfig;
|
||||
use OCP\IDBConnection;
|
||||
|
|
@ -24,44 +27,38 @@ use Psr\Log\LoggerInterface;
|
|||
class Sync extends TimedJob {
|
||||
public const MAX_INTERVAL = 12 * 60 * 60; // 12h
|
||||
public const MIN_INTERVAL = 30 * 60; // 30min
|
||||
/** @var Helper */
|
||||
protected $ldapHelper;
|
||||
/** @var LDAP */
|
||||
protected $ldap;
|
||||
/** @var UserMapping */
|
||||
protected $mapper;
|
||||
/** @var IConfig */
|
||||
protected $config;
|
||||
/** @var IAvatarManager */
|
||||
protected $avatarManager;
|
||||
/** @var IDBConnection */
|
||||
protected $dbc;
|
||||
/** @var IUserManager */
|
||||
protected $ncUserManager;
|
||||
/** @var LoggerInterface */
|
||||
protected $logger;
|
||||
/** @var IManager */
|
||||
protected $notificationManager;
|
||||
/** @var ConnectionFactory */
|
||||
protected $connectionFactory;
|
||||
/** @var AccessFactory */
|
||||
protected $accessFactory;
|
||||
|
||||
public function __construct(ITimeFactory $time) {
|
||||
parent::__construct($time);
|
||||
protected LDAP $ldap;
|
||||
|
||||
public function __construct(
|
||||
ITimeFactory $timeFactory,
|
||||
private IEventDispatcher $dispatcher,
|
||||
private IConfig $config,
|
||||
private IDBConnection $dbc,
|
||||
private IAvatarManager $avatarManager,
|
||||
private IUserManager $ncUserManager,
|
||||
private LoggerInterface $logger,
|
||||
private IManager $notificationManager,
|
||||
private UserMapping $mapper,
|
||||
private Helper $ldapHelper,
|
||||
private ConnectionFactory $connectionFactory,
|
||||
private AccessFactory $accessFactory,
|
||||
) {
|
||||
parent::__construct($timeFactory);
|
||||
$this->setInterval(
|
||||
(int)\OC::$server->getConfig()->getAppValue(
|
||||
(int)$this->config->getAppValue(
|
||||
'user_ldap',
|
||||
'background_sync_interval',
|
||||
(string)self::MIN_INTERVAL
|
||||
)
|
||||
);
|
||||
$this->ldap = new LDAP($this->config->getSystemValueString('ldap_log_file'));
|
||||
}
|
||||
|
||||
/**
|
||||
* updates the interval
|
||||
* Updates the interval
|
||||
*
|
||||
* the idea is to adjust the interval depending on the amount of known users
|
||||
* The idea is to adjust the interval depending on the amount of known users
|
||||
* and the attempt to update each user one day. At most it would run every
|
||||
* 30 minutes, and at least every 12 hours.
|
||||
*/
|
||||
|
|
@ -79,9 +76,8 @@ class Sync extends TimedJob {
|
|||
|
||||
/**
|
||||
* returns the smallest configured paging size
|
||||
* @return int
|
||||
*/
|
||||
protected function getMinPagingSize() {
|
||||
protected function getMinPagingSize(): int {
|
||||
$configKeys = $this->config->getAppKeys('user_ldap');
|
||||
$configKeys = array_filter($configKeys, function ($key) {
|
||||
return str_contains($key, 'ldap_paging_size');
|
||||
|
|
@ -98,8 +94,6 @@ class Sync extends TimedJob {
|
|||
* @param array $argument
|
||||
*/
|
||||
public function run($argument) {
|
||||
$this->setArgument($argument);
|
||||
|
||||
$isBackgroundJobModeAjax = $this->config
|
||||
->getAppValue('core', 'backgroundjobs_mode', 'ajax') === 'ajax';
|
||||
if ($isBackgroundJobModeAjax) {
|
||||
|
|
@ -134,10 +128,10 @@ class Sync extends TimedJob {
|
|||
}
|
||||
|
||||
/**
|
||||
* @param array $cycleData
|
||||
* @param array{offset: int, prefix: string} $cycleData
|
||||
* @return bool whether more results are expected from the same configuration
|
||||
*/
|
||||
public function runCycle($cycleData) {
|
||||
public function runCycle(array $cycleData): bool {
|
||||
$connection = $this->connectionFactory->get($cycleData['prefix']);
|
||||
$access = $this->accessFactory->get($connection);
|
||||
$access->setUserMapper($this->mapper);
|
||||
|
|
@ -162,24 +156,22 @@ class Sync extends TimedJob {
|
|||
}
|
||||
|
||||
/**
|
||||
* returns the info about the current cycle that should be run, if any,
|
||||
* Returns the info about the current cycle that should be run, if any,
|
||||
* otherwise null
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function getCycle() {
|
||||
public function getCycle(): ?array {
|
||||
$prefixes = $this->ldapHelper->getServerConfigurationPrefixes(true);
|
||||
if (count($prefixes) === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$cycleData = [
|
||||
'prefix' => $this->config->getAppValue('user_ldap', 'background_sync_prefix', null),
|
||||
'prefix' => $this->config->getAppValue('user_ldap', 'background_sync_prefix', 'none'),
|
||||
'offset' => (int)$this->config->getAppValue('user_ldap', 'background_sync_offset', '0'),
|
||||
];
|
||||
|
||||
if (
|
||||
$cycleData['prefix'] !== null
|
||||
$cycleData['prefix'] !== 'none'
|
||||
&& in_array($cycleData['prefix'], $prefixes)
|
||||
) {
|
||||
return $cycleData;
|
||||
|
|
@ -191,21 +183,21 @@ class Sync extends TimedJob {
|
|||
/**
|
||||
* Save the provided cycle information in the DB
|
||||
*
|
||||
* @param array $cycleData
|
||||
* @param array{prefix: ?string, offset: int} $cycleData
|
||||
*/
|
||||
public function setCycle(array $cycleData) {
|
||||
public function setCycle(array $cycleData): void {
|
||||
$this->config->setAppValue('user_ldap', 'background_sync_prefix', $cycleData['prefix']);
|
||||
$this->config->setAppValue('user_ldap', 'background_sync_offset', $cycleData['offset']);
|
||||
$this->config->setAppValue('user_ldap', 'background_sync_offset', (string)$cycleData['offset']);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns data about the next cycle that should run, if any, otherwise
|
||||
* null. It also always goes for the next LDAP configuration!
|
||||
*
|
||||
* @param array|null $cycleData the old cycle
|
||||
* @return array|null
|
||||
* @param ?array{prefix: string, offset: int} $cycleData the old cycle
|
||||
* @return ?array{prefix: string, offset: int}
|
||||
*/
|
||||
public function determineNextCycle(?array $cycleData = null) {
|
||||
public function determineNextCycle(?array $cycleData = null): ?array {
|
||||
$prefixes = $this->ldapHelper->getServerConfigurationPrefixes(true);
|
||||
if (count($prefixes) === 0) {
|
||||
return null;
|
||||
|
|
@ -225,13 +217,12 @@ class Sync extends TimedJob {
|
|||
}
|
||||
|
||||
/**
|
||||
* Checks whether the provided cycle should be run. Currently only the
|
||||
* Checks whether the provided cycle should be run. Currently, only the
|
||||
* last configuration change goes into account (at least one hour).
|
||||
*
|
||||
* @param $cycleData
|
||||
* @return bool
|
||||
* @param array{prefix: string} $cycleData
|
||||
*/
|
||||
public function qualifiesToRun($cycleData) {
|
||||
public function qualifiesToRun(array $cycleData): bool {
|
||||
$lastChange = (int)$this->config->getAppValue('user_ldap', $cycleData['prefix'] . '_lastChange', '0');
|
||||
if ((time() - $lastChange) > 60 * 30) {
|
||||
return true;
|
||||
|
|
@ -240,23 +231,20 @@ class Sync extends TimedJob {
|
|||
}
|
||||
|
||||
/**
|
||||
* increases the offset of the current cycle for the next run
|
||||
* Increases the offset of the current cycle for the next run
|
||||
*
|
||||
* @param $cycleData
|
||||
* @param array{prefix: string, offset: int} $cycleData
|
||||
*/
|
||||
protected function increaseOffset($cycleData) {
|
||||
protected function increaseOffset(array $cycleData): void {
|
||||
$ldapConfig = new Configuration($cycleData['prefix']);
|
||||
$cycleData['offset'] += (int)$ldapConfig->ldapPagingSize;
|
||||
$this->setCycle($cycleData);
|
||||
}
|
||||
|
||||
/**
|
||||
* determines the next configuration prefix based on the last one (if any)
|
||||
*
|
||||
* @param string|null $lastPrefix
|
||||
* @return string|null
|
||||
* Determines the next configuration prefix based on the last one (if any)
|
||||
*/
|
||||
protected function getNextPrefix($lastPrefix) {
|
||||
protected function getNextPrefix(?string $lastPrefix): ?string {
|
||||
$prefixes = $this->ldapHelper->getServerConfigurationPrefixes(true);
|
||||
$noOfPrefixes = count($prefixes);
|
||||
if ($noOfPrefixes === 0) {
|
||||
|
|
@ -276,73 +264,9 @@ class Sync extends TimedJob {
|
|||
}
|
||||
|
||||
/**
|
||||
* "fixes" DI
|
||||
* Only used in tests
|
||||
*/
|
||||
public function setArgument($argument) {
|
||||
if (isset($argument['config'])) {
|
||||
$this->config = $argument['config'];
|
||||
} else {
|
||||
$this->config = \OC::$server->getConfig();
|
||||
}
|
||||
|
||||
if (isset($argument['helper'])) {
|
||||
$this->ldapHelper = $argument['helper'];
|
||||
} else {
|
||||
$this->ldapHelper = new Helper($this->config, \OC::$server->getDatabaseConnection());
|
||||
}
|
||||
|
||||
if (isset($argument['ldapWrapper'])) {
|
||||
$this->ldap = $argument['ldapWrapper'];
|
||||
} else {
|
||||
$this->ldap = new LDAP($this->config->getSystemValueString('ldap_log_file'));
|
||||
}
|
||||
|
||||
if (isset($argument['avatarManager'])) {
|
||||
$this->avatarManager = $argument['avatarManager'];
|
||||
} else {
|
||||
$this->avatarManager = \OC::$server->get(IAvatarManager::class);
|
||||
}
|
||||
|
||||
if (isset($argument['dbc'])) {
|
||||
$this->dbc = $argument['dbc'];
|
||||
} else {
|
||||
$this->dbc = \OC::$server->getDatabaseConnection();
|
||||
}
|
||||
|
||||
if (isset($argument['ncUserManager'])) {
|
||||
$this->ncUserManager = $argument['ncUserManager'];
|
||||
} else {
|
||||
$this->ncUserManager = \OC::$server->getUserManager();
|
||||
}
|
||||
|
||||
if (isset($argument['logger'])) {
|
||||
$this->logger = $argument['logger'];
|
||||
} else {
|
||||
$this->logger = \OC::$server->get(LoggerInterface::class);
|
||||
}
|
||||
|
||||
if (isset($argument['notificationManager'])) {
|
||||
$this->notificationManager = $argument['notificationManager'];
|
||||
} else {
|
||||
$this->notificationManager = \OC::$server->getNotificationManager();
|
||||
}
|
||||
|
||||
if (isset($argument['mapper'])) {
|
||||
$this->mapper = $argument['mapper'];
|
||||
} else {
|
||||
$this->mapper = \OCP\Server::get(UserMapping::class);
|
||||
}
|
||||
|
||||
if (isset($argument['connectionFactory'])) {
|
||||
$this->connectionFactory = $argument['connectionFactory'];
|
||||
} else {
|
||||
$this->connectionFactory = new ConnectionFactory($this->ldap);
|
||||
}
|
||||
|
||||
if (isset($argument['accessFactory'])) {
|
||||
$this->accessFactory = $argument['accessFactory'];
|
||||
} else {
|
||||
$this->accessFactory = \OCP\Server::get(AccessFactory::class);
|
||||
}
|
||||
public function overwritePropertiesForTest(LDAP $ldapWrapper): void {
|
||||
$this->ldap = $ldapWrapper;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ use OCA\User_LDAP\Mapping\UserMapping;
|
|||
use OCA\User_LDAP\User\Manager;
|
||||
use OCA\User_LDAP\User\OfflineUser;
|
||||
use OCA\User_LDAP\User\User;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\IAppConfig;
|
||||
use OCP\IAvatarManager;
|
||||
use OCP\IConfig;
|
||||
|
|
@ -37,29 +38,31 @@ use Test\TestCase;
|
|||
* @package OCA\User_LDAP\Tests
|
||||
*/
|
||||
class AccessTest extends TestCase {
|
||||
/** @var UserMapping|\PHPUnit\Framework\MockObject\MockObject */
|
||||
/** @var UserMapping|MockObject */
|
||||
protected $userMapper;
|
||||
/** @var IManager|\PHPUnit\Framework\MockObject\MockObject */
|
||||
/** @var IManager|MockObject */
|
||||
protected $shareManager;
|
||||
/** @var GroupMapping|\PHPUnit\Framework\MockObject\MockObject */
|
||||
/** @var GroupMapping|MockObject */
|
||||
protected $groupMapper;
|
||||
/** @var Connection|\PHPUnit\Framework\MockObject\MockObject */
|
||||
/** @var Connection|MockObject */
|
||||
private $connection;
|
||||
/** @var LDAP|\PHPUnit\Framework\MockObject\MockObject */
|
||||
/** @var LDAP|MockObject */
|
||||
private $ldap;
|
||||
/** @var Manager|\PHPUnit\Framework\MockObject\MockObject */
|
||||
/** @var Manager|MockObject */
|
||||
private $userManager;
|
||||
/** @var Helper|\PHPUnit\Framework\MockObject\MockObject */
|
||||
/** @var Helper|MockObject */
|
||||
private $helper;
|
||||
/** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
|
||||
/** @var IConfig|MockObject */
|
||||
private $config;
|
||||
/** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */
|
||||
/** @var IUserManager|MockObject */
|
||||
private $ncUserManager;
|
||||
|
||||
private LoggerInterface&MockObject $logger;
|
||||
|
||||
private IAppConfig&MockObject $appConfig;
|
||||
|
||||
/** @var IEventDispatcher|MockObject */
|
||||
private $dispatcher;
|
||||
private Access $access;
|
||||
|
||||
protected function setUp(): void {
|
||||
|
|
@ -74,6 +77,7 @@ class AccessTest extends TestCase {
|
|||
$this->shareManager = $this->createMock(IManager::class);
|
||||
$this->logger = $this->createMock(LoggerInterface::class);
|
||||
$this->appConfig = $this->createMock(IAppConfig::class);
|
||||
$this->dispatcher = $this->createMock(IEventDispatcher::class);
|
||||
|
||||
$this->access = new Access(
|
||||
$this->ldap,
|
||||
|
|
@ -84,7 +88,9 @@ class AccessTest extends TestCase {
|
|||
$this->ncUserManager,
|
||||
$this->logger,
|
||||
$this->appConfig,
|
||||
$this->dispatcher,
|
||||
);
|
||||
$this->dispatcher->expects($this->any())->method('dispatchTyped');
|
||||
$this->access->setUserMapper($this->userMapper);
|
||||
$this->access->setGroupMapper($this->groupMapper);
|
||||
}
|
||||
|
|
@ -227,9 +233,9 @@ class AccessTest extends TestCase {
|
|||
*/
|
||||
public function testStringResemblesDN($case) {
|
||||
[$lw, $con, $um, $helper] = $this->getConnectorAndLdapMock();
|
||||
/** @var IConfig|\PHPUnit\Framework\MockObject\MockObject $config */
|
||||
/** @var IConfig|MockObject $config */
|
||||
$config = $this->createMock(IConfig::class);
|
||||
$access = new Access($lw, $con, $um, $helper, $config, $this->ncUserManager, $this->logger, $this->appConfig);
|
||||
$access = new Access($lw, $con, $um, $helper, $config, $this->ncUserManager, $this->logger, $this->appConfig, $this->dispatcher);
|
||||
|
||||
$lw->expects($this->exactly(1))
|
||||
->method('explodeDN')
|
||||
|
|
@ -249,10 +255,10 @@ class AccessTest extends TestCase {
|
|||
*/
|
||||
public function testStringResemblesDNLDAPmod($case) {
|
||||
[, $con, $um, $helper] = $this->getConnectorAndLdapMock();
|
||||
/** @var IConfig|\PHPUnit\Framework\MockObject\MockObject $config */
|
||||
/** @var IConfig|MockObject $config */
|
||||
$config = $this->createMock(IConfig::class);
|
||||
$lw = new LDAP();
|
||||
$access = new Access($lw, $con, $um, $helper, $config, $this->ncUserManager, $this->logger, $this->appConfig);
|
||||
$access = new Access($lw, $con, $um, $helper, $config, $this->ncUserManager, $this->logger, $this->appConfig, $this->dispatcher);
|
||||
|
||||
if (!function_exists('ldap_explode_dn')) {
|
||||
$this->markTestSkipped('LDAP Module not available');
|
||||
|
|
@ -282,7 +288,7 @@ class AccessTest extends TestCase {
|
|||
->method('getAttributes')
|
||||
->willReturn(['displayname' => ['bar', 'count' => 1]]);
|
||||
|
||||
/** @var UserMapping|\PHPUnit\Framework\MockObject\MockObject $mapperMock */
|
||||
/** @var UserMapping|MockObject $mapperMock */
|
||||
$mapperMock = $this->createMock(UserMapping::class);
|
||||
$mapperMock->expects($this->any())
|
||||
->method('getNameByDN')
|
||||
|
|
@ -327,7 +333,7 @@ class AccessTest extends TestCase {
|
|||
}
|
||||
|
||||
public function testBatchApplyUserAttributesSkipped() {
|
||||
/** @var UserMapping|\PHPUnit\Framework\MockObject\MockObject $mapperMock */
|
||||
/** @var UserMapping|MockObject $mapperMock */
|
||||
$mapperMock = $this->createMock(UserMapping::class);
|
||||
$mapperMock->expects($this->any())
|
||||
->method('getNameByDN')
|
||||
|
|
@ -368,7 +374,7 @@ class AccessTest extends TestCase {
|
|||
}
|
||||
|
||||
public function testBatchApplyUserAttributesDontSkip() {
|
||||
/** @var UserMapping|\PHPUnit\Framework\MockObject\MockObject $mapperMock */
|
||||
/** @var UserMapping|MockObject $mapperMock */
|
||||
$mapperMock = $this->createMock(UserMapping::class);
|
||||
$mapperMock->expects($this->any())
|
||||
->method('getNameByDN')
|
||||
|
|
@ -424,7 +430,7 @@ class AccessTest extends TestCase {
|
|||
*/
|
||||
public function testSanitizeDN($attribute) {
|
||||
[$lw, $con, $um, $helper] = $this->getConnectorAndLdapMock();
|
||||
/** @var IConfig|\PHPUnit\Framework\MockObject\MockObject $config */
|
||||
/** @var IConfig|MockObject $config */
|
||||
$config = $this->createMock(IConfig::class);
|
||||
|
||||
$dnFromServer = 'cn=Mixed Cases,ou=Are Sufficient To,ou=Test,dc=example,dc=org';
|
||||
|
|
@ -438,7 +444,7 @@ class AccessTest extends TestCase {
|
|||
$attribute => ['count' => 1, $dnFromServer]
|
||||
]);
|
||||
|
||||
$access = new Access($lw, $con, $um, $helper, $config, $this->ncUserManager, $this->logger, $this->appConfig);
|
||||
$access = new Access($lw, $con, $um, $helper, $config, $this->ncUserManager, $this->logger, $this->appConfig, $this->dispatcher);
|
||||
$values = $access->readAttribute('uid=whoever,dc=example,dc=org', $attribute);
|
||||
$this->assertSame($values[0], strtolower($dnFromServer));
|
||||
}
|
||||
|
|
@ -744,7 +750,7 @@ class AccessTest extends TestCase {
|
|||
->with('detta')
|
||||
->willReturnOnConsecutiveCalls($offlineUserMock, $regularUserMock);
|
||||
|
||||
/** @var UserMapping|\PHPUnit\Framework\MockObject\MockObject $mapperMock */
|
||||
/** @var UserMapping|MockObject $mapperMock */
|
||||
$mapperMock = $this->createMock(UserMapping::class);
|
||||
$mapperMock->expects($this->any())
|
||||
->method('getNameByDN')
|
||||
|
|
|
|||
|
|
@ -15,39 +15,42 @@ use OCA\User_LDAP\LDAP;
|
|||
use OCA\User_LDAP\Mapping\UserMapping;
|
||||
use OCA\User_LDAP\User\Manager;
|
||||
use OCP\AppFramework\Utility\ITimeFactory;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\IAvatarManager;
|
||||
use OCP\IConfig;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\IUserManager;
|
||||
use OCP\Notification\IManager;
|
||||
use OCP\Server;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Test\TestCase;
|
||||
|
||||
class SyncTest extends TestCase {
|
||||
/** @var array */
|
||||
protected $arguments;
|
||||
/** @var Helper|\PHPUnit\Framework\MockObject\MockObject */
|
||||
/** @var Helper|MockObject */
|
||||
protected $helper;
|
||||
/** @var LDAP|\PHPUnit\Framework\MockObject\MockObject */
|
||||
/** @var LDAP|MockObject */
|
||||
protected $ldapWrapper;
|
||||
/** @var Manager|\PHPUnit\Framework\MockObject\MockObject */
|
||||
/** @var Manager|MockObject */
|
||||
protected $userManager;
|
||||
/** @var UserMapping|\PHPUnit\Framework\MockObject\MockObject */
|
||||
/** @var UserMapping|MockObject */
|
||||
protected $mapper;
|
||||
/** @var Sync */
|
||||
protected $sync;
|
||||
/** @var IConfig|\PHPUnit\Framework\MockObject\MockObject */
|
||||
protected Sync $sync;
|
||||
/** @var IConfig|MockObject */
|
||||
protected $config;
|
||||
/** @var IAvatarManager|\PHPUnit\Framework\MockObject\MockObject */
|
||||
/** @var IAvatarManager|MockObject */
|
||||
protected $avatarManager;
|
||||
/** @var IDBConnection|\PHPUnit\Framework\MockObject\MockObject */
|
||||
/** @var IDBConnection|MockObject */
|
||||
protected $dbc;
|
||||
/** @var IUserManager|\PHPUnit\Framework\MockObject\MockObject */
|
||||
/** @var IUserManager|MockObject */
|
||||
protected $ncUserManager;
|
||||
/** @var IManager|\PHPUnit\Framework\MockObject\MockObject */
|
||||
/** @var IManager|MockObject */
|
||||
protected $notificationManager;
|
||||
/** @var ConnectionFactory|\PHPUnit\Framework\MockObject\MockObject */
|
||||
/** @var ConnectionFactory|MockObject */
|
||||
protected $connectionFactory;
|
||||
/** @var AccessFactory|\PHPUnit\Framework\MockObject\MockObject */
|
||||
/** @var AccessFactory|MockObject */
|
||||
protected $accessFactory;
|
||||
|
||||
protected function setUp(): void {
|
||||
|
|
@ -65,23 +68,25 @@ class SyncTest extends TestCase {
|
|||
$this->connectionFactory = $this->createMock(ConnectionFactory::class);
|
||||
$this->accessFactory = $this->createMock(AccessFactory::class);
|
||||
|
||||
$this->arguments = [
|
||||
'helper' => $this->helper,
|
||||
'ldapWrapper' => $this->ldapWrapper,
|
||||
'mapper' => $this->mapper,
|
||||
'config' => $this->config,
|
||||
'avatarManager' => $this->avatarManager,
|
||||
'dbc' => $this->dbc,
|
||||
'ncUserManager' => $this->ncUserManager,
|
||||
'notificationManager' => $this->notificationManager,
|
||||
'connectionFactory' => $this->connectionFactory,
|
||||
'accessFactory' => $this->accessFactory,
|
||||
];
|
||||
$this->sync = new Sync(
|
||||
Server::get(ITimeFactory::class),
|
||||
Server::get(IEventDispatcher::class),
|
||||
$this->config,
|
||||
$this->dbc,
|
||||
$this->avatarManager,
|
||||
$this->ncUserManager,
|
||||
Server::get(LoggerInterface::class),
|
||||
$this->notificationManager,
|
||||
$this->mapper,
|
||||
$this->helper,
|
||||
$this->connectionFactory,
|
||||
$this->accessFactory,
|
||||
);
|
||||
|
||||
$this->sync = new Sync($this->createMock(ITimeFactory::class));
|
||||
$this->sync->overwritePropertiesForTest($this->ldapWrapper);
|
||||
}
|
||||
|
||||
public function intervalDataProvider() {
|
||||
public function intervalDataProvider(): array {
|
||||
return [
|
||||
[
|
||||
0, 1000, 750
|
||||
|
|
@ -104,7 +109,7 @@ class SyncTest extends TestCase {
|
|||
/**
|
||||
* @dataProvider intervalDataProvider
|
||||
*/
|
||||
public function testUpdateInterval($userCount, $pagingSize1, $pagingSize2) {
|
||||
public function testUpdateInterval(int $userCount, int $pagingSize1, int $pagingSize2): void {
|
||||
$this->config->expects($this->once())
|
||||
->method('setAppValue')
|
||||
->with('user_ldap', 'background_sync_interval', $this->anything())
|
||||
|
|
@ -161,7 +166,7 @@ class SyncTest extends TestCase {
|
|||
return null;
|
||||
});
|
||||
|
||||
/** @var Access|\PHPUnit\Framework\MockObject\MockObject $access */
|
||||
/** @var Access|MockObject $access */
|
||||
$access = $this->createMock(Access::class);
|
||||
$this->accessFactory->expects($this->any())
|
||||
->method('get')
|
||||
|
|
@ -231,7 +236,7 @@ class SyncTest extends TestCase {
|
|||
}
|
||||
}
|
||||
|
||||
public function testQualifiesToRun() {
|
||||
public function testQualifiesToRun(): void {
|
||||
$cycleData = ['prefix' => 's01'];
|
||||
|
||||
$this->config->expects($this->exactly(2))
|
||||
|
|
@ -243,7 +248,7 @@ class SyncTest extends TestCase {
|
|||
$this->assertFalse($this->sync->qualifiesToRun($cycleData));
|
||||
}
|
||||
|
||||
public function runDataProvider() {
|
||||
public function runDataProvider(): array {
|
||||
return [
|
||||
#0 - one LDAP server, reset
|
||||
[[
|
||||
|
|
@ -335,7 +340,7 @@ class SyncTest extends TestCase {
|
|||
return null;
|
||||
});
|
||||
|
||||
/** @var Access|\PHPUnit\Framework\MockObject\MockObject $access */
|
||||
/** @var Access|MockObject $access */
|
||||
$access = $this->createMock(Access::class);
|
||||
$this->accessFactory->expects($this->any())
|
||||
->method('get')
|
||||
|
|
|
|||
|
|
@ -854,6 +854,7 @@ return array(
|
|||
'OCP\\User\\Events\\BeforePasswordUpdatedEvent' => $baseDir . '/lib/public/User/Events/BeforePasswordUpdatedEvent.php',
|
||||
'OCP\\User\\Events\\BeforeUserCreatedEvent' => $baseDir . '/lib/public/User/Events/BeforeUserCreatedEvent.php',
|
||||
'OCP\\User\\Events\\BeforeUserDeletedEvent' => $baseDir . '/lib/public/User/Events/BeforeUserDeletedEvent.php',
|
||||
'OCP\\User\\Events\\BeforeUserIdUnassignedEvent' => $baseDir . '/lib/public/User/Events/BeforeUserIdUnassignedEvent.php',
|
||||
'OCP\\User\\Events\\BeforeUserLoggedInEvent' => $baseDir . '/lib/public/User/Events/BeforeUserLoggedInEvent.php',
|
||||
'OCP\\User\\Events\\BeforeUserLoggedInWithCookieEvent' => $baseDir . '/lib/public/User/Events/BeforeUserLoggedInWithCookieEvent.php',
|
||||
'OCP\\User\\Events\\BeforeUserLoggedOutEvent' => $baseDir . '/lib/public/User/Events/BeforeUserLoggedOutEvent.php',
|
||||
|
|
@ -868,6 +869,8 @@ return array(
|
|||
'OCP\\User\\Events\\UserCreatedEvent' => $baseDir . '/lib/public/User/Events/UserCreatedEvent.php',
|
||||
'OCP\\User\\Events\\UserDeletedEvent' => $baseDir . '/lib/public/User/Events/UserDeletedEvent.php',
|
||||
'OCP\\User\\Events\\UserFirstTimeLoggedInEvent' => $baseDir . '/lib/public/User/Events/UserFirstTimeLoggedInEvent.php',
|
||||
'OCP\\User\\Events\\UserIdAssignedEvent' => $baseDir . '/lib/public/User/Events/UserIdAssignedEvent.php',
|
||||
'OCP\\User\\Events\\UserIdUnassignedEvent' => $baseDir . '/lib/public/User/Events/UserIdUnassignedEvent.php',
|
||||
'OCP\\User\\Events\\UserLiveStatusEvent' => $baseDir . '/lib/public/User/Events/UserLiveStatusEvent.php',
|
||||
'OCP\\User\\Events\\UserLoggedInEvent' => $baseDir . '/lib/public/User/Events/UserLoggedInEvent.php',
|
||||
'OCP\\User\\Events\\UserLoggedInWithCookieEvent' => $baseDir . '/lib/public/User/Events/UserLoggedInWithCookieEvent.php',
|
||||
|
|
|
|||
|
|
@ -887,6 +887,7 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
|
|||
'OCP\\User\\Events\\BeforePasswordUpdatedEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/BeforePasswordUpdatedEvent.php',
|
||||
'OCP\\User\\Events\\BeforeUserCreatedEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/BeforeUserCreatedEvent.php',
|
||||
'OCP\\User\\Events\\BeforeUserDeletedEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/BeforeUserDeletedEvent.php',
|
||||
'OCP\\User\\Events\\BeforeUserIdUnassignedEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/BeforeUserIdUnassignedEvent.php',
|
||||
'OCP\\User\\Events\\BeforeUserLoggedInEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/BeforeUserLoggedInEvent.php',
|
||||
'OCP\\User\\Events\\BeforeUserLoggedInWithCookieEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/BeforeUserLoggedInWithCookieEvent.php',
|
||||
'OCP\\User\\Events\\BeforeUserLoggedOutEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/BeforeUserLoggedOutEvent.php',
|
||||
|
|
@ -901,6 +902,8 @@ class ComposerStaticInit749170dad3f5e7f9ca158f5a9f04f6a2
|
|||
'OCP\\User\\Events\\UserCreatedEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/UserCreatedEvent.php',
|
||||
'OCP\\User\\Events\\UserDeletedEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/UserDeletedEvent.php',
|
||||
'OCP\\User\\Events\\UserFirstTimeLoggedInEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/UserFirstTimeLoggedInEvent.php',
|
||||
'OCP\\User\\Events\\UserIdAssignedEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/UserIdAssignedEvent.php',
|
||||
'OCP\\User\\Events\\UserIdUnassignedEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/UserIdUnassignedEvent.php',
|
||||
'OCP\\User\\Events\\UserLiveStatusEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/UserLiveStatusEvent.php',
|
||||
'OCP\\User\\Events\\UserLoggedInEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/UserLoggedInEvent.php',
|
||||
'OCP\\User\\Events\\UserLoggedInWithCookieEvent' => __DIR__ . '/../../..' . '/lib/public/User/Events/UserLoggedInWithCookieEvent.php',
|
||||
|
|
|
|||
|
|
@ -7,14 +7,18 @@
|
|||
*/
|
||||
namespace OC\Console;
|
||||
|
||||
use ArgumentCountError;
|
||||
use OC\MemoryInfo;
|
||||
use OC\NeedsUpdateException;
|
||||
use OC\SystemConfig;
|
||||
use OCP\App\AppPathNotFoundException;
|
||||
use OCP\App\IAppManager;
|
||||
use OCP\Console\ConsoleEvent;
|
||||
use OCP\Defaults;
|
||||
use OCP\EventDispatcher\IEventDispatcher;
|
||||
use OCP\IConfig;
|
||||
use OCP\IRequest;
|
||||
use OCP\Server;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\Console\Application as SymfonyApplication;
|
||||
|
|
@ -33,8 +37,8 @@ class Application {
|
|||
private LoggerInterface $logger,
|
||||
private MemoryInfo $memoryInfo,
|
||||
private IAppManager $appManager,
|
||||
private Defaults $defaults,
|
||||
) {
|
||||
$defaults = \OC::$server->get('ThemingDefaults');
|
||||
$this->application = new SymfonyApplication($defaults->getName(), \OC_Util::getVersionString());
|
||||
}
|
||||
|
||||
|
|
@ -44,7 +48,7 @@ class Application {
|
|||
public function loadCommands(
|
||||
InputInterface $input,
|
||||
ConsoleOutputInterface $output
|
||||
) {
|
||||
): void {
|
||||
// $application is required to be defined in the register_command scripts
|
||||
$application = $this->application;
|
||||
$inputDefinition = $application->getDefinition();
|
||||
|
|
@ -118,7 +122,7 @@ class Application {
|
|||
$errorOutput = $output->getErrorOutput();
|
||||
$errorOutput->writeln('Nextcloud is not installed - only a limited number of commands are available');
|
||||
}
|
||||
} catch (NeedsUpdateException $e) {
|
||||
} catch (NeedsUpdateException) {
|
||||
if ($input->getArgument('command') !== '_completion') {
|
||||
$errorOutput = $output->getErrorOutput();
|
||||
$errorOutput->writeln('Nextcloud or one of the apps require upgrade - only a limited number of commands are available');
|
||||
|
|
@ -127,7 +131,7 @@ class Application {
|
|||
}
|
||||
|
||||
if ($input->getFirstArgument() !== 'check') {
|
||||
$errors = \OC_Util::checkServer(\OC::$server->getSystemConfig());
|
||||
$errors = \OC_Util::checkServer(Server::get(SystemConfig::class));
|
||||
if (!empty($errors)) {
|
||||
foreach ($errors as $error) {
|
||||
$output->writeln((string)$error['error']);
|
||||
|
|
@ -163,13 +167,11 @@ class Application {
|
|||
*
|
||||
* @param bool $boolean Whether to automatically exit after a command execution or not
|
||||
*/
|
||||
public function setAutoExit($boolean) {
|
||||
public function setAutoExit(bool $boolean): void {
|
||||
$this->application->setAutoExit($boolean);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param InputInterface $input
|
||||
* @param OutputInterface $output
|
||||
* @return int
|
||||
* @throws \Exception
|
||||
*/
|
||||
|
|
@ -183,15 +185,18 @@ class Application {
|
|||
return $this->application->run($input, $output);
|
||||
}
|
||||
|
||||
private function loadCommandsFromInfoXml($commands) {
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function loadCommandsFromInfoXml(iterable $commands): void {
|
||||
foreach ($commands as $command) {
|
||||
try {
|
||||
$c = \OCP\Server::get($command);
|
||||
$c = Server::get($command);
|
||||
} catch (ContainerExceptionInterface $e) {
|
||||
if (class_exists($command)) {
|
||||
try {
|
||||
$c = new $command();
|
||||
} catch (\ArgumentCountError $e2) {
|
||||
} catch (ArgumentCountError) {
|
||||
throw new \Exception("Failed to construct console command '$command': " . $e->getMessage(), 0, $e);
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ class Generator {
|
|||
$height,
|
||||
$crop,
|
||||
$mode,
|
||||
$mimeType,
|
||||
));
|
||||
|
||||
// since we only ask for one preview, and the generate method return the last one it created, it returns the one we want
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ use OCP\IPreview;
|
|||
*
|
||||
* @since 25.0.1
|
||||
* @since 28.0.0 the constructor arguments ``$width``, ``$height``, ``$crop`` and ``$mode`` are no longer nullable.
|
||||
* @since 31.0.0 the constructor arguments ``$mimeType`` was added
|
||||
*/
|
||||
class BeforePreviewFetchedEvent extends \OCP\EventDispatcher\Event {
|
||||
/**
|
||||
|
|
@ -24,14 +25,15 @@ class BeforePreviewFetchedEvent extends \OCP\EventDispatcher\Event {
|
|||
*/
|
||||
public function __construct(
|
||||
private Node $node,
|
||||
/** @deprecated 28.0.0 null deprecated **/
|
||||
/** @deprecated 28.0.0 passing null is deprecated **/
|
||||
private ?int $width = null,
|
||||
/** @deprecated 28.0.0 null deprecated **/
|
||||
/** @deprecated 28.0.0 passing null is deprecated **/
|
||||
private ?int $height = null,
|
||||
/** @deprecated 28.0.0 null deprecated **/
|
||||
/** @deprecated 28.0.0 passing null is deprecated **/
|
||||
private ?bool $crop = null,
|
||||
/** @deprecated 28.0.0 null deprecated **/
|
||||
/** @deprecated 28.0.0 passing null is deprecated **/
|
||||
private ?string $mode = null,
|
||||
private ?string $mimeType = null,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
|
@ -71,4 +73,11 @@ class BeforePreviewFetchedEvent extends \OCP\EventDispatcher\Event {
|
|||
public function getMode(): ?string {
|
||||
return $this->mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 31.0.0
|
||||
*/
|
||||
public function getMimeType(): ?string {
|
||||
return $this->mimeType;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
34
lib/public/User/Events/BeforeUserIdUnassignedEvent.php
Normal file
34
lib/public/User/Events/BeforeUserIdUnassignedEvent.php
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCP\User\Events;
|
||||
|
||||
use OCP\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* Emitted before removing the mapping between an external user and an internal userid
|
||||
* @since 31.0.0
|
||||
*/
|
||||
class BeforeUserIdUnassignedEvent extends Event {
|
||||
/**
|
||||
* @since 31.0.0
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly string $userId,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 31.0.0
|
||||
*/
|
||||
public function getUserId(): string {
|
||||
return $this->userId;
|
||||
}
|
||||
}
|
||||
34
lib/public/User/Events/UserIdAssignedEvent.php
Normal file
34
lib/public/User/Events/UserIdAssignedEvent.php
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCP\User\Events;
|
||||
|
||||
use OCP\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* Emitted by backends (like user_ldap) when a user created externally is mapped for the first time and assigned a userid
|
||||
* @since 31.0.0
|
||||
*/
|
||||
class UserIdAssignedEvent extends Event {
|
||||
/**
|
||||
* @since 31.0.0
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly string $userId,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 31.0.0
|
||||
*/
|
||||
public function getUserId(): string {
|
||||
return $this->userId;
|
||||
}
|
||||
}
|
||||
34
lib/public/User/Events/UserIdUnassignedEvent.php
Normal file
34
lib/public/User/Events/UserIdUnassignedEvent.php
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
|
||||
* SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
*/
|
||||
|
||||
namespace OCP\User\Events;
|
||||
|
||||
use OCP\EventDispatcher\Event;
|
||||
|
||||
/**
|
||||
* Emitted after removing the mapping between an external user and an internal userid
|
||||
* @since 31.0.0
|
||||
*/
|
||||
class UserIdUnassignedEvent extends Event {
|
||||
/**
|
||||
* @since 31.0.0
|
||||
*/
|
||||
public function __construct(
|
||||
private readonly string $userId,
|
||||
) {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 31.0.0
|
||||
*/
|
||||
public function getUserId(): string {
|
||||
return $this->userId;
|
||||
}
|
||||
}
|
||||
|
|
@ -91,7 +91,7 @@ class GeneratorTest extends \Test\TestCase {
|
|||
|
||||
$this->eventDispatcher->expects($this->once())
|
||||
->method('dispatchTyped')
|
||||
->with(new BeforePreviewFetchedEvent($file, 100, 100, false, IPreview::MODE_FILL));
|
||||
->with(new BeforePreviewFetchedEvent($file, 100, 100, false, IPreview::MODE_FILL, null));
|
||||
|
||||
$result = $this->generator->getPreview($file, 100, 100);
|
||||
$this->assertSame($previewFile, $result);
|
||||
|
|
@ -219,7 +219,7 @@ class GeneratorTest extends \Test\TestCase {
|
|||
|
||||
$this->eventDispatcher->expects($this->once())
|
||||
->method('dispatchTyped')
|
||||
->with(new BeforePreviewFetchedEvent($file, 100, 100, false, IPreview::MODE_FILL));
|
||||
->with(new BeforePreviewFetchedEvent($file, 100, 100, false, IPreview::MODE_FILL, null));
|
||||
|
||||
$result = $this->generator->getPreview($file, 100, 100);
|
||||
$this->assertSame($previewFile, $result);
|
||||
|
|
@ -258,7 +258,7 @@ class GeneratorTest extends \Test\TestCase {
|
|||
|
||||
$this->eventDispatcher->expects($this->once())
|
||||
->method('dispatchTyped')
|
||||
->with(new BeforePreviewFetchedEvent($file, 1024, 512, true, IPreview::MODE_COVER));
|
||||
->with(new BeforePreviewFetchedEvent($file, 1024, 512, true, IPreview::MODE_COVER, 'invalidType'));
|
||||
|
||||
$this->generator->getPreview($file, 1024, 512, true, IPreview::MODE_COVER, 'invalidType');
|
||||
}
|
||||
|
|
@ -295,7 +295,7 @@ class GeneratorTest extends \Test\TestCase {
|
|||
|
||||
$this->eventDispatcher->expects($this->once())
|
||||
->method('dispatchTyped')
|
||||
->with(new BeforePreviewFetchedEvent($file, 1024, 512, true, IPreview::MODE_COVER));
|
||||
->with(new BeforePreviewFetchedEvent($file, 1024, 512, true, IPreview::MODE_COVER, 'invalidType'));
|
||||
|
||||
$result = $this->generator->getPreview($file, 1024, 512, true, IPreview::MODE_COVER, 'invalidType');
|
||||
$this->assertSame($preview, $result);
|
||||
|
|
@ -323,7 +323,7 @@ class GeneratorTest extends \Test\TestCase {
|
|||
|
||||
$this->eventDispatcher->expects($this->once())
|
||||
->method('dispatchTyped')
|
||||
->with(new BeforePreviewFetchedEvent($file, 100, 100, false, IPreview::MODE_FILL));
|
||||
->with(new BeforePreviewFetchedEvent($file, 100, 100, false, IPreview::MODE_FILL, null));
|
||||
|
||||
$this->expectException(NotFoundException::class);
|
||||
$this->generator->getPreview($file, 100, 100);
|
||||
|
|
@ -448,7 +448,7 @@ class GeneratorTest extends \Test\TestCase {
|
|||
|
||||
$this->eventDispatcher->expects($this->once())
|
||||
->method('dispatchTyped')
|
||||
->with(new BeforePreviewFetchedEvent($file, $reqX, $reqY, $crop, $mode));
|
||||
->with(new BeforePreviewFetchedEvent($file, $reqX, $reqY, $crop, $mode, null));
|
||||
|
||||
$result = $this->generator->getPreview($file, $reqX, $reqY, $crop, $mode);
|
||||
if ($expectedX === $maxX && $expectedY === $maxY) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue