diff --git a/Events.php b/Events.php index 20d7bc4..0f1a3d7 100644 --- a/Events.php +++ b/Events.php @@ -283,6 +283,17 @@ public static function onAccountSettingsMenuInit($event) } } + public static function onBeforeValidate($event) + { + $registrationForm = $event->sender; + $minimumAge = Yii::$app->getModule('legal')->getMinimumAge(); + + if ($minimumAge > 0) { + $ageValidator = new validators\AgeValidator(['minimumAge' => $minimumAge]); + $ageValidator->validateAttribute($registrationForm, 'birthday'); + } + } + /** * Callback on daily cron job run */ diff --git a/config.php b/config.php index f5fce73..09b2f3a 100644 --- a/config.php +++ b/config.php @@ -7,6 +7,7 @@ use humhub\modules\content\widgets\richtext\ProsemirrorRichText; use humhub\modules\user\models\forms\Registration; use humhub\modules\user\widgets\AccountSettingsMenu; +use humhub\modules\user\models\Profile; use humhub\widgets\FooterMenu; use humhub\widgets\LayoutAddons; @@ -30,5 +31,6 @@ ['class' => ProsemirrorRichText::class, 'event' => ProsemirrorRichText::EVENT_AFTER_RUN, 'callback' => ['humhub\modules\legal\Events', 'onAfterRunRichText']], ['class' => AccountSettingsMenu::class, 'event' => AccountSettingsMenu::EVENT_INIT, 'callback' => ['humhub\modules\legal\Events', 'onAccountSettingsMenuInit']], ['class' => CronController::class, 'event' => CronController::EVENT_ON_DAILY_RUN, 'callback' => ['humhub\modules\legal\Events', 'onCronDailyRun']], + ['class' => Profile::class, 'event' => Profile::EVENT_BEFORE_VALIDATE, 'callback' => ['humhub\modules\legal\Events', 'onBeforeValidate']], ], ]; diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index b6baf78..834bfb3 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -4,6 +4,7 @@ Changelog 1.4.3 (Unreleased) -------------------------- - Fix #85: Fix downloading of large user export data file +- Enh: Check User Birthday field - Enh #90: Use PHP CS Fixer 1.4.2 (September 13, 2024) diff --git a/tests/codeception/acceptance/LegalCest.php b/tests/codeception/acceptance/LegalCest.php index 49c55e3..81a509c 100644 --- a/tests/codeception/acceptance/LegalCest.php +++ b/tests/codeception/acceptance/LegalCest.php @@ -136,4 +136,48 @@ public function testAgeVerification(AcceptanceTester $I) $I->amUser1(true); $I->dontSee($title, '.panel-heading'); } + + public function testAgeValidation(AcceptanceTester $I) + { + $I->wantTo('test age validation during registration and profile update'); + $minimumAge = 18; + + $I->amAdmin(); + $I->amGoingTo('enable age verification'); + $I->enableAgeVerification($minimumAge); + + // Test registration with valid age + $I->amGoingTo('test registration with valid age'); + $I->amOnRoute('/user/registration'); + $I->fillField('Registration[username]', 'validAgeUser'); + $I->fillField('Registration[email]', 'validage@example.com'); + $I->fillField('Registration[password]', 'ValidPassword123'); + $I->fillField('Registration[birthday]', date('Y-m-d', strtotime("-{$minimumAge} years -1 day"))); + $I->click('Register'); + $I->dontSee('You must be at least ' . $minimumAge . ' years old.'); + + // Test registration with invalid age + $I->amGoingTo('test registration with invalid age'); + $I->amOnRoute('/user/registration'); + $I->fillField('Registration[username]', 'invalidAgeUser'); + $I->fillField('Registration[email]', 'invalidage@example.com'); + $I->fillField('Registration[password]', 'InvalidPassword123'); + $I->fillField('Registration[birthday]', date('Y-m-d', strtotime("-{$minimumAge} years +1 day"))); + $I->click('Register'); + $I->see('You must be at least ' . $minimumAge . ' years old.'); + + // Test profile update with invalid age + $I->amGoingTo('test profile update with invalid age'); + $I->amUser1(true); + $I->amOnRoute('/user/account/edit'); + $I->fillField('Profile[birthday]', date('Y-m-d', strtotime("-{$minimumAge} years +1 day"))); + $I->click('Save'); + $I->see('You must be at least ' . $minimumAge . ' years old.'); + + // Test profile update with valid age + $I->amGoingTo('test profile update with valid age'); + $I->fillField('Profile[birthday]', date('Y-m-d', strtotime("-{$minimumAge} years -1 day"))); + $I->click('Save'); + $I->dontSee('You must be at least ' . $minimumAge . ' years old.'); + } } diff --git a/validators/AgeValidator.php b/validators/AgeValidator.php new file mode 100644 index 0000000..2ea3f8a --- /dev/null +++ b/validators/AgeValidator.php @@ -0,0 +1,57 @@ +minimumAge === null) { + $this->minimumAge = Yii::$app->getModule('legal')->getMinimumAge(); + } + } + + /** + * Validates the age of the user based on the given attribute value. + * + * @param \yii\base\Model $model the data model being validated + * @param string $attribute the name of the attribute to be validated + */ + public function validateAttribute($model, $attribute) + { + $value = $model->$attribute; + if (!$value instanceof DateTime) { + try { + $value = new DateTime($value); + } catch (\Exception $e) { + $this->addError($model, $attribute, Yii::t('LegalModule.base', 'Invalid date format.')); + return; + } + } + + $today = new DateTime(); + $age = $today->diff($value)->y; + + if ($age < $this->minimumAge) { + $message = Yii::t('LegalModule.base', 'You must be at least {age} years old.', ['age' => $this->minimumAge]); + $this->addError($model, $attribute, $message); + } + } +}