mirror of
https://github.com/bitwarden/server.git
synced 2024-11-26 12:55:17 +01:00
new device logged in email notification
This commit is contained in:
parent
43967ebbc1
commit
b19628c6f8
@ -11,6 +11,11 @@
|
||||
<EmbeddedResource Include="MailTemplates\Handlebars\**\*.hbs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="MailTemplates\Handlebars\NewDeviceLoggedIn.html.hbs" />
|
||||
<None Remove="MailTemplates\Handlebars\NewDeviceLoggedIn.text.hbs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Handlebars.Net" Version="1.9.5" />
|
||||
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="2.6.0" />
|
||||
|
@ -1,27 +1,50 @@
|
||||
namespace Bit.Core.Enums
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
|
||||
namespace Bit.Core.Enums
|
||||
{
|
||||
public enum DeviceType : byte
|
||||
{
|
||||
[Display(Name = "Android")]
|
||||
Android = 0,
|
||||
[Display(Name = "iOS")]
|
||||
iOS = 1,
|
||||
[Display(Name = "Chrome Extension")]
|
||||
ChromeExtension = 2,
|
||||
[Display(Name = "Firefox Extension")]
|
||||
FirefoxExtension = 3,
|
||||
[Display(Name = "Opera Extension")]
|
||||
OperaExtension = 4,
|
||||
[Display(Name = "Edge Extension")]
|
||||
EdgeExtension = 5,
|
||||
[Display(Name = "Windows")]
|
||||
WindowsDesktop = 6,
|
||||
[Display(Name = "macOS")]
|
||||
MacOsDesktop = 7,
|
||||
[Display(Name = "Linux")]
|
||||
LinuxDesktop = 8,
|
||||
[Display(Name = "Chrome")]
|
||||
ChromeBrowser = 9,
|
||||
[Display(Name = "Firefox")]
|
||||
FirefoxBrowser = 10,
|
||||
[Display(Name = "Opera")]
|
||||
OperaBrowser = 11,
|
||||
[Display(Name = "Edge")]
|
||||
EdgeBrowser = 12,
|
||||
[Display(Name = "Internet Explorer")]
|
||||
IEBrowser = 13,
|
||||
[Display(Name = "Unknown Browser")]
|
||||
UnknownBrowser = 14,
|
||||
[Display(Name = "Android")]
|
||||
AndroidAmazon = 15,
|
||||
[Display(Name = "UWP")]
|
||||
UWP = 16,
|
||||
[Display(Name = "Safari")]
|
||||
SafariBrowser = 17,
|
||||
[Display(Name = "Vivaldi")]
|
||||
VivaldiBrowser = 18,
|
||||
[Display(Name = "Vivaldi Extension")]
|
||||
VivaldiExtension = 19,
|
||||
[Display(Name = "Safari Extension")]
|
||||
SafariExtension = 20
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ using Bit.Core.Models;
|
||||
using Bit.Core.Identity;
|
||||
using Bit.Core.Models.Data;
|
||||
using Bit.Core.Utilities;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Bit.Core.IdentityServer
|
||||
{
|
||||
@ -29,6 +31,7 @@ namespace Bit.Core.IdentityServer
|
||||
private readonly IOrganizationRepository _organizationRepository;
|
||||
private readonly IOrganizationUserRepository _organizationUserRepository;
|
||||
private readonly IApplicationCacheService _applicationCacheService;
|
||||
private readonly IMailService _mailService;
|
||||
private readonly CurrentContext _currentContext;
|
||||
|
||||
public ResourceOwnerPasswordValidator(
|
||||
@ -41,6 +44,7 @@ namespace Bit.Core.IdentityServer
|
||||
IOrganizationRepository organizationRepository,
|
||||
IOrganizationUserRepository organizationUserRepository,
|
||||
IApplicationCacheService applicationCacheService,
|
||||
IMailService mailService,
|
||||
CurrentContext currentContext)
|
||||
{
|
||||
_userManager = userManager;
|
||||
@ -52,6 +56,7 @@ namespace Bit.Core.IdentityServer
|
||||
_organizationRepository = organizationRepository;
|
||||
_organizationUserRepository = organizationUserRepository;
|
||||
_applicationCacheService = applicationCacheService;
|
||||
_mailService = mailService;
|
||||
_currentContext = currentContext;
|
||||
}
|
||||
|
||||
@ -373,6 +378,16 @@ namespace Bit.Core.IdentityServer
|
||||
{
|
||||
device.UserId = user.Id;
|
||||
await _deviceService.SaveAsync(device);
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
if(now - user.CreationDate > TimeSpan.FromMinutes(10))
|
||||
{
|
||||
var deviceType = device.Type.GetType().GetMember(device.Type.ToString())
|
||||
.FirstOrDefault()?.GetCustomAttribute<DisplayAttribute>()?.GetName();
|
||||
await _mailService.SendNewDeviceLoggedInEmail(user.Email, deviceType, now,
|
||||
_currentContext.IpAddress);
|
||||
}
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
|
21
src/Core/MailTemplates/Handlebars/NewDeviceLoggedIn.html.hbs
Normal file
21
src/Core/MailTemplates/Handlebars/NewDeviceLoggedIn.html.hbs
Normal file
@ -0,0 +1,21 @@
|
||||
{{#>FullHtmlLayout}}
|
||||
<table width="100%" cellpadding="0" cellspacing="0" style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
|
||||
<tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
|
||||
<td class="content-block" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0 0 10px; -webkit-text-size-adjust: none;" valign="top">
|
||||
Your Bitwarden account was just logged into from a new device.
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
|
||||
<td class="content-block" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0 0 10px; -webkit-text-size-adjust: none;" valign="top">
|
||||
<b style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">Date:</b> {{TheDate}} at {{TheTime}} {{TimeZone}}<br style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;" />
|
||||
<b style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">IP Address:</b> {{IpAddress}}<br style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;" />
|
||||
<b style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">Device Type:</b> {{DeviceType}}
|
||||
</td>
|
||||
</tr>
|
||||
<tr style="margin: 0; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; -webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none;">
|
||||
<td class="content-block last" style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; box-sizing: border-box; font-size: 16px; color: #333; line-height: 25px; margin: 0; -webkit-font-smoothing: antialiased; padding: 0; -webkit-text-size-adjust: none;" valign="top">
|
||||
You can deauthorize all devices that have access to your account from the <a target="_blank" clicktracking=off href="{{{WebVaultUrl}}}" style="-webkit-font-smoothing: antialiased; -webkit-text-size-adjust: none; box-sizing: border-box; color: #3c8dbc; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 16px; line-height: 25px; margin: 0; text-decoration: underline;">web vault</a> under Settings → My Account → Deauthorize Sessions.
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
{{/FullHtmlLayout}}
|
10
src/Core/MailTemplates/Handlebars/NewDeviceLoggedIn.text.hbs
Normal file
10
src/Core/MailTemplates/Handlebars/NewDeviceLoggedIn.text.hbs
Normal file
@ -0,0 +1,10 @@
|
||||
{{#>BasicTextLayout}}
|
||||
Your Bitwarden account was just logged into from a new device.
|
||||
|
||||
Date: {{TheDate}} at {{TheTime}} {{TimeZone}}
|
||||
IP Address: {{IpAddress}}
|
||||
Device Type: {{DeviceType}}
|
||||
|
||||
You can deauthorize all devices that have access to your account from the
|
||||
web vault under Settings > My Account > Deauthorize Sessions.
|
||||
{{/BasicTextLayout}}
|
11
src/Core/Models/Mail/NewDeviceLoggedInModel.cs
Normal file
11
src/Core/Models/Mail/NewDeviceLoggedInModel.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace Bit.Core.Models.Mail
|
||||
{
|
||||
public class NewDeviceLoggedInModel : BaseMailModel
|
||||
{
|
||||
public string TheDate { get; set; }
|
||||
public string TheTime { get; set; }
|
||||
public string TimeZone { get; set; }
|
||||
public string IpAddress { get; set; }
|
||||
public string DeviceType { get; set; }
|
||||
}
|
||||
}
|
@ -20,5 +20,6 @@ namespace Bit.Core.Services
|
||||
Task SendOrganizationConfirmedEmailAsync(string organizationName, string email);
|
||||
Task SendPasswordlessSignInAsync(string returnUrl, string token, string email);
|
||||
Task SendInvoiceUpcomingAsync(string email, decimal amount, DateTime dueDate, List<string> items, bool mentionInvoices);
|
||||
Task SendNewDeviceLoggedInEmail(string email, string deviceType, DateTime timestamp, string ip);
|
||||
}
|
||||
}
|
||||
|
@ -236,6 +236,24 @@ namespace Bit.Core.Services
|
||||
await _mailDeliveryService.SendEmailAsync(message);
|
||||
}
|
||||
|
||||
public async Task SendNewDeviceLoggedInEmail(string email, string deviceType, DateTime timestamp, string ip)
|
||||
{
|
||||
var message = CreateDefaultMessage($"New Device Logged In From {deviceType}", email);
|
||||
var model = new NewDeviceLoggedInModel
|
||||
{
|
||||
WebVaultUrl = _globalSettings.BaseServiceUri.VaultWithHash,
|
||||
SiteName = _globalSettings.SiteName,
|
||||
DeviceType = deviceType,
|
||||
TheDate = timestamp.ToLongDateString(),
|
||||
TheTime = timestamp.ToShortTimeString(),
|
||||
TimeZone = "UTC",
|
||||
IpAddress = ip
|
||||
};
|
||||
await AddMessageContentAsync(message, "NewDeviceLoggedIn", model);
|
||||
message.MetaData.Add("SendGridCategories", new List<string> { "NewDeviceLoggedIn" });
|
||||
await _mailDeliveryService.SendEmailAsync(message);
|
||||
}
|
||||
|
||||
private MailMessage CreateDefaultMessage(string subject, string toEmail)
|
||||
{
|
||||
return CreateDefaultMessage(subject, new List<string> { toEmail });
|
||||
|
@ -72,5 +72,10 @@ namespace Bit.Core.Services
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task SendNewDeviceLoggedInEmail(string email, string deviceType, DateTime timestamp, string ip)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user