Skip to content

Commit b6a4ead

Browse files
author
Alexander Bigga
authored
Merge pull request #3 from f-franz/master
Extend user and access management
2 parents 7c911b9 + 55ccbb5 commit b6a4ead

File tree

88 files changed

+5099
-445
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

88 files changed

+5099
-445
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
.vscode
2+
.idea

Classes/Command/DeleteDeactivatedAccountsCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
8484
$time = new \DateTime();
8585
$deleteTimestamp = $time->getTimestamp() - ((60 * 60 * 24) * $timespan);
8686

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

8989
if (!empty($feUsers)) {
9090
$deleteCounter = $this->deleteFeUsers($feUsers);

Classes/Command/DeleteInactiveAccountsCommand.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
8282
}
8383
$deleteTimespan = time() - (60 * 60 * (int)$timespan);
8484

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

8787
if (!empty($feUsers)) {
8888
$deleteCounter = $this->deleteFeUsers($feUsers);

Classes/Command/DigasBaseCommand.php

Lines changed: 115 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
* This copyright notice MUST APPEAR in all copies of the script!
2626
***************************************************************/
2727

28+
use Slub\DigasFeManagement\Domain\Model\Access;
29+
use Slub\DigasFeManagement\Domain\Model\User;
30+
use Slub\DigasFeManagement\Domain\Repository\AccessRepository;
2831
use Slub\DigasFeManagement\Domain\Repository\UserRepository;
2932
use Symfony\Component\Console\Command\Command;
3033
use Symfony\Component\Console\Input\InputInterface;
@@ -34,6 +37,7 @@
3437
use TYPO3\CMS\Core\Utility\GeneralUtility;
3538
use TYPO3\CMS\Extbase\Object\ObjectManager;
3639
use TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager;
40+
use TYPO3\CMS\Fluid\View\StandaloneView;
3741

3842
/**
3943
* Class DigasBaseCommand
@@ -51,6 +55,11 @@ class DigasBaseCommand extends Command
5155
*/
5256
protected $UserRepository;
5357

58+
/**
59+
* @var AccessRepository
60+
*/
61+
protected $AccessRepository;
62+
5463
/**
5564
* @var PersistenceManager
5665
*/
@@ -66,6 +75,11 @@ class DigasBaseCommand extends Command
6675
*/
6776
protected $settings;
6877

78+
/**
79+
* @var array
80+
*/
81+
protected $feUserGroups;
82+
6983
/**
7084
* @param InputInterface $input
7185
* @param OutputInterface $output
@@ -76,13 +90,16 @@ public function initialize(InputInterface $input, OutputInterface $output)
7690

7791
$this->objectManager = GeneralUtility::makeInstance(ObjectManager::class);
7892
$this->UserRepository = $this->objectManager->get(UserRepository::class);
93+
$this->AccessRepository = $this->objectManager->get(AccessRepository::class);
7994
$this->persistenceManager = $this->objectManager->get(PersistenceManager::class);
8095

8196
$configurationManager = $this->objectManager->get('TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface');
8297
$typoscriptConfiguration = $configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT);
8398
if (!empty($extSettings = $typoscriptConfiguration['plugin.']['tx_femanager.']['settings.'])) {
8499
$this->settings = $extSettings;
85100
$this->UserRepository->setStoragePid($this->settings['pids.']['feUsers']);
101+
$this->AccessRepository->setStoragePid($this->settings['pids.']['feUsers']);
102+
$this->feUserGroups = explode(',', $this->settings['feUserGroups']);
86103
}
87104
}
88105

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

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

@@ -145,4 +162,100 @@ protected function deleteFeUsers($feUsers)
145162
}
146163
return $deleteCounter;
147164
}
165+
166+
/**
167+
* Init user locale to send emails in users selected language
168+
*
169+
* @param \Slub\DigasFeManagement\Domain\Model\User $feUser
170+
* @return void
171+
*/
172+
protected function initUserLocal(\Slub\DigasFeManagement\Domain\Model\User $feUser)
173+
{
174+
// hack to send english texts to user only if user registered on english page (sys_language_uid==1)
175+
switch ($feUser->getLocale()) {
176+
case '1':
177+
setlocale(LC_ALL, 'en_US.utf8');
178+
$GLOBALS['LANG']->init('en');
179+
break;
180+
case '0':
181+
default:
182+
setlocale(LC_ALL, 'de_DE.utf8');
183+
$GLOBALS['LANG']->init('de');
184+
break;
185+
}
186+
}
187+
188+
/**
189+
* Prepare notification email for kitodo access
190+
*
191+
* @param User $feUser
192+
* @param Access[] $userDocumentEntries
193+
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
194+
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException
195+
*/
196+
protected function notifyUser(User $feUser, array $userDocumentEntries)
197+
{
198+
// get fe_user data
199+
if (!empty($feUser) && !empty($userDocumentEntries)) {
200+
$documentsList = [];
201+
foreach ($userDocumentEntries as $accessEntry) {
202+
$documentsList[] = [
203+
'recordId' => $accessEntry->getDlfDocument()->getRecordId(),
204+
'documentTitle' => $accessEntry->getDlfDocument()->getTitle(),
205+
'rejected' => $accessEntry->getRejected(),
206+
'rejectedReason' => $accessEntry->getRejectedReason()
207+
];
208+
209+
$notificationTimestamp = strtotime('now');
210+
$this->updateAccessEntry($accessEntry, $notificationTimestamp);
211+
}
212+
213+
$this->sendNotificationEmail($feUser, $documentsList);
214+
}
215+
}
216+
217+
/**
218+
* Generate notification mail content
219+
*
220+
* @param array $documentsList List of kitodo documents
221+
* @param string $emailTemplate Path to email template
222+
* @param string $emailType Email type (html or text)
223+
* @return string
224+
*/
225+
protected function generateNotificationEmail(array $documentsList, string $emailTemplate, string $emailType = 'text')
226+
{
227+
// generate email template by given emailType
228+
$template = GeneralUtility::getFileAbsFileName($emailTemplate);
229+
$htmlView = GeneralUtility::makeInstance(StandaloneView::class);
230+
$htmlView->setFormat($emailType);
231+
$htmlView->setTemplatePathAndFilename($template);
232+
$htmlView->assignMultiple([
233+
'loginPid' => $this->settings['pids.']['loginPage'],
234+
'documentsList' => $documentsList
235+
]);
236+
237+
return $htmlView->render();
238+
}
239+
240+
/**
241+
* Update access entry with access_granted_notification or expire_notification timestamp
242+
*
243+
* @param Access $accessEntry
244+
* @param int $notificationTimestamp
245+
*/
246+
protected function updateAccessEntry(Access $accessEntry, int $notificationTimestamp)
247+
{
248+
// must be overridden in child class
249+
}
250+
251+
/**
252+
* Send email to fe_users for kitodo documents access
253+
*
254+
* @param User $feUser
255+
* @param array $documentsList
256+
*/
257+
protected function sendNotificationEmail(User $feUser, array $documentsList)
258+
{
259+
// must be overridden in child class
260+
}
148261
}
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
<?php
2+
3+
namespace Slub\DigasFeManagement\Command;
4+
5+
/***************************************************************
6+
* Copyright notice
7+
*
8+
* (c) 2022 SLUB Dresden <[email protected]>
9+
* All rights reserved
10+
*
11+
* This script is part of the TYPO3 project. The TYPO3 project is
12+
* free software; you can redistribute it and/or modify
13+
* it under the terms of the GNU General Public License as published by
14+
* the Free Software Foundation; either version 3 of the License, or
15+
* (at your option) any later version.
16+
*
17+
* The GNU General Public License can be found at
18+
* http://www.gnu.org/copyleft/gpl.html.
19+
*
20+
* This script is distributed in the hope that it will be useful,
21+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
22+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23+
* GNU General Public License for more details.
24+
*
25+
* This copyright notice MUST APPEAR in all copies of the script!
26+
***************************************************************/
27+
28+
use Slub\DigasFeManagement\Domain\Model\Access;
29+
use Slub\DigasFeManagement\Domain\Model\User;
30+
use Symfony\Component\Console\Input\InputArgument;
31+
use Symfony\Component\Console\Input\InputInterface;
32+
use Symfony\Component\Console\Output\OutputInterface;
33+
use TYPO3\CMS\Core\Mail\MailMessage;
34+
use TYPO3\CMS\Core\Utility\GeneralUtility;
35+
use TYPO3\CMS\Core\Utility\MathUtility;
36+
use TYPO3\CMS\Extbase\Utility\LocalizationUtility as ExtbaseLocalizationUtility;
37+
38+
/**
39+
* Class KitodoAccessExpirationNotification
40+
*/
41+
class KitodoAccessExpirationNotification extends DigasBaseCommand
42+
{
43+
/**
44+
* @var int Expiration timespan in days.
45+
*/
46+
protected $expirationTimestamp;
47+
48+
/**
49+
* @param InputInterface $input
50+
* @param OutputInterface $output
51+
*/
52+
public function initialize(InputInterface $input, OutputInterface $output)
53+
{
54+
parent::initialize($input, $output);
55+
}
56+
57+
/**
58+
* Configure the command by defining the name, options and arguments
59+
*/
60+
protected function configure()
61+
{
62+
$this->setDescription('[DiGAS FE Management] Notify fe_users about expiring kitodo documents.')
63+
->addArgument(
64+
'expirationTimestamp',
65+
InputArgument::REQUIRED,
66+
'Add a timespan in days (i.e. "365"). fe_users with expiring document access will get an information email.'
67+
)->setHelp(
68+
'This command informs fe_users with expiring kitodo document access.'
69+
);
70+
}
71+
72+
/**
73+
* Executes the command
74+
*
75+
* @param InputInterface $input
76+
* @param OutputInterface $output
77+
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\InvalidQueryException
78+
*/
79+
protected function execute(InputInterface $input, OutputInterface $output)
80+
{
81+
// Initialize IO
82+
parent::execute($input, $output);
83+
84+
if (MathUtility::canBeInterpretedAsInteger($input->getArgument('expirationTimestamp'))) {
85+
$this->expirationTimestamp = MathUtility::forceIntegerInRange((int)$input->getArgument('expirationTimestamp'), 0);
86+
}
87+
88+
if ($this->expirationTimestamp <= 0) {
89+
$this->io->error('"expirationTimestamp" has to a positive integer value. Abort.');
90+
return;
91+
}
92+
93+
$time = new \DateTime();
94+
$expirationTimestamp = $time->getTimestamp() + ((60 * 60 * 24) * $this->expirationTimestamp);
95+
96+
$this->io->text('Get fe_users with nearly expiration documents.');
97+
// get fe users with requests for access loop
98+
$expireAccessUsers = $this->AccessRepository->findExpirationUsers($expirationTimestamp);
99+
$this->io->text(count($expireAccessUsers) . ' fe_users with expiring documents were found.');
100+
101+
if (!empty($expireAccessUsers)) {
102+
foreach ($expireAccessUsers as $expireUser) {
103+
/** @var User $feUser */
104+
$feUser = $this->UserRepository->findByUid($expireUser->getFeUser());
105+
$expiringAccessEntries = $this->AccessRepository->findExpiringEntriesByUser($expireUser->getFeUser(), $expirationTimestamp);
106+
107+
if (!empty($expiringAccessEntries)) {
108+
$this->io->text(sprintf('Notify fe_user (UID: %s) with %s expiring documents.', $expireUser->getFeUser(), count($expiringAccessEntries)));
109+
110+
$this->notifyUser($feUser, $expiringAccessEntries);
111+
$this->persistenceManager->persistAll();
112+
}
113+
}
114+
}
115+
116+
$this->io->success('Task finished successfully.');
117+
118+
}
119+
120+
/**
121+
* Update access model object and set accessGrantedNotification
122+
*
123+
* @param Access $accessEntry
124+
* @param string $notificationTimestamp
125+
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\IllegalObjectTypeException
126+
* @throws \TYPO3\CMS\Extbase\Persistence\Exception\UnknownObjectException
127+
*/
128+
protected function updateAccessEntry(Access $accessEntry, int $notificationTimestamp)
129+
{
130+
// update access entry with notification time
131+
$accessEntry->setExpireNotification($notificationTimestamp);
132+
$this->AccessRepository->update($accessEntry);
133+
}
134+
135+
/**
136+
* Send email to fe_users with expiring kitodo documents
137+
*
138+
* @param User $feUser
139+
* @param array $documentsList
140+
*/
141+
protected function sendNotificationEmail(User $feUser, array $documentsList)
142+
{
143+
$this->initUserLocal($feUser);
144+
$userEmail = $feUser->getEmail();
145+
$userFullName = $feUser->getFullName();
146+
if (!GeneralUtility::validEmail($userEmail)) {
147+
$this->io->warning(sprintf('[DiGAS FE Management] Expiration notification warning to user (UID: %s) could not be sent. No valid email address.', $feUser->getUid()));
148+
return;
149+
}
150+
$email = GeneralUtility::makeInstance(MailMessage::class);
151+
152+
$textEmail = $this->generateNotificationEmail(
153+
$documentsList,
154+
'EXT:digas_fe_management/Resources/Private/Templates/Email/Text/KitodoAccessExpirationNotification.html'
155+
);
156+
$htmlEmail = $this->generateNotificationEmail(
157+
$documentsList,
158+
'EXT:digas_fe_management/Resources/Private/Templates/Email/Html/KitodoAccessExpirationNotification.html',
159+
'html'
160+
);
161+
$emailSubject = ExtbaseLocalizationUtility::translate('kitodoAccessExpirationNotification.email.subject', 'DigasFeManagement');
162+
163+
// Prepare and send the message
164+
$email->setSubject($emailSubject)
165+
->setFrom([
166+
$this->settings['adminEmail'] => $this->settings['adminName']
167+
])
168+
->setTo([
169+
$userEmail => $userFullName
170+
])
171+
->setBody($textEmail)
172+
->addPart($htmlEmail, 'text/html')
173+
->send();
174+
}
175+
}

0 commit comments

Comments
 (0)