/
kev
/
Nextcloud_Users-mod
Обзор
Документация
Войти
/
kev
/
Nextcloud_Users-mod
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
lib/Service/UserManagementService.php
342 строки
12 KB
Evgeny Konovalov
first_commit
01 мар 2026, 19:48
01 мар 2026, 19:48
b6c8230
Код
Авторство
О чём код?
<?php declare(strict_types=1); namespace OCA\Users_mod\Service; use OCP\Accounts\IAccountManager; use OCP\Accounts\IAccountProperty; use OCP\IGroupManager; use OCP\IUser; use OCP\IUserManager; use OCP\IUserSession; use Psr\Log\LoggerInterface; /** * Сервис управления пользователями: получение и обновление данных через IUserManager, IAccountManager, IGroupManager. */ class UserManagementService { public function __construct( private IUserManager $userManager, private IAccountManager $accountManager, private IGroupManager $groupManager, private IUserSession $userSession, private ?LoggerInterface $logger = null, ) { } /** * Проверка прав администратора. */ public function isAdmin(): bool { $user = $this->userSession->getUser(); return $user !== null && $this->groupManager->isAdmin($user->getUID()); } /** * Список UID пользователей с опциональным поиском и пагинацией. * * @return list<string> */ public function searchUsers(string $search = '', int $limit = 100, int $offset = 0): array { $users = $this->userManager->search($search, $limit, $offset); return array_map(fn (IUser $u) => $u->getUID(), $users); } /** * Данные одного пользователя для отображения в форме (все поля из учётной записи и профиля). * * @return array<string, mixed>|null */ public function getUserData(string $userId): ?array { $user = $this->userManager->get($userId); if ($user === null) { return null; } return $this->userToArray($user); } /** * Преобразование IUser в массив полей для API/формы. * * @return array<string, mixed> */ public function userToArray(IUser $user): array { $uid = $user->getUID(); try { $account = $this->accountManager->getAccount($user); } catch (\Throwable $e) { $account = null; } $getProp = function (string $name) use ($account): string { if ($account === null) { return ''; } try { $prop = $account->getProperty($name); return $prop instanceof IAccountProperty ? $prop->getValue() : ''; } catch (\Throwable $e) { return ''; } }; $email = $getProp(IAccountManager::PROPERTY_EMAIL) ?: ($user->getEMailAddress() ?? ''); $displayname = $getProp(IAccountManager::PROPERTY_DISPLAYNAME) ?: $user->getDisplayName(); $phone = $getProp(IAccountManager::PROPERTY_PHONE); $address = $getProp(IAccountManager::PROPERTY_ADDRESS); $website = $getProp(IAccountManager::PROPERTY_WEBSITE); $twitter = defined(IAccountManager::class . '::PROPERTY_TWITTER') ? $getProp(IAccountManager::PROPERTY_TWITTER) : ''; try { $groups = $this->groupManager->getUserGroups($user); } catch (\Throwable $e) { $groups = []; } $groupIds = $groups !== null && is_array($groups) ? array_map(fn ($g) => $g->getGID(), $groups) : []; return [ 'id' => $uid, 'displayname' => $displayname, 'email' => $email, 'phone' => $phone, 'address' => $address, 'website' => $website, 'twitter' => $twitter, 'quota' => $user->getQuota(), 'enabled' => $user->isEnabled(), 'groups' => $groupIds, 'lastLogin' => $user->getLastLogin(), ]; } /** * Создание пользователя. * При любой ошибке логируем и возвращаем null (контроллер вернёт 400). * * @param array{userid: string, password?: string, displayname?: string, email?: string, groups?: list<string>} $data */ public function createUser(array $data): ?IUser { $userid = trim($data['userid'] ?? ''); if ($userid === '') { return null; } if ($this->userManager->get($userid) !== null) { return null; } try { $password = $data['password'] ?? ''; $user = $this->userManager->createUser($userid, $password); if ($user === null || $user === false) { return null; } $this->updateUserData($user, $data); $groups = $data['groups'] ?? []; foreach ($groups as $gid) { $group = $this->groupManager->get($gid); if ($group !== null && !$group->inGroup($user)) { $group->addUser($user); } } return $user; } catch (\Throwable $e) { if ($this->logger !== null) { $this->logger->error('users_mod: createUser failed: ' . $e->getMessage(), [ 'exception' => $e, 'userid' => $userid, ]); } return null; } } /** * Обновление данных пользователя (профиль, квота, группы, включён/выключен). * * @param array{displayname?: string, email?: string, phone?: string, address?: string, website?: string, twitter?: string, quota?: string, enabled?: bool, groups?: list<string>, password?: string} $data */ public function updateUserData(IUser $user, array $data): void { if (isset($data['displayname'])) { $user->setDisplayName($data['displayname']); } try { $account = $this->accountManager->getAccount($user); } catch (\Throwable $e) { $account = null; } if ($account !== null) { try { $account->setProperty(IAccountManager::PROPERTY_DISPLAYNAME, $user->getDisplayName(), IAccountManager::SCOPE_FEDERATED, IAccountManager::NOT_VERIFIED); if (array_key_exists('email', $data)) { $user->setSystemEMailAddress((string) $data['email']); $account->setProperty(IAccountManager::PROPERTY_EMAIL, (string) $data['email'], IAccountManager::SCOPE_FEDERATED, IAccountManager::NOT_VERIFIED); } if (array_key_exists('phone', $data)) { $account->setProperty(IAccountManager::PROPERTY_PHONE, (string) $data['phone'], IAccountManager::SCOPE_LOCAL, IAccountManager::NOT_VERIFIED); } if (array_key_exists('address', $data)) { $account->setProperty(IAccountManager::PROPERTY_ADDRESS, (string) $data['address'], IAccountManager::SCOPE_LOCAL, IAccountManager::NOT_VERIFIED); } if (array_key_exists('website', $data)) { $account->setProperty(IAccountManager::PROPERTY_WEBSITE, (string) $data['website'], IAccountManager::SCOPE_LOCAL, IAccountManager::NOT_VERIFIED); } if (array_key_exists('twitter', $data) && defined(IAccountManager::class . '::PROPERTY_TWITTER')) { $account->setProperty(IAccountManager::PROPERTY_TWITTER, (string) $data['twitter'], IAccountManager::SCOPE_LOCAL, IAccountManager::NOT_VERIFIED); } $this->accountManager->updateAccount($account); } catch (\Throwable $e) { if (array_key_exists('email', $data)) { $user->setSystemEMailAddress((string) $data['email']); } } } else { if (array_key_exists('email', $data)) { $user->setSystemEMailAddress((string) $data['email']); } } if (array_key_exists('quota', $data)) { $user->setQuota((string) $data['quota']); } if (array_key_exists('enabled', $data)) { $user->setEnabled((bool) $data['enabled']); } if (isset($data['password']) && $data['password'] !== '' && $user->canChangePassword()) { $user->setPassword($data['password']); } if (isset($data['groups']) && is_array($data['groups'])) { $currentGroups = $this->groupManager->getUserGroups($user); $current = $currentGroups !== null ? array_map(fn ($g) => $g->getGID(), $currentGroups) : []; $target = $data['groups']; foreach (array_diff($target, $current) as $gid) { $group = $this->groupManager->get($gid); if ($group !== null) { $group->addUser($user); } } foreach (array_diff($current, $target) as $gid) { $group = $this->groupManager->get($gid); if ($group !== null && $gid !== 'admin') { $group->removeUser($user); } } } } /** * Удаление пользователя. */ public function deleteUser(string $userId): bool { $user = $this->userManager->get($userId); if ($user === null) { return false; } return $user->delete(); } /** * Включить/выключить пользователя. */ public function setEnabled(string $userId, bool $enabled): bool { $user = $this->userManager->get($userId); if ($user === null) { return false; } $user->setEnabled($enabled); return true; } /** * Список всех групп для выбора в форме. * * @return list<string> */ public function getGroupIds(): array { $groups = $this->groupManager->search(''); $ids = []; foreach ($groups as $g) { $ids[] = $g->getGID(); } sort($ids); return $ids; } /** * Создание группы. */ public function createGroup(string $gid): bool { $gid = trim($gid); if ($gid === '') { return false; } if ($this->groupManager->get($gid) !== null) { return false; } return $this->groupManager->createGroup($gid) !== null; } /** * Данные группы: id и список UID участников. * * @return array{id: string, members: list<string>}|null */ public function getGroupData(string $gid): ?array { $group = $this->groupManager->get($gid); if ($group === null) { return null; } $users = $group->getUsers(); $members = []; foreach ($users as $u) { $members[] = $u->getUID(); } sort($members); return ['id' => $group->getGID(), 'members' => $members]; } /** * Удаление группы. */ public function deleteGroup(string $gid): bool { $group = $this->groupManager->get($gid); if ($group === null) { return false; } return $group->delete(); } /** * Добавить пользователя в группу. */ public function addUserToGroup(string $gid, string $uid): bool { $group = $this->groupManager->get($gid); $user = $this->userManager->get($uid); if ($group === null || $user === null) { return false; } if ($group->inGroup($user)) { return true; } $group->addUser($user); return true; } /** * Удалить пользователя из группы. */ public function removeUserFromGroup(string $gid, string $uid): bool { $group = $this->groupManager->get($gid); $user = $this->userManager->get($uid); if ($group === null || $user === null) { return false; } if (!$group->inGroup($user)) { return true; } $group->removeUser($user); return true; } }