Skip to content

Commit

Permalink
Merge pull request #3 from f-franz/master
Browse files Browse the repository at this point in the history
Extend user and access management
  • Loading branch information
Alexander Bigga authored Mar 26, 2022
2 parents 7c911b9 + 55ccbb5 commit b6a4ead
Show file tree
Hide file tree
Showing 88 changed files with 5,099 additions and 445 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
.vscode
.idea
2 changes: 1 addition & 1 deletion Classes/Command/DeleteDeactivatedAccountsCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
$time = new \DateTime();
$deleteTimestamp = $time->getTimestamp() - ((60 * 60 * 24) * $timespan);

$feUsers = $this->UserRepository->findDeactivatedAccounts($deleteTimestamp, $this->settings['feUserGroup']);
$feUsers = $this->UserRepository->findDeactivatedAccounts($deleteTimestamp, $this->feUserGroups);

if (!empty($feUsers)) {
$deleteCounter = $this->deleteFeUsers($feUsers);
Expand Down
2 changes: 1 addition & 1 deletion Classes/Command/DeleteInactiveAccountsCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
}
$deleteTimespan = time() - (60 * 60 * (int)$timespan);

$feUsers = $this->UserRepository->findInactiveAccounts($deleteTimespan, $this->settings['feUserGroup']);
$feUsers = $this->UserRepository->findInactiveAccounts($deleteTimespan, $this->feUserGroups);

if (!empty($feUsers)) {
$deleteCounter = $this->deleteFeUsers($feUsers);
Expand Down
117 changes: 115 additions & 2 deletions Classes/Command/DigasBaseCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/

use Slub\DigasFeManagement\Domain\Model\Access;
use Slub\DigasFeManagement\Domain\Model\User;
use Slub\DigasFeManagement\Domain\Repository\AccessRepository;
use Slub\DigasFeManagement\Domain\Repository\UserRepository;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
Expand All @@ -34,6 +37,7 @@
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Object\ObjectManager;
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
use TYPO3\CMS\Fluid\View\StandaloneView;

/**
* Class DigasBaseCommand
Expand All @@ -51,6 +55,11 @@ class DigasBaseCommand extends Command
*/
protected $UserRepository;

/**
* @var AccessRepository
*/
protected $AccessRepository;

/**
* @var PersistenceManager
*/
Expand All @@ -66,6 +75,11 @@ class DigasBaseCommand extends Command
*/
protected $settings;

/**
* @var array
*/
protected $feUserGroups;

/**
* @param InputInterface $input
* @param OutputInterface $output
Expand All @@ -76,13 +90,16 @@ public function initialize(InputInterface $input, OutputInterface $output)

$this->objectManager = GeneralUtility::makeInstance(ObjectManager::class);
$this->UserRepository = $this->objectManager->get(UserRepository::class);
$this->AccessRepository = $this->objectManager->get(AccessRepository::class);
$this->persistenceManager = $this->objectManager->get(PersistenceManager::class);

$configurationManager = $this->objectManager->get('TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface');
$typoscriptConfiguration = $configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT);
if (!empty($extSettings = $typoscriptConfiguration['plugin.']['tx_femanager.']['settings.'])) {
$this->settings = $extSettings;
$this->UserRepository->setStoragePid($this->settings['pids.']['feUsers']);
$this->AccessRepository->setStoragePid($this->settings['pids.']['feUsers']);
$this->feUserGroups = explode(',', $this->settings['feUserGroups']);
}
}

Expand All @@ -108,8 +125,8 @@ protected function execute(InputInterface $input, OutputInterface $output)
return;
}

if (empty($this->settings['feUserGroup'])) {
$this->io->error('[DiGAS FE Management] Typoscript variable {plugin.tx_femanager.settings.feUserGroup} is not set. Abort.');
if (empty($this->settings['feUserGroups'])) {
$this->io->error('[DiGAS FE Management] Typoscript variable {plugin.tx_femanager.settings.feUserGroups} is not set. Abort.');
return;
}

Expand Down Expand Up @@ -145,4 +162,100 @@ protected function deleteFeUsers($feUsers)
}
return $deleteCounter;
}

/**
* Init user locale to send emails in users selected language
*
* @param \Slub\DigasFeManagement\Domain\Model\User $feUser
* @return void
*/
protected function initUserLocal(\Slub\DigasFeManagement\Domain\Model\User $feUser)
{
// hack to send english texts to user only if user registered on english page (sys_language_uid==1)
switch ($feUser->getLocale()) {
case '1':
setlocale(LC_ALL, 'en_US.utf8');
$GLOBALS['LANG']->init('en');
break;
case '0':
default:
setlocale(LC_ALL, 'de_DE.utf8');
$GLOBALS['LANG']->init('de');
break;
}
}

/**
* Prepare notification email for kitodo access
*
* @param User $feUser
* @param Access[] $userDocumentEntries
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException
*/
protected function notifyUser(User $feUser, array $userDocumentEntries)
{
// get fe_user data
if (!empty($feUser) && !empty($userDocumentEntries)) {
$documentsList = [];
foreach ($userDocumentEntries as $accessEntry) {
$documentsList[] = [
'recordId' => $accessEntry->getDlfDocument()->getRecordId(),
'documentTitle' => $accessEntry->getDlfDocument()->getTitle(),
'rejected' => $accessEntry->getRejected(),
'rejectedReason' => $accessEntry->getRejectedReason()
];

$notificationTimestamp = strtotime('now');
$this->updateAccessEntry($accessEntry, $notificationTimestamp);
}

$this->sendNotificationEmail($feUser, $documentsList);
}
}

/**
* Generate notification mail content
*
* @param array $documentsList List of kitodo documents
* @param string $emailTemplate Path to email template
* @param string $emailType Email type (html or text)
* @return string
*/
protected function generateNotificationEmail(array $documentsList, string $emailTemplate, string $emailType = 'text')
{
// generate email template by given emailType
$template = GeneralUtility::getFileAbsFileName($emailTemplate);
$htmlView = GeneralUtility::makeInstance(StandaloneView::class);
$htmlView->setFormat($emailType);
$htmlView->setTemplatePathAndFilename($template);
$htmlView->assignMultiple([
'loginPid' => $this->settings['pids.']['loginPage'],
'documentsList' => $documentsList
]);

return $htmlView->render();
}

/**
* Update access entry with access_granted_notification or expire_notification timestamp
*
* @param Access $accessEntry
* @param int $notificationTimestamp
*/
protected function updateAccessEntry(Access $accessEntry, int $notificationTimestamp)
{
// must be overridden in child class
}

/**
* Send email to fe_users for kitodo documents access
*
* @param User $feUser
* @param array $documentsList
*/
protected function sendNotificationEmail(User $feUser, array $documentsList)
{
// must be overridden in child class
}
}
175 changes: 175 additions & 0 deletions Classes/Command/KitodoAccessExpirationNotification.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
<?php

namespace Slub\DigasFeManagement\Command;

/***************************************************************
* Copyright notice
*
* (c) 2022 SLUB Dresden <[email protected]>
* All rights reserved
*
* This script is part of the TYPO3 project. The TYPO3 project is
* free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* The GNU General Public License can be found at
* http://www.gnu.org/copyleft/gpl.html.
*
* This script is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* This copyright notice MUST APPEAR in all copies of the script!
***************************************************************/

use Slub\DigasFeManagement\Domain\Model\Access;
use Slub\DigasFeManagement\Domain\Model\User;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use TYPO3\CMS\Core\Mail\MailMessage;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\MathUtility;
use TYPO3\CMS\Extbase\Utility\LocalizationUtility as ExtbaseLocalizationUtility;

/**
* Class KitodoAccessExpirationNotification
*/
class KitodoAccessExpirationNotification extends DigasBaseCommand
{
/**
* @var int Expiration timespan in days.
*/
protected $expirationTimestamp;

/**
* @param InputInterface $input
* @param OutputInterface $output
*/
public function initialize(InputInterface $input, OutputInterface $output)
{
parent::initialize($input, $output);
}

/**
* Configure the command by defining the name, options and arguments
*/
protected function configure()
{
$this->setDescription('[DiGAS FE Management] Notify fe_users about expiring kitodo documents.')
->addArgument(
'expirationTimestamp',
InputArgument::REQUIRED,
'Add a timespan in days (i.e. "365"). fe_users with expiring document access will get an information email.'
)->setHelp(
'This command informs fe_users with expiring kitodo document access.'
);
}

/**
* Executes the command
*
* @param InputInterface $input
* @param OutputInterface $output
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
// Initialize IO
parent::execute($input, $output);

if (MathUtility::canBeInterpretedAsInteger($input->getArgument('expirationTimestamp'))) {
$this->expirationTimestamp = MathUtility::forceIntegerInRange((int)$input->getArgument('expirationTimestamp'), 0);
}

if ($this->expirationTimestamp <= 0) {
$this->io->error('"expirationTimestamp" has to a positive integer value. Abort.');
return;
}

$time = new \DateTime();
$expirationTimestamp = $time->getTimestamp() + ((60 * 60 * 24) * $this->expirationTimestamp);

$this->io->text('Get fe_users with nearly expiration documents.');
// get fe users with requests for access loop
$expireAccessUsers = $this->AccessRepository->findExpirationUsers($expirationTimestamp);
$this->io->text(count($expireAccessUsers) . ' fe_users with expiring documents were found.');

if (!empty($expireAccessUsers)) {
foreach ($expireAccessUsers as $expireUser) {
/** @var User $feUser */
$feUser = $this->UserRepository->findByUid($expireUser->getFeUser());
$expiringAccessEntries = $this->AccessRepository->findExpiringEntriesByUser($expireUser->getFeUser(), $expirationTimestamp);

if (!empty($expiringAccessEntries)) {
$this->io->text(sprintf('Notify fe_user (UID: %s) with %s expiring documents.', $expireUser->getFeUser(), count($expiringAccessEntries)));

$this->notifyUser($feUser, $expiringAccessEntries);
$this->persistenceManager->persistAll();
}
}
}

$this->io->success('Task finished successfully.');

}

/**
* Update access model object and set accessGrantedNotification
*
* @param Access $accessEntry
* @param string $notificationTimestamp
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException
*/
protected function updateAccessEntry(Access $accessEntry, int $notificationTimestamp)
{
// update access entry with notification time
$accessEntry->setExpireNotification($notificationTimestamp);
$this->AccessRepository->update($accessEntry);
}

/**
* Send email to fe_users with expiring kitodo documents
*
* @param User $feUser
* @param array $documentsList
*/
protected function sendNotificationEmail(User $feUser, array $documentsList)
{
$this->initUserLocal($feUser);
$userEmail = $feUser->getEmail();
$userFullName = $feUser->getFullName();
if (!GeneralUtility::validEmail($userEmail)) {
$this->io->warning(sprintf('[DiGAS FE Management] Expiration notification warning to user (UID: %s) could not be sent. No valid email address.', $feUser->getUid()));
return;
}
$email = GeneralUtility::makeInstance(MailMessage::class);

$textEmail = $this->generateNotificationEmail(
$documentsList,
'EXT:digas_fe_management/Resources/Private/Templates/Email/Text/KitodoAccessExpirationNotification.html'
);
$htmlEmail = $this->generateNotificationEmail(
$documentsList,
'EXT:digas_fe_management/Resources/Private/Templates/Email/Html/KitodoAccessExpirationNotification.html',
'html'
);
$emailSubject = ExtbaseLocalizationUtility::translate('kitodoAccessExpirationNotification.email.subject', 'DigasFeManagement');

// Prepare and send the message
$email->setSubject($emailSubject)
->setFrom([
$this->settings['adminEmail'] => $this->settings['adminName']
])
->setTo([
$userEmail => $userFullName
])
->setBody($textEmail)
->addPart($htmlEmail, 'text/html')
->send();
}
}
Loading

0 comments on commit b6a4ead

Please sign in to comment.