mirror of
https://git.teknik.io/Teknikode/Teknik.git
synced 2023-08-02 14:16:22 +02:00
Added trusted device support for Two Factor authentication.
This commit is contained in:
parent
011e737846
commit
000f977dfe
@ -4,6 +4,7 @@ using System.Linq;
|
||||
using System.Web;
|
||||
using System.Web.Mvc;
|
||||
using System.Web.Routing;
|
||||
using Teknik.Helpers;
|
||||
|
||||
namespace Teknik
|
||||
{
|
||||
|
@ -4,6 +4,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Teknik.Areas.Shortener.Models;
|
||||
using Teknik.Helpers;
|
||||
using Teknik.Models;
|
||||
|
||||
namespace Teknik.Areas.Shortener
|
||||
|
@ -5,6 +5,7 @@ using System.Web;
|
||||
using System.IO;
|
||||
using Teknik.Configuration;
|
||||
using Teknik.Models;
|
||||
using Teknik.Helpers;
|
||||
|
||||
namespace Teknik.Areas.Upload
|
||||
{
|
||||
|
@ -23,6 +23,7 @@ using Teknik.Filters;
|
||||
using QRCoder;
|
||||
using System.Text;
|
||||
using TwoStepsAuthenticator;
|
||||
using System.Drawing;
|
||||
|
||||
namespace Teknik.Areas.Users.Controllers
|
||||
{
|
||||
@ -167,10 +168,30 @@ namespace Teknik.Areas.Users.Controllers
|
||||
bool userValid = UserHelper.UserPasswordCorrect(db, Config, user, model.Password);
|
||||
if (userValid)
|
||||
{
|
||||
bool twoFactor = false;
|
||||
string returnUrl = model.ReturnUrl;
|
||||
if (user.SecuritySettings.TwoFactorEnabled)
|
||||
{
|
||||
twoFactor = true;
|
||||
// We need to check their device, and two factor them
|
||||
if (user.SecuritySettings.AllowTrustedDevices)
|
||||
{
|
||||
// Check for the trusted device cookie
|
||||
HttpCookie cookie = Request.Cookies[Constants.TRUSTEDDEVICECOOKIE + "_" + username];
|
||||
if (cookie != null)
|
||||
{
|
||||
string token = cookie.Value;
|
||||
if (user.TrustedDevices.Where(d => d.Token == token).FirstOrDefault() != null)
|
||||
{
|
||||
// The device token is attached to the user, let's let it slide
|
||||
twoFactor = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (twoFactor)
|
||||
{
|
||||
Session["AuthenticatedUser"] = user;
|
||||
if (string.IsNullOrEmpty(model.ReturnUrl))
|
||||
returnUrl = Request.UrlReferrer.AbsoluteUri.ToString();
|
||||
@ -295,7 +316,7 @@ namespace Teknik.Areas.Users.Controllers
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
public ActionResult Edit(string curPass, string newPass, string newPassConfirm, string pgpPublicKey, string recoveryEmail, bool twoFactorEnabled, string website, string quote, string about, string blogTitle, string blogDesc, bool saveKey, bool serverSideEncrypt)
|
||||
public ActionResult Edit(string curPass, string newPass, string newPassConfirm, string pgpPublicKey, string recoveryEmail, bool allowTrustedDevices, bool twoFactorEnabled, string website, string quote, string about, string blogTitle, string blogDesc, bool saveKey, bool serverSideEncrypt)
|
||||
{
|
||||
if (ModelState.IsValid)
|
||||
{
|
||||
@ -329,6 +350,7 @@ namespace Teknik.Areas.Users.Controllers
|
||||
}
|
||||
user.SecuritySettings.PGPSignature = pgpPublicKey;
|
||||
|
||||
// Recovery Email
|
||||
bool newRecovery = false;
|
||||
if (recoveryEmail != user.SecuritySettings.RecoveryEmail)
|
||||
{
|
||||
@ -337,24 +359,56 @@ namespace Teknik.Areas.Users.Controllers
|
||||
user.SecuritySettings.RecoveryVerified = false;
|
||||
}
|
||||
|
||||
// Trusted Devices
|
||||
user.SecuritySettings.AllowTrustedDevices = allowTrustedDevices;
|
||||
if (!allowTrustedDevices)
|
||||
{
|
||||
// They turned it off, let's clear the trusted devices
|
||||
user.TrustedDevices.Clear();
|
||||
List<TrustedDevice> foundDevices = db.TrustedDevices.Where(d => d.UserId == user.UserId).ToList();
|
||||
if (foundDevices != null)
|
||||
{
|
||||
foreach (TrustedDevice device in foundDevices)
|
||||
{
|
||||
db.TrustedDevices.Remove(device);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Two Factor Authentication
|
||||
bool oldTwoFactor = user.SecuritySettings.TwoFactorEnabled;
|
||||
user.SecuritySettings.TwoFactorEnabled = twoFactorEnabled;
|
||||
string newKey = string.Empty;
|
||||
if (twoFactorEnabled)
|
||||
if (!oldTwoFactor && twoFactorEnabled)
|
||||
{
|
||||
// They just enabled it, let's regen the key
|
||||
newKey = Authenticator.GenerateKey();
|
||||
}
|
||||
else if (!twoFactorEnabled)
|
||||
{
|
||||
// remove the key when it's disabled
|
||||
newKey = string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No change, let's use the old value
|
||||
newKey = user.SecuritySettings.TwoFactorKey;
|
||||
}
|
||||
user.SecuritySettings.TwoFactorKey = newKey;
|
||||
|
||||
// Profile Info
|
||||
user.UserSettings.Website = website;
|
||||
user.UserSettings.Quote = quote;
|
||||
user.UserSettings.About = about;
|
||||
|
||||
// Blogs
|
||||
user.BlogSettings.Title = blogTitle;
|
||||
user.BlogSettings.Description = blogDesc;
|
||||
|
||||
// Uploads
|
||||
user.UploadSettings.SaveKey = saveKey;
|
||||
user.UploadSettings.ServerSideEncrypt = serverSideEncrypt;
|
||||
|
||||
UserHelper.EditAccount(db, Config, user, changePass, newPass);
|
||||
|
||||
// If they have a recovery email, let's send a verification
|
||||
@ -557,18 +611,24 @@ namespace Teknik.Areas.Users.Controllers
|
||||
[AllowAnonymous]
|
||||
public ActionResult ConfirmTwoFactorAuth(string returnUrl, bool rememberMe)
|
||||
{
|
||||
ViewBag.Title = "Unknown Device - " + Config.Title;
|
||||
ViewBag.Description = "We do not recognize this device.";
|
||||
LoginViewModel model = new LoginViewModel();
|
||||
model.ReturnUrl = returnUrl;
|
||||
model.RememberMe = rememberMe;
|
||||
User user = (User)Session["AuthenticatedUser"];
|
||||
if (user != null)
|
||||
{
|
||||
ViewBag.Title = "Unknown Device - " + Config.Title;
|
||||
ViewBag.Description = "We do not recognize this device.";
|
||||
TwoFactorViewModel model = new TwoFactorViewModel();
|
||||
model.ReturnUrl = returnUrl;
|
||||
model.RememberMe = rememberMe;
|
||||
model.AllowTrustedDevice = user.SecuritySettings.AllowTrustedDevices;
|
||||
|
||||
return View("/Areas/User/Views/User/TwoFactorCheck.cshtml", model);
|
||||
return View("/Areas/User/Views/User/TwoFactorCheck.cshtml", model);
|
||||
}
|
||||
return Redirect(Url.SubRouteUrl("error", "Error.Http403"));
|
||||
}
|
||||
|
||||
[HttpPost]
|
||||
[AllowAnonymous]
|
||||
public ActionResult ConfirmAuthenticatorCode(string code, string returnUrl, bool rememberMe)
|
||||
public ActionResult ConfirmAuthenticatorCode(string code, string returnUrl, bool rememberMe, bool rememberDevice, string deviceName)
|
||||
{
|
||||
User user = (User)Session["AuthenticatedUser"];
|
||||
if (user != null)
|
||||
@ -586,6 +646,23 @@ namespace Teknik.Areas.Users.Controllers
|
||||
HttpCookie authcookie = UserHelper.CreateAuthCookie(user.Username, rememberMe, Request.Url.Host.GetDomain(), Request.IsLocal);
|
||||
Response.Cookies.Add(authcookie);
|
||||
|
||||
if (user.SecuritySettings.AllowTrustedDevices && rememberDevice)
|
||||
{
|
||||
// They want to remember the device, and have allow trusted devices on
|
||||
HttpCookie trustedDeviceCookie = UserHelper.CreateTrustedDeviceCookie(user.Username, Request.Url.Host.GetDomain(), Request.IsLocal);
|
||||
Response.Cookies.Add(trustedDeviceCookie);
|
||||
|
||||
TrustedDevice device = new TrustedDevice();
|
||||
device.UserId = user.UserId;
|
||||
device.Name = (string.IsNullOrEmpty(deviceName)) ? "Unknown" : deviceName;
|
||||
device.DateSeen = DateTime.Now;
|
||||
device.Token = trustedDeviceCookie.Value;
|
||||
|
||||
// Add the token
|
||||
db.TrustedDevices.Add(device);
|
||||
db.SaveChanges();
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(returnUrl))
|
||||
returnUrl = Request.UrlReferrer.AbsoluteUri.ToString();
|
||||
return Json(new { result = returnUrl });
|
||||
@ -628,9 +705,9 @@ namespace Teknik.Areas.Users.Controllers
|
||||
|
||||
QRCodeGenerator qrGenerator = new QRCodeGenerator();
|
||||
QRCodeData qrCodeData = qrGenerator.CreateQrCode(ProvisionUrl, QRCodeGenerator.ECCLevel.Q);
|
||||
SvgQRCode qrCode = new SvgQRCode(qrCodeData);
|
||||
string qrCodeImage = qrCode.GetGraphic(20);
|
||||
return File(Encoding.UTF8.GetBytes(qrCodeImage), "image/svg+xml");
|
||||
QRCode qrCode = new QRCode(qrCodeData);
|
||||
Bitmap qrCodeImage = qrCode.GetGraphic(20);
|
||||
return File(Helpers.Utility.ImageToByte(qrCodeImage), "image/png");
|
||||
}
|
||||
}
|
||||
}
|
@ -24,6 +24,8 @@ namespace Teknik.Areas.Users.Models
|
||||
|
||||
public bool RecoveryVerified { get; set; }
|
||||
|
||||
public bool AllowTrustedDevices { get; set; }
|
||||
|
||||
public bool TwoFactorEnabled { get; set; }
|
||||
|
||||
[CaseSensitive]
|
||||
@ -35,6 +37,7 @@ namespace Teknik.Areas.Users.Models
|
||||
{
|
||||
RecoveryEmail = string.Empty;
|
||||
RecoveryVerified = false;
|
||||
AllowTrustedDevices = false;
|
||||
TwoFactorEnabled = false;
|
||||
TwoFactorKey = string.Empty;
|
||||
PGPSignature = string.Empty;
|
||||
|
@ -6,9 +6,9 @@ using Teknik.Attributes;
|
||||
|
||||
namespace Teknik.Areas.Users.Models
|
||||
{
|
||||
public class UserDevice
|
||||
public class TrustedDevice
|
||||
{
|
||||
public int UserDeviceId { get; set; }
|
||||
public int TrustedDeviceId { get; set; }
|
||||
|
||||
public int UserId { get; set; }
|
||||
|
@ -33,7 +33,7 @@ namespace Teknik.Areas.Users.Models
|
||||
|
||||
public virtual UploadSettings UploadSettings { get; set; }
|
||||
|
||||
public virtual ICollection<UserDevice> Devices { get; set; }
|
||||
public virtual ICollection<TrustedDevice> TrustedDevices { get; set; }
|
||||
|
||||
public virtual ICollection<Upload.Models.Upload> Uploads { get; set; }
|
||||
|
||||
@ -47,7 +47,7 @@ namespace Teknik.Areas.Users.Models
|
||||
JoinDate = DateTime.Now;
|
||||
LastSeen = DateTime.Now;
|
||||
Groups = new List<Group>();
|
||||
Devices = new List<UserDevice>();
|
||||
TrustedDevices = new List<TrustedDevice>();
|
||||
}
|
||||
}
|
||||
}
|
@ -2,16 +2,18 @@
|
||||
$("#authCheckStatus").css('display', 'none', 'important');
|
||||
|
||||
$("#verifyCodeSubmit").click(function () {
|
||||
setCode = $("#code").val();
|
||||
returnUrl = $("#returnUrl").val();
|
||||
rememberMe = ($("#rememberMe").val() == 'True');
|
||||
setCode = $("#Code").val();
|
||||
returnUrl = $("#ReturnUrl").val();
|
||||
rememberMe = ($("#RememberMe").val() == 'True');
|
||||
rememberDevice = $("#RememberDevice").is(":checked");
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
url: confirmAuthCodeURL,
|
||||
data: {
|
||||
code: setCode,
|
||||
returnUrl: returnUrl,
|
||||
rememberMe: rememberMe
|
||||
rememberMe: rememberMe,
|
||||
rememberDevice: rememberDevice
|
||||
},
|
||||
xhrFields: {
|
||||
withCredentials: true
|
||||
|
@ -2,6 +2,7 @@
|
||||
$("[name='update_upload_saveKey']").bootstrapSwitch();
|
||||
$("[name='update_upload_serverSideEncrypt']").bootstrapSwitch();
|
||||
$("[name='update_security_two_factor']").bootstrapSwitch();
|
||||
$("[name='update_security_allow_trusted']").bootstrapSwitch();
|
||||
|
||||
$('#ResendVerification').click(function () {
|
||||
$.ajax({
|
||||
@ -98,6 +99,7 @@
|
||||
password = $("#update_password").val();
|
||||
password_confirm = $("#update_password_confirm").val();
|
||||
update_pgp_public_key = $("#update_pgp_public_key").val();
|
||||
update_security_allow_trusted = $("#update_security_allow_trusted").is(":checked");
|
||||
update_security_two_factor = $("#update_security_two_factor").is(":checked");
|
||||
recovery = $("#update_recovery_email").val();
|
||||
website = $("#update_website").val();
|
||||
@ -115,6 +117,7 @@
|
||||
newPass: password,
|
||||
newPassConfirm: password_confirm,
|
||||
pgpPublicKey: update_pgp_public_key,
|
||||
allowTrustedDevices: update_security_allow_trusted,
|
||||
twoFactorEnabled: update_security_two_factor,
|
||||
recoveryEmail: recovery,
|
||||
website: website,
|
||||
|
@ -437,7 +437,7 @@ namespace Teknik.Areas.Users.Utility
|
||||
}
|
||||
|
||||
// Create a new verification code and add it
|
||||
string verifyCode = Teknik.Utility.RandomString(24);
|
||||
string verifyCode = Helpers.Utility.RandomString(24);
|
||||
RecoveryEmailVerification ver = new RecoveryEmailVerification();
|
||||
ver.UserId = user.UserId;
|
||||
ver.Code = verifyCode;
|
||||
@ -518,7 +518,7 @@ Thank you and enjoy!
|
||||
}
|
||||
|
||||
// Create a new verification code and add it
|
||||
string verifyCode = Teknik.Utility.RandomString(24);
|
||||
string verifyCode = Helpers.Utility.RandomString(24);
|
||||
ResetPasswordVerification ver = new ResetPasswordVerification();
|
||||
ver.UserId = user.UserId;
|
||||
ver.Code = verifyCode;
|
||||
@ -858,7 +858,7 @@ If you recieved this email and you did not reset your password, you can ignore t
|
||||
{
|
||||
Config config = Config.Load();
|
||||
HttpCookie authcookie = FormsAuthentication.GetAuthCookie(username, remember);
|
||||
authcookie.Name = "TeknikAuth";
|
||||
authcookie.Name = Constants.AUTHCOOKIE;
|
||||
authcookie.HttpOnly = true;
|
||||
authcookie.Secure = true;
|
||||
|
||||
@ -878,5 +878,35 @@ If you recieved this email and you did not reset your password, you can ignore t
|
||||
|
||||
return authcookie;
|
||||
}
|
||||
|
||||
public static HttpCookie CreateTrustedDeviceCookie(string username, string domain, bool local)
|
||||
{
|
||||
Config config = Config.Load();
|
||||
|
||||
byte[] time = BitConverter.GetBytes(DateTime.UtcNow.ToBinary());
|
||||
byte[] key = Guid.NewGuid().ToByteArray();
|
||||
string token = Convert.ToBase64String(time.Concat(key).ToArray());
|
||||
HttpCookie trustCookie = new HttpCookie(Constants.TRUSTEDDEVICECOOKIE + "_" + username);
|
||||
trustCookie.Value = token;
|
||||
trustCookie.HttpOnly = true;
|
||||
trustCookie.Secure = true;
|
||||
trustCookie.Expires = DateTime.Now.AddYears(1);
|
||||
|
||||
// Set domain dependent on where it's being ran from
|
||||
if (local) // localhost
|
||||
{
|
||||
trustCookie.Domain = null;
|
||||
}
|
||||
else if (config.DevEnvironment) // dev.example.com
|
||||
{
|
||||
trustCookie.Domain = string.Format("dev.{0}", domain);
|
||||
}
|
||||
else // A production instance
|
||||
{
|
||||
trustCookie.Domain = string.Format(".{0}", domain);
|
||||
}
|
||||
|
||||
return trustCookie;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
17
Teknik/Areas/User/ViewModels/TwoFactorViewModel.cs
Normal file
17
Teknik/Areas/User/ViewModels/TwoFactorViewModel.cs
Normal file
@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
using Teknik.ViewModels;
|
||||
|
||||
namespace Teknik.Areas.Users.ViewModels
|
||||
{
|
||||
public class TwoFactorViewModel : ViewModelBase
|
||||
{
|
||||
public bool RememberMe { get; set; }
|
||||
|
||||
public string ReturnUrl { get; set; }
|
||||
|
||||
public bool AllowTrustedDevice { get; set; }
|
||||
}
|
||||
}
|
@ -125,19 +125,6 @@
|
||||
<textarea class="form-control" id="update_pgp_public_key" name="update_pgp_public_key" placeholder="Public Key Here" title="enter your pgp public key" rows="15">@Model.SecuritySettings.PGPSignature</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-6 text-left">
|
||||
<label for="update_security_two_factor"><h4>Enable Two Factor Authentication</h4></label>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="update_security_two_factor" name="update_security_two_factor" title="whether the key should be saved on the server or not" type="checkbox" value="true" @(Model.SecuritySettings.TwoFactorEnabled ? "checked" : string.Empty) />
|
||||
</label>
|
||||
</div>
|
||||
<p class="form-control-static @(Model.SecuritySettings.TwoFactorEnabled ? string.Empty : "hide")" id="setupAuthenticatorLink">
|
||||
<small><a href="#" class="text-primary" id="SetupAuthenticator" data-toggle="modal" data-target="#authenticatorSetup"><i class="fa fa-lock"></i> Set Up Authenticator</a></small>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<div class="row">
|
||||
@ -161,6 +148,27 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-4 text-left">
|
||||
<label for="update_security_two_factor"><h4>Enable Two Factor Authentication</h4></label>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="update_security_two_factor" name="update_security_two_factor" title="whether two factor authentication should occur for this account" type="checkbox" value="true" @(Model.SecuritySettings.TwoFactorEnabled ? "checked" : string.Empty) />
|
||||
</label>
|
||||
</div>
|
||||
<p class="form-control-static @(Model.SecuritySettings.TwoFactorEnabled ? string.Empty : "hide")" id="setupAuthenticatorLink">
|
||||
<small><a href="#" class="text-primary" id="SetupAuthenticator" data-toggle="modal" data-target="#authenticatorSetup"><i class="fa fa-lock"></i> Set Up Authenticator</a></small>
|
||||
</p>
|
||||
</div>
|
||||
<div class="col-sm-4 text-left">
|
||||
<label for="update_security_allow_trusted"><h4>Allow Trusted Device Saving</h4></label>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="update_security_allow_trusted" name="update_security_allow_trusted" title="whether a device could be cached to bypass two factor authentication" type="checkbox" value="true" @(Model.SecuritySettings.AllowTrustedDevices ? "checked" : string.Empty) />
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Blog Settings -->
|
||||
<div class="tab-pane" id="blog">
|
||||
|
@ -1,4 +1,4 @@
|
||||
@model Teknik.Areas.Users.ViewModels.LoginViewModel
|
||||
@model Teknik.Areas.Users.ViewModels.TwoFactorViewModel
|
||||
|
||||
@using Teknik.Helpers
|
||||
|
||||
@ -22,12 +22,23 @@
|
||||
</div>
|
||||
</div>
|
||||
<form role="form" id="twoFactorCheckForm" action="##" method="post" accept-charset="UTF-8">
|
||||
<input name="returnUrl" id="returnUrl" type="hidden" value="@Model.ReturnUrl" />
|
||||
<input name="rememberMe" id="rememberMe" type="hidden" value="@Model.RememberMe" />
|
||||
<input name="ReturnUrl" id="ReturnUrl" type="hidden" value="@Model.ReturnUrl" />
|
||||
<input name="RememberMe" id="RememberMe" type="hidden" value="@Model.RememberMe" />
|
||||
<div class="form-group text-left">
|
||||
<label for="update_website">Authentication code</label>
|
||||
<input type="text" class="form-control" id="code" name="code" data-val-required="The Authentication Code is required." data-val="true" />
|
||||
<input type="text" class="form-control" id="Code" name="Code" data-val-required="The Authentication Code is required." data-val="true" />
|
||||
</div>
|
||||
@if (Model.AllowTrustedDevice)
|
||||
{
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="RememberDevice" type="checkbox" value="true" name="RememberDevice" /><input name="RememberDevice" type="hidden" value="false"> Remember Device
|
||||
</label>
|
||||
</div>
|
||||
<small>Set this device as a trusted device. It is not advised to trust a public computer.</small>
|
||||
<br />
|
||||
<br />
|
||||
}
|
||||
<div class="form-group">
|
||||
<button class="btn btn-primary btn-block" id="verifyCodeSubmit" type="button" name="verifyCodeSubmit">Verify</button>
|
||||
</div>
|
||||
|
@ -9,6 +9,9 @@ namespace Teknik.Helpers
|
||||
public static class Constants
|
||||
{
|
||||
public const string SERVERUSER = "Server Admin";
|
||||
public const string AUTHCOOKIE = "TeknikAuth";
|
||||
public const string TRUSTEDDEVICECOOKIE = "TeknikTrustedDevice";
|
||||
|
||||
// Paste Constants
|
||||
public static Dictionary<string, string> HIGHLIGHTFORMATS = new Dictionary<string, string>()
|
||||
{
|
||||
|
@ -8,7 +8,7 @@ using System.Linq;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
|
||||
namespace Teknik
|
||||
namespace Teknik.Helpers
|
||||
{
|
||||
public static class Utility
|
||||
{
|
||||
|
@ -22,7 +22,7 @@ namespace Teknik.Models
|
||||
public DbSet<User> Users { get; set; }
|
||||
public DbSet<Group> Groups { get; set; }
|
||||
public DbSet<Role> Roles { get; set; }
|
||||
public DbSet<UserDevice> UserDevices { get; set; }
|
||||
public DbSet<TrustedDevice> TrustedDevices { get; set; }
|
||||
public DbSet<TransferType> TransferTypes { get; set; }
|
||||
// User Settings
|
||||
public DbSet<UserSettings> UserSettings { get; set; }
|
||||
@ -112,7 +112,7 @@ namespace Teknik.Models
|
||||
modelBuilder.Entity<User>().ToTable("Users");
|
||||
modelBuilder.Entity<Group>().ToTable("Groups");
|
||||
modelBuilder.Entity<Role>().ToTable("Roles");
|
||||
modelBuilder.Entity<UserDevice>().ToTable("UserDevices");
|
||||
modelBuilder.Entity<TrustedDevice>().ToTable("TrustedDevices");
|
||||
modelBuilder.Entity<TransferType>().ToTable("TransferTypes");
|
||||
modelBuilder.Entity<RecoveryEmailVerification>().ToTable("RecoveryEmailVerifications");
|
||||
modelBuilder.Entity<ResetPasswordVerification>().ToTable("ResetPasswordVerifications");
|
||||
|
@ -224,7 +224,8 @@
|
||||
<Compile Include="Areas\User\Models\ResetPasswordVerification.cs" />
|
||||
<Compile Include="Areas\User\Models\RecoveryEmailVerification.cs" />
|
||||
<Compile Include="Areas\User\Models\SecuritySettings.cs" />
|
||||
<Compile Include="Areas\User\Models\UserDevice.cs" />
|
||||
<Compile Include="Areas\User\Models\TrustedDevice.cs" />
|
||||
<Compile Include="Areas\User\ViewModels\TwoFactorViewModel.cs" />
|
||||
<Compile Include="Models\TransferTypes.cs" />
|
||||
<Compile Include="Areas\User\Models\UploadSettings.cs" />
|
||||
<Compile Include="Areas\User\Models\UserSettings.cs" />
|
||||
|
Loading…
Reference in New Issue
Block a user