Skip to content

Commit 85a2454

Browse files
authored
add preview confirmation workflow (#209)
1 parent 073ed0b commit 85a2454

21 files changed

+118
-81
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ Add frontend user authentication and document restriction to pimcore.
1111

1212
| Release | Supported Pimcore Versions | Supported Symfony Versions | Release Date | Maintained | Branch |
1313
|---------|-----------------------------------|----------------------------|--------------|----------------|----------|
14-
| **5.x** | `11.0` | `6.2` | 28.09.2023 | Feature Branch | master |
14+
| **5.x** | `11.0` | `6.4` | 28.09.2023 | Feature Branch | master |
1515
| **4.x** | `10.5 - 10.6` | `5.4` | 22.11.2021 | Unsupported | 4.x |
1616
| **3.x** | `6.0` - `6.8` | `3.4`, `^4.4` | 21.07.2019 | Unsupported | 3.x |
1717
| **2.5** | `5.4`, `5.5`, `5.6`, `5.7`, `5.8` | `3.4` | 18.07.2019 | Unsupported | 2.5 |
@@ -32,7 +32,7 @@ Please read the installation instructions before going deep with Members!
3232

3333
```json
3434
"require" : {
35-
"dachcom-digital/members" : "~5.1.0"
35+
"dachcom-digital/members" : "~5.2.0"
3636
}
3737
```
3838

@@ -167,6 +167,6 @@ Before updating, please [check our upgrade notes!](UPGRADE.md)
167167
## License
168168
**DACHCOM.DIGITAL AG**, Löwenhofstrasse 15, 9424 Rheineck, Schweiz
169169
[dachcom.com](https://www.dachcom.com), [email protected]
170-
Copyright © 2024 DACHCOM.DIGITAL. All rights reserved.
170+
Copyright © 2025 DACHCOM.DIGITAL. All rights reserved.
171171

172172
For licensing details please visit [LICENSE.md](LICENSE.md)

UPGRADE.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# Upgrade Notes
22

33
## 5.1.0
4+
- [NEW FEATURE] "Preview confirmation" workflow added to avoid registration confirmation by prefetching email processes.
5+
Read more about it [here](./docs/60_RegistrationTypes.md#email-prefetching).
6+
This also comes with a new template: `@Members/registration/confirm_preview.html.twig` and also two new translations (
7+
`members.registration.confirm_preview`, `members.registration.complete_confirmation`)
48
- [LICENSE] Dual-License with GPL and Dachcom Commercial License (DCL) added
59

610
### 5.0.3

config/install/translations/frontend.csv

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
"members.registration.confirmed","Glückwunsch %username%, Ihr Benutzerkonto ist jetzt bestätigt.","Congrats %username%, your account is now activated."
1717
"members.registration.already_confirmed_or_not_found","Dieses Benutzerkonto wurde bereits bestätigt oder existiert nicht.","This user account has already been confirmed or does not exist."
1818
"members.registration.back","Zurück zur ursprünglichen Seite.","Back to the originating page."
19+
"members.registration.confirm_preview","Hallo %username%, bitte bestätige nun deine Registrierung!","Hello %username%, please confirm your registration now!"
20+
"members.registration.complete_confirmation","Registrierung abschliessen","Complete registration"
1921
"members.registration.submit","Registrieren","Register"
2022
"members.registration.flash.user_created","Der Benutzer wurde erfolgreich erstellt.","The user has been created successfully."
2123
"members.resetting.check_email","Eine E-Mail wurde verschickt. Sie beinhaltet einen Link zum Zurücksetzen des Passwortes. Hinweis: Ein neues Passwort kann nur alle %tokenLifetime% Stunden beantragt werden. Eventuell wurde diese E-Mail als Spam markiert, wenn sie nicht angekommen ist.","An email has been sent. It contains a link you must click to reset your password. Note: You can only request a new password once within %tokenLifetime% hours. If you don't get an email check your spam folder or try again."

config/pimcore/routing/registration.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ members_user_registration_check_admin:
1111
path: /check-admin
1212
defaults: { _controller: MembersBundle\Controller\RegistrationController::checkAdminAction }
1313
methods: [GET]
14+
members_user_registration_confirm_preview:
15+
path: /confirm-preview/{token}
16+
defaults: { _controller: MembersBundle\Controller\RegistrationController::confirmPreviewAction }
17+
methods: [ GET ]
1418
members_user_registration_confirm:
1519
path: /confirm/{token}
1620
defaults: { _controller: MembersBundle\Controller\RegistrationController::confirmAction }

docs/60_RegistrationTypes.md

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,49 @@ Name: `confirm_by_mail`
66

77
> This is the default value.
88
9-
After registration the user will receive a confirmation mail with a confirmation url. By clicking on that link the user gets automatically activated.
9+
After registration the user will receive a confirmation mail with a confirmation url.
10+
By clicking on that link the user gets automatically activated.
1011

1112
If `send_admin_mail_after_register` is enabled, the system will send a notification mail to a defined admin.
1213

14+
#### Email prefetching
15+
16+
> [!IMPORTANT]
17+
> Some email providers have spam detection or security features that prefetch URLs from incoming emails
18+
> (e.g., Safe Links in Microsoft Defender for Office 365).
19+
20+
To prevent unintended automatic activations, you can enable a "preview confirmation" page.
21+
This requires users to manually confirm their registration by clicking an additional button.
22+
23+
This feature is disabled by default. To enable it, update your configuration as follows:
24+
25+
```yaml
26+
27+
members:
28+
enable_preview_confirmation: true # default is false
29+
```
30+
31+
When enabled, users will first be redirected to /confirm-preview/{token},
32+
where they must confirm their registration manually.
33+
34+
***
35+
1336
### Confirm By Admin
1437
Name: `confirm_by_admin`
1538

1639
After registration the user has to wait until a authorized admin activates the user in backend.
1740

1841
If `send_user_mail_after_confirmed` is enabled, the system will send a notification mail to user.
1942

43+
***
44+
2045
### Confirm Instant
2146
Name: `confirm_instant`
2247

2348
After registration the user gets automatically logged in without any further actions.
2449

50+
***
51+
2552
## Configuration
2653
Add those lines to your `config/config.yaml`:
2754

@@ -37,6 +64,8 @@ members:
3764
send_user_mail_after_confirmed: false
3865
```
3966

67+
***
68+
4069
## Registration Types with SSO
4170
If you're using the [SSO feature](./SSO/10_Overview.md), you may want to define some independent mail workflows.
4271
If Members detects an SSO registration process, you're able to define the registration type via the `post_register_type_oauth` flag.

src/Controller/RegistrationController.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,22 @@ public function checkAdminAction(Request $request): Response
129129
return $this->renderTemplate('@Members/registration/check_admin.html.twig', ['user' => $user]);
130130
}
131131

132+
public function confirmPreviewAction(Request $request, string $token): Response
133+
{
134+
$user = $this->userManager->findUserByConfirmationToken($token);
135+
136+
if ($user === null) {
137+
throw new NotFoundHttpException(sprintf('The user with confirmation token "%s" does not exist', $token));
138+
}
139+
140+
$confirmationUrl = $this->generateUrl('members_user_registration_confirm', ['token' => $user->getConfirmationToken()]);
141+
142+
return $this->renderTemplate('@Members/registration/confirm_preview.html.twig', [
143+
'user' => $user,
144+
'confirmationUrl' => $confirmationUrl,
145+
]);
146+
}
147+
132148
public function confirmAction(Request $request, string $token): Response
133149
{
134150
$user = $this->userManager->findUserByConfirmationToken($token);

src/DependencyInjection/Configuration.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ public function getConfigTreeBuilder()
3838
->children()
3939
->booleanNode('send_admin_mail_after_register')->defaultFalse()->end()
4040
->booleanNode('send_user_mail_after_confirmed')->defaultFalse()->end()
41+
->booleanNode('enable_preview_confirmation')->defaultFalse()->end()
4142
->enumNode('post_register_type')
4243
->values($validPostRegisterTypes)
4344
->defaultValue('confirm_by_mail')

src/Mailer/Mailer.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,12 @@ public function __construct(
3030

3131
public function sendConfirmationEmailMessage(UserInterface $user): void
3232
{
33+
$route = $this->configuration->getConfig('enable_preview_confirmation') === true
34+
? 'members_user_registration_confirm_preview'
35+
: 'members_user_registration_confirm';
36+
3337
$template = $this->getMailTemplatePath('register_confirm', $user);
34-
$url = $this->router->generate('members_user_registration_confirm', ['token' => $user->getConfirmationToken()], UrlGeneratorInterface::ABSOLUTE_URL);
38+
$url = $this->router->generate($route, ['token' => $user->getConfirmationToken()], UrlGeneratorInterface::ABSOLUTE_URL);
3539

3640
$mailParams = [
3741
'user' => $user,
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
{% extends '@Members/layout.html.twig' %}
2+
3+
{% block members_user_content %}
4+
{% set user_name = user is not null ? user.username|default(user.email) : '' %}
5+
<p>{{ 'members.registration.confirm_preview'|trans({ '%username%': user_name }) }}</p>
6+
{% if confirmationUrl %}
7+
<p><a class="btn btn-info btn-sm" href="{{ confirmationUrl }}">{{ 'members.registration.complete_confirmation'|trans }}</a></p>
8+
{% endif %}
9+
{% endblock members_user_content %}

tests/Unit/Config/ConfigurationTest.php

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,7 @@
77

88
class ConfigurationTest extends DachcomBundleTestCase
99
{
10-
/**
11-
* @throws \Codeception\Exception\ModuleException
12-
*/
13-
public function testConfigArrayGetter()
10+
public function testConfigArrayGetter(): void
1411
{
1512
$configuration = $this->getContainer()->get(Configuration::class);
1613
$adminConfig = $configuration->getConfigArray();
@@ -19,10 +16,7 @@ public function testConfigArrayGetter()
1916
$this->assertArrayHasKey('send_admin_mail_after_register', $adminConfig);
2017
}
2118

22-
/**
23-
* @throws \Codeception\Exception\ModuleException
24-
*/
25-
public function testConfigSlotGetter()
19+
public function testConfigSlotGetter(): void
2620
{
2721
$configuration = $this->getContainer()->get(Configuration::class);
2822
$configSlot = $configuration->getConfig('post_register_type');

0 commit comments

Comments
 (0)