Skip to content

Commit 5bb817d

Browse files
committed
Add User Agent info to email
1 parent e3399d3 commit 5bb817d

File tree

7 files changed

+126
-19
lines changed

7 files changed

+126
-19
lines changed

composer.json

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
"birke/rememberme": "^2.0",
2626
"composer/semver": "^3.2.4",
2727
"doctrine/dbal": "^3.5",
28+
"donatj/phpuseragentparser": "^1.10",
2829
"ext-gd": "*",
2930
"ezyang/htmlpurifier": "^4.7.0",
3031
"filp/whoops": "^2.14",
@@ -77,6 +78,15 @@
7778
"slam/phpstan-extensions": "^6.0",
7879
"symplify/monorepo-builder": "^11.2"
7980
},
81+
"replace": {
82+
"userfrosting/framework": "6.0.0-alpha.4",
83+
"userfrosting/sprinkle-account": "6.0.0-alpha.4",
84+
"userfrosting/sprinkle-admin": "6.0.0-alpha.4",
85+
"userfrosting/sprinkle-core": "6.0.0-alpha.4",
86+
"userfrosting/userfrosting": "6.0.0-alpha.4"
87+
},
88+
"minimum-stability": "dev",
89+
"prefer-stable": true,
8090
"autoload": {
8191
"psr-4": {
8292
"UserFrosting\\": "packages/framework/src",
@@ -95,14 +105,5 @@
95105
"UserFrosting\\Tests\\App\\": "packages/skeleton/app/tests/",
96106
"Workers\\MonoRepo\\": "utils/"
97107
}
98-
},
99-
"replace": {
100-
"userfrosting/framework": "6.0.0-alpha.4",
101-
"userfrosting/sprinkle-account": "6.0.0-alpha.4",
102-
"userfrosting/sprinkle-admin": "6.0.0-alpha.4",
103-
"userfrosting/sprinkle-core": "6.0.0-alpha.4",
104-
"userfrosting/userfrosting": "6.0.0-alpha.4"
105-
},
106-
"minimum-stability": "dev",
107-
"prefer-stable": true
108+
}
108109
}

packages/sprinkle-account/app/templates/mail/code.html.twig

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,28 @@
33
{% endblock %}
44

55
{% block body %}
6-
<p>Dear {{user.first_name}},
7-
</p>
6+
<p>Dear {{user.first_name}},</p>
7+
8+
<p>Enter the 6-digit code below to verify your identity and access your account with <a href="{{site.uri.public}}">{{site.title}}</a>.</p>
9+
10+
<h2>{{code}}</h2>
11+
812
<p>
9-
Enter the 6-digit code below to verify your identity and access your account with <a href="{{site.uri.public}}">{{site.title}}</a>.
13+
Thank you for helping us keep your account secure.<br />The {{site.title}} Team
1014
</p>
11-
<h3>{{code}}</h3>
12-
<p>
13-
Thank you for helping us keep your account secure.
14-
The {{site.title}} Team
15+
16+
<p style="font-size: 0.8em; color: #999;">
17+
This email was sent to you because you requested a verification code for your account. If you did not request this code, please ignore this email.<br />
18+
If you have any questions, please contact us at <a href="mailto:{{site.email}}">{{site.email}}</a>.
19+
</p>
20+
21+
<p style="font-size: 0.8em; color: #999;">
22+
Request Details:
23+
<ul style="font-size: 0.8em; color: #999;">
24+
<li><strong>Date</strong>: {{date|date('l, F j, Y H:i:s')}}</li>
25+
<li><strong>Operating System</strong>: {{user_agent.platform}}</li>
26+
<li><strong>Platform</strong>: {{user_agent.browser}} {{user_agent.version}}</li>
27+
<li><strong>IP Address</strong>: {{user_agent.ip}}</li>
28+
</ul>
1529
</p>
1630
{% endblock %}

packages/sprinkle-core/app/src/Core.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
use UserFrosting\Sprinkle\Core\Twig\Extensions\CsrfExtension;
9797
use UserFrosting\Sprinkle\Core\Twig\Extensions\I18nExtension;
9898
use UserFrosting\Sprinkle\Core\Twig\Extensions\RoutesExtension;
99+
use UserFrosting\Sprinkle\Core\Twig\Extensions\UserAgentExtension;
99100
use UserFrosting\Sprinkle\MiddlewareRecipe;
100101
use UserFrosting\Sprinkle\SprinkleRecipe;
101102
use UserFrosting\ViteTwig\ViteTwigExtension;
@@ -260,6 +261,7 @@ public function getTwigExtensions(): array
260261
AlertsExtension::class,
261262
RoutesExtension::class,
262263
EntrypointsTwigExtension::class,
264+
UserAgentExtension::class,
263265
VersionedAssetsTwigExtension::class,
264266
ViteTwigExtension::class,
265267
];

packages/sprinkle-core/app/src/Mail/TwigMailMessage.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ final class TwigMailMessage extends AbstractMailMessage implements MailMessage
3131
* @param Twig $view The Twig view object used to render mail templates.
3232
* @param string $template optional Set the Twig template to use for this message.
3333
*/
34-
public function __construct(protected Twig $view, protected string $template)
34+
public function __construct(protected Twig $view, protected string $template = '')
3535
{
3636
$twig = $this->view->getEnvironment();
3737
$this->params = $twig->getGlobals();

packages/sprinkle-core/app/src/Twig/Extensions/CoreExtension.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
use UserFrosting\Sprinkle\Core\Util\Util;
2020

2121
/**
22-
* Test Twig functionality from CoreExtension.
22+
* Core Twig Extensions.
2323
*/
2424
class CoreExtension extends AbstractExtension implements GlobalsInterface
2525
{
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
/*
6+
* UserFrosting Core Sprinkle (http://www.userfrosting.com)
7+
*
8+
* @link https://github.com/userfrosting/sprinkle-core
9+
* @copyright Copyright (c) 2013-2024 Alexander Weissman & Louis Charette
10+
* @license https://github.com/userfrosting/sprinkle-core/blob/master/LICENSE.md (MIT License)
11+
*/
12+
13+
namespace UserFrosting\Sprinkle\Core\Twig\Extensions;
14+
15+
use donatj\UserAgent\UserAgentParser;
16+
use Twig\Extension\AbstractExtension;
17+
use Twig\Extension\GlobalsInterface;
18+
19+
/**
20+
* Twig extension to provide user agent information and utilities as global
21+
* variables and filters in templates.
22+
*
23+
* The `user_agent` global variable contains the user agent string from the
24+
* server's global variables, while the `user_ip` global variable contains the
25+
* user's IP address.
26+
*
27+
* The user agent string is parsed using the `UserAgentParser` service.
28+
* @see https://github.com/donatj/PhpUserAgent
29+
*/
30+
class UserAgentExtension extends AbstractExtension implements GlobalsInterface
31+
{
32+
/**
33+
* @param UserAgentParser $parser The user agent parser service
34+
*/
35+
public function __construct(
36+
protected UserAgentParser $parser,
37+
) {
38+
}
39+
40+
/**
41+
* Adds Twig global variables `site`.
42+
*
43+
* @return array<string, mixed>
44+
*/
45+
public function getGlobals(): array
46+
{
47+
return [
48+
'user_agent' => $this->getUserAgent(),
49+
];
50+
}
51+
52+
/**
53+
* Retrieves the user agent information.
54+
*
55+
* This includes:
56+
* - 'ip': The user's IP address.
57+
* - 'browser': The name of the user's browser.
58+
* - 'version': The version of the user's browser.
59+
* - 'platform': The user's operating system or platform.
60+
*
61+
* @return array{
62+
* ip: string,
63+
* browser: string,
64+
* version: string,
65+
* platform: string
66+
* } An associative array containing details about the user agent.
67+
*/
68+
protected function getUserAgent(): array
69+
{
70+
$parser = $this->parser->parse();
71+
72+
return [
73+
'ip' => $this->getUserIp(),
74+
'browser' => $parser->browser() ?? '',
75+
'version' => $parser->browserVersion() ?? '',
76+
'platform' => $parser->platform() ?? '',
77+
];
78+
}
79+
80+
/**
81+
* Retrieves the user ip from the server's global variables.
82+
*
83+
* @return string
84+
*/
85+
protected function getUserIp(): string
86+
{
87+
return $_SERVER['REMOTE_ADDR'] ?? '';
88+
}
89+
}

packages/sprinkle-core/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"php": "^8.1",
3535
"composer/semver": "^3.2.4",
3636
"doctrine/dbal": "^3.5",
37+
"donatj/phpuseragentparser": "^1.10",
3738
"filp/whoops": "^2.14",
3839
"illuminate/cache": "^10.0",
3940
"illuminate/database": "^10.0",

0 commit comments

Comments
 (0)