diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 30d7c1fc..7c0e9c3c 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -1,5 +1,19 @@ # Release notes +## Version 2024-11 +*Release date: ...* + +### Small changes +- Updated dependencies +- Updated Composer to 2.8.2 +- Remove email addresses from api output #109 +- Added possibility to view errors only from the log #81 +- Added logging for mailman sync #80 + +### Bug fix +- Fix: Course start dates are shown earlier in different timezone #113 +- Fix: User account can be approved before email address is confirmed #108 + ## Version 2024-10 *Release date: 2024-11-06* diff --git a/VERSION.txt b/VERSION.txt index 18b2c403..e9202af6 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -2024-10 \ No newline at end of file +2024-11 \ No newline at end of file diff --git a/composer.lock b/composer.lock index eda6f887..8c9ed0bb 100644 --- a/composer.lock +++ b/composer.lock @@ -703,16 +703,16 @@ }, { "name": "league/container", - "version": "4.2.2", + "version": "4.2.3", "source": { "type": "git", "url": "https://github.com/thephpleague/container.git", - "reference": "ff346319ca1ff0e78277dc2311a42107cc1aab88" + "reference": "72f9bebe7bd623007782a40f5ec305661ab706d8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/thephpleague/container/zipball/ff346319ca1ff0e78277dc2311a42107cc1aab88", - "reference": "ff346319ca1ff0e78277dc2311a42107cc1aab88", + "url": "https://api.github.com/repos/thephpleague/container/zipball/72f9bebe7bd623007782a40f5ec305661ab706d8", + "reference": "72f9bebe7bd623007782a40f5ec305661ab706d8", "shasum": "" }, "require": { @@ -773,7 +773,7 @@ ], "support": { "issues": "https://github.com/thephpleague/container/issues", - "source": "https://github.com/thephpleague/container/tree/4.2.2" + "source": "https://github.com/thephpleague/container/tree/4.2.3" }, "funding": [ { @@ -781,7 +781,7 @@ "type": "github" } ], - "time": "2024-03-13T13:12:53+00:00" + "time": "2024-10-23T12:06:58+00:00" }, { "name": "mobiledetect/mobiledetectlib", @@ -1362,16 +1362,16 @@ }, { "name": "symfony/config", - "version": "v6.4.8", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/config.git", - "reference": "12e7e52515ce37191b193cf3365903c4f3951e35" + "reference": "5ed4195a81d2352e0e4ce24e5f7e26fc794e7597" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/config/zipball/12e7e52515ce37191b193cf3365903c4f3951e35", - "reference": "12e7e52515ce37191b193cf3365903c4f3951e35", + "url": "https://api.github.com/repos/symfony/config/zipball/5ed4195a81d2352e0e4ce24e5f7e26fc794e7597", + "reference": "5ed4195a81d2352e0e4ce24e5f7e26fc794e7597", "shasum": "" }, "require": { @@ -1417,7 +1417,7 @@ "description": "Helps you find, load, combine, autofill and validate configuration values of any kind", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/config/tree/v6.4.8" + "source": "https://github.com/symfony/config/tree/v6.4.13" }, "funding": [ { @@ -1433,20 +1433,20 @@ "type": "tidelift" } ], - "time": "2024-05-31T14:49:08+00:00" + "time": "2024-10-25T15:07:50+00:00" }, { "name": "symfony/console", - "version": "v6.4.12", + "version": "v6.4.13", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "72d080eb9edf80e36c19be61f72c98ed8273b765" + "reference": "f793dd5a7d9ae9923e35d0503d08ba734cec1d79" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/72d080eb9edf80e36c19be61f72c98ed8273b765", - "reference": "72d080eb9edf80e36c19be61f72c98ed8273b765", + "url": "https://api.github.com/repos/symfony/console/zipball/f793dd5a7d9ae9923e35d0503d08ba734cec1d79", + "reference": "f793dd5a7d9ae9923e35d0503d08ba734cec1d79", "shasum": "" }, "require": { @@ -1511,7 +1511,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v6.4.12" + "source": "https://github.com/symfony/console/tree/v6.4.13" }, "funding": [ { @@ -1527,7 +1527,7 @@ "type": "tidelift" } ], - "time": "2024-09-20T08:15:52+00:00" + "time": "2024-10-09T08:40:40+00:00" }, { "name": "symfony/deprecation-contracts", @@ -1598,16 +1598,16 @@ }, { "name": "symfony/filesystem", - "version": "v7.1.5", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", - "reference": "61fe0566189bf32e8cfee78335d8776f64a66f5a" + "reference": "c835867b3c62bb05c7fe3d637c871c7ae52024d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/filesystem/zipball/61fe0566189bf32e8cfee78335d8776f64a66f5a", - "reference": "61fe0566189bf32e8cfee78335d8776f64a66f5a", + "url": "https://api.github.com/repos/symfony/filesystem/zipball/c835867b3c62bb05c7fe3d637c871c7ae52024d4", + "reference": "c835867b3c62bb05c7fe3d637c871c7ae52024d4", "shasum": "" }, "require": { @@ -1644,7 +1644,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.1.5" + "source": "https://github.com/symfony/filesystem/tree/v7.1.6" }, "funding": [ { @@ -1660,7 +1660,7 @@ "type": "tidelift" } ], - "time": "2024-09-17T09:16:35+00:00" + "time": "2024-10-25T15:11:02+00:00" }, { "name": "symfony/polyfill-ctype", @@ -2065,16 +2065,16 @@ }, { "name": "symfony/string", - "version": "v7.1.5", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "d66f9c343fa894ec2037cc928381df90a7ad4306" + "reference": "61b72d66bf96c360a727ae6232df5ac83c71f626" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/d66f9c343fa894ec2037cc928381df90a7ad4306", - "reference": "d66f9c343fa894ec2037cc928381df90a7ad4306", + "url": "https://api.github.com/repos/symfony/string/zipball/61b72d66bf96c360a727ae6232df5ac83c71f626", + "reference": "61b72d66bf96c360a727ae6232df5ac83c71f626", "shasum": "" }, "require": { @@ -2132,7 +2132,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.1.5" + "source": "https://github.com/symfony/string/tree/v7.1.6" }, "funding": [ { @@ -2148,7 +2148,7 @@ "type": "tidelift" } ], - "time": "2024-09-20T08:28:38+00:00" + "time": "2024-09-25T14:20:29+00:00" } ], "packages-dev": [ @@ -2514,16 +2514,16 @@ }, { "name": "composer/composer", - "version": "2.8.1", + "version": "2.8.2", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "e52b8672276cf436670cdd6bd5de4353740e83b2" + "reference": "6e543d03187c882ea1c6ba43add2467754427803" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/e52b8672276cf436670cdd6bd5de4353740e83b2", - "reference": "e52b8672276cf436670cdd6bd5de4353740e83b2", + "url": "https://api.github.com/repos/composer/composer/zipball/6e543d03187c882ea1c6ba43add2467754427803", + "reference": "6e543d03187c882ea1c6ba43add2467754427803", "shasum": "" }, "require": { @@ -2608,7 +2608,7 @@ "irc": "ircs://irc.libera.chat:6697/composer", "issues": "https://github.com/composer/composer/issues", "security": "https://github.com/composer/composer/security/policy", - "source": "https://github.com/composer/composer/tree/2.8.1" + "source": "https://github.com/composer/composer/tree/2.8.2" }, "funding": [ { @@ -2624,7 +2624,7 @@ "type": "tidelift" } ], - "time": "2024-10-04T09:31:01+00:00" + "time": "2024-10-29T15:12:11+00:00" }, { "name": "composer/metadata-minifier", @@ -5593,16 +5593,16 @@ }, { "name": "symfony/finder", - "version": "v7.1.4", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "d95bbf319f7d052082fb7af147e0f835a695e823" + "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/d95bbf319f7d052082fb7af147e0f835a695e823", - "reference": "d95bbf319f7d052082fb7af147e0f835a695e823", + "url": "https://api.github.com/repos/symfony/finder/zipball/2cb89664897be33f78c65d3d2845954c8d7a43b8", + "reference": "2cb89664897be33f78c65d3d2845954c8d7a43b8", "shasum": "" }, "require": { @@ -5637,7 +5637,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.1.4" + "source": "https://github.com/symfony/finder/tree/v7.1.6" }, "funding": [ { @@ -5653,7 +5653,7 @@ "type": "tidelift" } ], - "time": "2024-08-13T14:28:19+00:00" + "time": "2024-10-01T08:31:23+00:00" }, { "name": "symfony/polyfill-php73", @@ -5889,16 +5889,16 @@ }, { "name": "symfony/process", - "version": "v7.1.5", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "5c03ee6369281177f07f7c68252a280beccba847" + "reference": "6aaa189ddb4ff6b5de8fa3210f2fb42c87b4d12e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/5c03ee6369281177f07f7c68252a280beccba847", - "reference": "5c03ee6369281177f07f7c68252a280beccba847", + "url": "https://api.github.com/repos/symfony/process/zipball/6aaa189ddb4ff6b5de8fa3210f2fb42c87b4d12e", + "reference": "6aaa189ddb4ff6b5de8fa3210f2fb42c87b4d12e", "shasum": "" }, "require": { @@ -5930,7 +5930,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.1.5" + "source": "https://github.com/symfony/process/tree/v7.1.6" }, "funding": [ { @@ -5946,20 +5946,20 @@ "type": "tidelift" } ], - "time": "2024-09-19T21:48:23+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "symfony/var-dumper", - "version": "v7.1.5", + "version": "v7.1.6", "source": { "type": "git", "url": "https://github.com/symfony/var-dumper.git", - "reference": "e20e03889539fd4e4211e14d2179226c513c010d" + "reference": "cb5bd55a6b8c2c1c7fb68b0aeae0e257948a720c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/var-dumper/zipball/e20e03889539fd4e4211e14d2179226c513c010d", - "reference": "e20e03889539fd4e4211e14d2179226c513c010d", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/cb5bd55a6b8c2c1c7fb68b0aeae0e257948a720c", + "reference": "cb5bd55a6b8c2c1c7fb68b0aeae0e257948a720c", "shasum": "" }, "require": { @@ -6013,7 +6013,7 @@ "dump" ], "support": { - "source": "https://github.com/symfony/var-dumper/tree/v7.1.5" + "source": "https://github.com/symfony/var-dumper/tree/v7.1.6" }, "funding": [ { @@ -6029,7 +6029,7 @@ "type": "tidelift" } ], - "time": "2024-09-16T10:07:02+00:00" + "time": "2024-09-25T14:20:29+00:00" }, { "name": "theseer/tokenizer", diff --git a/composer.phar b/composer.phar index e3253ebc..b58b584b 100644 Binary files a/composer.phar and b/composer.phar differ diff --git a/src/Command/CourseRemindersCommand.php b/src/Command/CourseRemindersCommand.php index 778fd4f0..b5374faf 100644 --- a/src/Command/CourseRemindersCommand.php +++ b/src/Command/CourseRemindersCommand.php @@ -12,6 +12,10 @@ class CourseRemindersCommand extends Command { + public $Courses = null; + public $Users = null; + public $Logentries = null; + private function getModeratorEmails() { $moderators = $this->Users->find()->where([ @@ -71,6 +75,9 @@ public function execute(Arguments $args, ConsoleIo $io) $this->loadModel('Logentries'); $waitPeriod = new FrozenTime('-10 Days'); // no mail will be sent within $waitPeriod days after previous mail + // needed for logging + $scriptName = str_replace('Command', '', basename(__FILE__, '.php')); + // clean up old log entries after 3 months $oldEntries = $this->Logentries->find()->where(['created <' => new FrozenTime('-3 Months')]); $io->out('Cleaned up old log entries: ' . $oldEntries->count()); @@ -103,7 +110,7 @@ public function execute(Arguments $args, ConsoleIo $io) $this->Logentries->createLogEntry( '50', '586', - basename(__FILE__, '.php'), + $scriptName, 'Spam guard', $errorMessage ); @@ -166,7 +173,7 @@ public function execute(Arguments $args, ConsoleIo $io) $this->Logentries->createLogEntry( '90', '586', - basename(__FILE__, '.php'), + $scriptName, 'DB error', $errorMessage ); @@ -177,7 +184,7 @@ public function execute(Arguments $args, ConsoleIo $io) $this->Logentries->createLogEntry( '30', '586', - basename(__FILE__, '.php'), + $scriptName, 'Sent reminder mail', $logDescription ); @@ -208,7 +215,7 @@ public function execute(Arguments $args, ConsoleIo $io) $this->Logentries->createLogEntry( '90', '586', - basename(__FILE__, '.php'), + $scriptName, $logSubject, $logDescription ); @@ -228,7 +235,7 @@ public function execute(Arguments $args, ConsoleIo $io) $this->Logentries->createLogEntry( '10', '586', - basename(__FILE__, '.php'), + $scriptName, 'Finished. Stats:', $logDescription ); diff --git a/src/Command/ReviewRemindersCommand.php b/src/Command/ReviewRemindersCommand.php index c5521b79..c13decbb 100644 --- a/src/Command/ReviewRemindersCommand.php +++ b/src/Command/ReviewRemindersCommand.php @@ -97,7 +97,7 @@ public function execute(Arguments $args, ConsoleIo $io) $this->loadModel('Users'); $this->loadModel('Logentries'); $io->out('~~~ Started Review Reminders ~~~'); - $issuesUrl = 'https://github.com/acdh-oeaw/dhcr-main/labels/InReview'; + $issuesUrl = 'https://github.com/acdh-oeaw/dhcr-main/labels/inreview'; $content = file_get_contents($issuesUrl); $pattern = '/\b\d+\sOpen\b/i'; if (preg_match($pattern, $content, $lines)) { diff --git a/src/Controller/LogentriesController.php b/src/Controller/LogentriesController.php index 0aacaa9e..2e9769dd 100644 --- a/src/Controller/LogentriesController.php +++ b/src/Controller/LogentriesController.php @@ -32,5 +32,32 @@ public function index() $query = $this->Logentries->find('all', ['order' => ['Logentries.id' => 'DESC']])->contain(['LogentryCodes', 'Users']); $this->set('logentries', $this->paginate($query)); $this->set(compact('user')); // required for contributors menu + $this->render('show-entries'); + } + + public function errors() + { + $user = $this->Authentication->getIdentity(); + if (!$user->is_admin) { + $this->Flash->error(__('Not authorized to logentries errors')); + return $this->redirect(['controller' => 'Dashboard', 'action' => 'index']); + } + // Set breadcrums + $breadcrumTitles[0] = 'Category Lists'; + $breadcrumControllers[0] = 'Dashboard'; + $breadcrumActions[0] = 'categoryLists'; + $breadcrumTitles[1] = 'Log Entries'; + $breadcrumControllers[1] = 'Logentries'; + $breadcrumActions[1] = 'index'; + $breadcrumTitles[2] = 'Errors'; + $breadcrumControllers[2] = 'Logentries'; + $breadcrumActions[2] = 'errors'; + $this->set((compact('breadcrumTitles', 'breadcrumControllers', 'breadcrumActions'))); + $query = $this->Logentries->find('all', ['order' => ['Logentries.id' => 'DESC']]) + ->where(['logentry_code_id >=' => '50']) + ->contain(['LogentryCodes', 'Users']); + $this->set('logentries', $this->paginate($query)); + $this->set(compact('user')); // required for contributors menu + $this->render('show-entries'); } } diff --git a/src/Controller/UsersController.php b/src/Controller/UsersController.php index 82922a91..0b7c2714 100644 --- a/src/Controller/UsersController.php +++ b/src/Controller/UsersController.php @@ -16,6 +16,7 @@ class UsersController extends AppController public $Institutions = null; public $InviteTranslations = null; + public $Logentries = null; public const ALLOW_UNAUTHENTICATED = [ 'signIn', @@ -492,7 +493,8 @@ public function approve($key = null) ->contain('Institutions') ->where([ 'approved' => 0, - 'active' => 1 + 'active' => 1, + 'email_verified' => 1 ]); $this->set('users', $this->paginate($query)); $usersCount = $this->Users->find()->where([ @@ -784,23 +786,47 @@ public function newsletter() if ($subscriptionStatusNew == 1) { $requestUrl = env('LIST_SUBSCRIBE_URL'); $responseText = 'Successfully subscribed'; // response contains "Successfully subscribed:" + $logAction = 'Subscribe mailinglist'; } else { $requestUrl = env('LIST_UNSUBSCRIBE_URL'); $responseText = 'Successfully unsubscribed'; // response contains "Successfully Unsubscribed:" + $logAction = 'Unsubscribe mailinglist'; } $requestUrl .= $user->email . '&adminpw=' . env('LIST_ADMIN_PWD'); + // prepare logging + $this->loadModel('Logentries'); + $scriptName = basename(__FILE__, '.php'); + // request $html = file_get_contents($requestUrl); if (stripos($html, $responseText) > 0) { // mailman processed action $user = $this->Users->patchEntity($user, $this->request->getData()); if ($this->Users->save($user)) { $this->Flash->success($responseText); + // log success + $this->Logentries->createLogEntry( + '10', + '586', + $scriptName, + $logAction, + $responseText + ); return $this->redirect(['controller' => 'Dashboard', 'action' => 'profileSettings']); } else { - $this->Flash->error('Error: Subscription status not saved in DB.'); + $errorMessage = 'Subscription status not saved in DB'; + $this->Flash->error('Error: ' .$errorMessage); } } else { // invalid response from mailman - $this->Flash->error('Error: Subscription change not processed external.'); + $errorMessage = 'Subscription change not processed external'; + $this->Flash->error('Error: ' .$errorMessage); } + // log error + $this->Logentries->createLogEntry( + '50', + '586', + $scriptName, + $logAction, + $errorMessage + ); } } $this->viewBuilder()->setLayout('contributors'); diff --git a/templates/Logentries/index.php b/templates/Logentries/show_entries.php similarity index 77% rename from templates/Logentries/index.php rename to templates/Logentries/show_entries.php index 35ccae34..338f8759 100644 --- a/templates/Logentries/index.php +++ b/templates/Logentries/show_entries.php @@ -13,16 +13,26 @@
+
= $this->Paginator->sort('id') ?> | = $this->Paginator->sort('logentry_code_id', 'Type') ?> | -= $this->Paginator->sort('user_id') ?> | = $this->Paginator->sort('source_name', 'Application Source') ?> | = $this->Paginator->sort('subject', 'Action') ?> | = $this->Paginator->sort('description', 'Details') ?> | -= $this->Paginator->sort('cleared') ?> | = $this->Paginator->sort('created', ['label' => 'Date & Time']) ?> | ||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
= $this->Number->format($logentry->id) ?> | = $logentry->logentry_code->id . ' - ' . $logentry->logentry_code->name ?> | -= $this->Html->link( - $logentry->user->id, - ['controller' => 'Users', 'action' => 'view', $logentry->user->id], - ['title' => $logentry->user->first_name . ' ' . $logentry->user->last_name] - ) ?> | = h($logentry->source_name) ?> | = h($logentry->subject) ?> | = $this->Text->autoParagraph($logentry->description) ?> | -= ($logentry->cleared ? "Yes" : "No") ?> | = h($logentry->created->i18nFormat('yyyy-MM-dd HH:mm')) ?> UTC | ||||||
+ |
|