accountRepository = $accountRepository; $this->aliasRepository = $aliasRepository; $this->domainRepository = $domainRepository; $this->passwordHelper = $passwordHelper; } // -- /accounts - List all accounts public function listAccounts(string $filterByDomain): array { $accountList = $this->accountRepository->fetchAccountList($filterByDomain); return [ 'filterDomain' => $filterByDomain, 'accountList' => $accountList, ]; } // -- /accounts/{id} - Show account details public function getAccountDetails(int $accountId): array { // Get account data from database $account = $this->accountRepository->fetchAccountById($accountId); // Don't display the password hash, but at least the type of hash (used hash algorithm) $passwordHashType = $this->passwordHelper->getPasswordHashType($account->getPasswordHash()); // Get list of aliases for this account $aliases = $this->aliasRepository->fetchAliasesForUserId($accountId); return [ 'id' => $accountId, 'accountUsername' => $account->getUsername(), 'account' => $account, 'passwordHashType' => $passwordHashType, 'aliases' => $aliases, ]; } // -- /accounts/new - Create new account public function getPageDataForCreate(): array { return [ 'domainList' => array_keys($this->domainRepository->fetchDomainList()), ]; } public function createNewAccount(AccountCreateData $createData): array { // Check if new username is still available $username = $createData->getUsername(); if (!$this->accountRepository->checkUsernameAvailable($username) || !$this->aliasRepository->checkAliasAvailable($username)) { throw new InputValidationError("Username \"$username\" is not available."); } // Array returned by the function on success $returnData = [ 'username' => $username, ]; // Hash new password $password = $createData->getPassword(); if ($password === null) { $password = $this->passwordHelper->generateRandomPassword(); $returnData['generatedPassword'] = $password; } $passwordHash = $this->passwordHelper->hashPassword($password); // Construct home directory from username if necessary if ($createData->getHomeDir() !== null) { $homeDir = $createData->getHomeDir(); } else { [$localPart, $domainPart] = explode('@', $username, 2); $homeDir = $domainPart . '/' . $localPart; } // Create account in database $returnData['id'] = $this->accountRepository->insertAccount( $username, $passwordHash, $createData->getActive(), $homeDir, $createData->getMemo() ); return $returnData; } // -- /accounts/{id}/edit - Edit account data public function getAccountDataForEdit(int $accountId): array { // Get account data from database $account = $this->accountRepository->fetchAccountById($accountId); return [ 'id' => $accountId, 'accountUsername' => $account->getUsername(), 'account' => $account, ]; } public function editAccountData(int $accountId, AccountEditData $editData): array { // Array returned by the function on success $returnData = []; // Check if account exists try { $account = $this->accountRepository->fetchAccountById($accountId); } catch (AccountNotFoundException $e) { throw new InputValidationError('Account with ID ' . $accountId . ' does not exist!'); } $newUsername = $editData->getUsername(); if ($newUsername === $account->getUsername()) { // Username is unchanged $newUsername = null; } // This variable will be set to true if the user wants to change their username, has an existing alias with this username, // and checked the "replace existing alias" option. $aliasNeedsToBeReplaced = false; // Check if new username is still available if ($newUsername !== null) { $newUsernameAvailable = true; // Check if account with this username already exists if (!$this->accountRepository->checkUsernameAvailable($newUsername)) { $newUsernameAvailable = false; } // Check if alias with this username/address already exists if (!$this->aliasRepository->checkAliasAvailable($newUsername)) { $newUsernameAvailable = false; // Alias already exists. If user wants to replace an existing alias, check if the alias belongs to this user. if ($editData->getUsernameReplaceAlias()) { $existingAlias = $this->aliasRepository->fetchAliasByAddress($newUsername); if ($existingAlias->getUserId() === $accountId) { $aliasNeedsToBeReplaced = true; $newUsernameAvailable = true; } } } if (!$newUsernameAvailable) { throw new InputValidationError("Username \"$newUsername\" is not available."); } } // Start database transaction $this->accountRepository->beginTransaction(); // Create alias for old username (if wanted) if ($editData->getUsernameCreateAlias()) { $oldUsername = $account->getUsername(); if (!$this->aliasRepository->checkAliasAvailable($oldUsername)) { throw new InputValidationError("Alias \"$oldUsername\" cannot be created: Alias already exists."); } $this->aliasRepository->createNewAlias($accountId, $oldUsername); } // Generate new password (if wanted) $newPassword = $editData->getPassword(); if ($editData->getPasswordGenerateRandom()) { $newPassword = $this->passwordHelper->generateRandomPassword(); $returnData['generatedPassword'] = $newPassword; } // Hash new password $newPasswordHash = $newPassword !== null ? $this->passwordHelper->hashPassword($newPassword) : null; // Update account in database $this->accountRepository->updateAccountWithId( $accountId, $newUsername, $newPasswordHash, $editData->getActive(), $editData->getHomeDir(), $editData->getMemo() ); // Remove existing alias for new username (if wanted) if ($editData->getUsernameReplaceAlias() && $aliasNeedsToBeReplaced) { $this->aliasRepository->deleteAlias($accountId, $newUsername); } // Commit database transaction $this->accountRepository->commitTransaction(); return $returnData; } // -- /accounts/{id}/delete - Delete account public function getAccountDataForDelete(int $accountId): array { // Get account data from database $account = $this->accountRepository->fetchAccountById($accountId); // Get list of aliases for this account $aliases = $this->aliasRepository->fetchAliasesForUserId($accountId); return [ 'id' => $accountId, 'accountUsername' => $account->getUsername(), 'aliases' => $aliases, ]; } public function deleteAccount(int $accountId): array { // Check if account exists try { $account = $this->accountRepository->fetchAccountById($accountId); } catch (AccountNotFoundException $e) { throw new InputValidationError('Account with ID ' . $accountId . ' does not exist!'); } // Start database transaction $this->accountRepository->beginTransaction(); // Delete all aliases associated with this account $deleteAliasCount = $this->aliasRepository->deleteAllAliasesForUserId($accountId); // Delete account from database $this->accountRepository->deleteAccountWithId($accountId); // Commit database transaction $this->accountRepository->commitTransaction(); return [ 'username' => $account->getUsername(), 'deleted_alias_count' => $deleteAliasCount, ]; } // -- /accounts/{id}/addalias - Create a new alias for the account public function addAliasToAccount(int $accountId, AccountAddAliasData $aliasAddData): void { // Check if account exists try { $this->accountRepository->fetchAccountById($accountId); } catch (AccountNotFoundException $e) { throw new InputValidationError('Account with ID ' . $accountId . ' does not exist!'); } // Check if alias address is still available $address = $aliasAddData->getAliasAddress(); if (!$this->accountRepository->checkUsernameAvailable($address) || !$this->aliasRepository->checkAliasAvailable($address)) { throw new InputValidationError("Alias address \"$address\" is not available."); } // Create alias in database $this->aliasRepository->createNewAlias($accountId, $address); } }