The next generation of the Teknik Services. Written in ASP.NET. https://www.teknik.io/
Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

UserController.cs 32KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.Entity;
  4. using System.Linq;
  5. using System.Runtime.InteropServices;
  6. using System.Web;
  7. using System.Web.Mvc;
  8. using System.Web.Security;
  9. using Teknik.Areas.Shortener.Models;
  10. using Teknik.Areas.Blog.Models;
  11. using Teknik.Areas.Error.Controllers;
  12. using Teknik.Areas.Error.ViewModels;
  13. using Teknik.Areas.Users.Models;
  14. using Teknik.Areas.Users.ViewModels;
  15. using Teknik.Controllers;
  16. using Teknik.Helpers;
  17. using Teknik.Models;
  18. using Teknik.ViewModels;
  19. using System.Windows;
  20. using System.Net;
  21. using Teknik.Areas.Users.Utility;
  22. using Teknik.Filters;
  23. using QRCoder;
  24. using System.Text;
  25. using TwoStepsAuthenticator;
  26. using System.Drawing;
  27. namespace Teknik.Areas.Users.Controllers
  28. {
  29. public class UserController : DefaultController
  30. {
  31. private static readonly UsedCodesManager usedCodesManager = new UsedCodesManager();
  32. private TeknikEntities db = new TeknikEntities();
  33. // GET: Profile/Profile
  34. [TrackPageView]
  35. [AllowAnonymous]
  36. public ActionResult Index(string username)
  37. {
  38. if (string.IsNullOrEmpty(username))
  39. {
  40. username = User.Identity.Name;
  41. }
  42. ProfileViewModel model = new ProfileViewModel();
  43. ViewBag.Title = "User Does Not Exist - " + Config.Title;
  44. ViewBag.Description = "The User does not exist";
  45. try
  46. {
  47. User user = UserHelper.GetUser(db, username);
  48. if (user != null)
  49. {
  50. ViewBag.Title = username + "'s Profile - " + Config.Title;
  51. ViewBag.Description = "Viewing " + username + "'s Profile";
  52. model.UserID = user.UserId;
  53. model.Username = user.Username;
  54. if (Config.EmailConfig.Enabled)
  55. {
  56. model.Email = string.Format("{0}@{1}", user.Username, Config.EmailConfig.Domain);
  57. }
  58. model.JoinDate = user.JoinDate;
  59. model.LastSeen = UserHelper.GetLastAccountActivity(db, Config, user);
  60. model.UserSettings = user.UserSettings;
  61. model.SecuritySettings = user.SecuritySettings;
  62. model.BlogSettings = user.BlogSettings;
  63. model.UploadSettings = user.UploadSettings;
  64. model.Uploads = db.Uploads.Where(u => u.UserId == user.UserId).OrderByDescending(u => u.DateUploaded).ToList();
  65. model.Pastes = db.Pastes.Where(u => u.UserId == user.UserId).OrderByDescending(u => u.DatePosted).ToList();
  66. model.ShortenedUrls = db.ShortenedUrls.Where(s => s.UserId == user.UserId).OrderByDescending(s => s.DateAdded).ToList();
  67. return View(model);
  68. }
  69. model.Error = true;
  70. model.ErrorMessage = "The user does not exist";
  71. }
  72. catch (Exception ex)
  73. {
  74. model.Error = true;
  75. model.ErrorMessage = ex.GetFullMessage(true);
  76. }
  77. return View(model);
  78. }
  79. [TrackPageView]
  80. public ActionResult Settings()
  81. {
  82. string username = User.Identity.Name;
  83. SettingsViewModel model = new SettingsViewModel();
  84. ViewBag.Title = "User Does Not Exist - " + Config.Title;
  85. ViewBag.Description = "The User does not exist";
  86. User user = UserHelper.GetUser(db, username);
  87. if (user != null)
  88. {
  89. Session["AuthenticatedUser"] = user;
  90. ViewBag.Title = "Settings - " + Config.Title;
  91. ViewBag.Description = "Your " + Config.Title + " Settings";
  92. model.UserID = user.UserId;
  93. model.Username = user.Username;
  94. model.TrustedDeviceCount = user.TrustedDevices.Count;
  95. model.UserSettings = user.UserSettings;
  96. model.SecuritySettings = user.SecuritySettings;
  97. model.BlogSettings = user.BlogSettings;
  98. model.UploadSettings = user.UploadSettings;
  99. return View(model);
  100. }
  101. model.Error = true;
  102. return View(model);
  103. }
  104. [HttpGet]
  105. [TrackPageView]
  106. [AllowAnonymous]
  107. public ActionResult ViewRawPGP(string username)
  108. {
  109. ViewBag.Title = username + "'s Public Key - " + Config.Title;
  110. ViewBag.Description = "The PGP public key for " + username;
  111. User user = UserHelper.GetUser(db, username);
  112. if (user != null)
  113. {
  114. if (!string.IsNullOrEmpty(user.SecuritySettings.PGPSignature))
  115. {
  116. return Content(user.SecuritySettings.PGPSignature, "text/plain");
  117. }
  118. }
  119. return Redirect(Url.SubRouteUrl("error", "Error.Http404"));
  120. }
  121. [HttpGet]
  122. [TrackPageView]
  123. [AllowAnonymous]
  124. public ActionResult Login(string ReturnUrl)
  125. {
  126. LoginViewModel model = new LoginViewModel();
  127. model.ReturnUrl = ReturnUrl;
  128. return View("/Areas/User/Views/User/ViewLogin.cshtml", model);
  129. }
  130. [HttpPost]
  131. [AllowAnonymous]
  132. public ActionResult Login([Bind(Prefix = "Login")]LoginViewModel model)
  133. {
  134. if (ModelState.IsValid)
  135. {
  136. string username = model.Username;
  137. User user = UserHelper.GetUser(db, username);
  138. if (user != null)
  139. {
  140. bool userValid = UserHelper.UserPasswordCorrect(db, Config, user, model.Password);
  141. if (userValid)
  142. {
  143. // Perform transfer actions on the account
  144. UserHelper.TransferUser(db, Config, user, model.Password);
  145. user.LastSeen = DateTime.Now;
  146. db.Entry(user).State = EntityState.Modified;
  147. db.SaveChanges();
  148. bool twoFactor = false;
  149. string returnUrl = model.ReturnUrl;
  150. if (user.SecuritySettings.TwoFactorEnabled)
  151. {
  152. twoFactor = true;
  153. // We need to check their device, and two factor them
  154. if (user.SecuritySettings.AllowTrustedDevices)
  155. {
  156. // Check for the trusted device cookie
  157. HttpCookie cookie = Request.Cookies[Constants.TRUSTEDDEVICECOOKIE + "_" + username];
  158. if (cookie != null)
  159. {
  160. string token = cookie.Value;
  161. if (user.TrustedDevices.Where(d => d.Token == token).FirstOrDefault() != null)
  162. {
  163. // The device token is attached to the user, let's let it slide
  164. twoFactor = false;
  165. }
  166. }
  167. }
  168. }
  169. if (twoFactor)
  170. {
  171. Session["AuthenticatedUser"] = user;
  172. if (string.IsNullOrEmpty(model.ReturnUrl))
  173. returnUrl = Request.UrlReferrer.AbsoluteUri.ToString();
  174. returnUrl = Url.SubRouteUrl("user", "User.CheckAuthenticatorCode", new { returnUrl = returnUrl, rememberMe = model.RememberMe });
  175. model.ReturnUrl = string.Empty;
  176. }
  177. else
  178. {
  179. returnUrl = Request.UrlReferrer.AbsoluteUri.ToString();
  180. // They don't need two factor auth.
  181. HttpCookie authcookie = UserHelper.CreateAuthCookie(model.Username, model.RememberMe, Request.Url.Host.GetDomain(), Request.IsLocal);
  182. Response.Cookies.Add(authcookie);
  183. }
  184. if (string.IsNullOrEmpty(model.ReturnUrl))
  185. {
  186. return Json(new { result = returnUrl });
  187. }
  188. else
  189. {
  190. return Redirect(model.ReturnUrl);
  191. }
  192. }
  193. }
  194. }
  195. return Json(new { error = "Invalid Username or Password." });
  196. }
  197. public ActionResult Logout()
  198. {
  199. // Get cookie
  200. HttpCookie authCookie = UserHelper.CreateAuthCookie(User.Identity.Name, false, Request.Url.Host.GetDomain(), Request.IsLocal);
  201. // Signout
  202. FormsAuthentication.SignOut();
  203. Session.Abandon();
  204. // Destroy Cookies
  205. authCookie.Expires = DateTime.Now.AddYears(-1);
  206. Response.Cookies.Add(authCookie);
  207. return Redirect(Url.SubRouteUrl("www", "Home.Index"));
  208. }
  209. [HttpGet]
  210. [TrackPageView]
  211. [AllowAnonymous]
  212. public ActionResult Register(string ReturnUrl)
  213. {
  214. RegisterViewModel model = new RegisterViewModel();
  215. model.ReturnUrl = ReturnUrl;
  216. return View("/Areas/User/Views/User/ViewRegistration.cshtml", model);
  217. }
  218. [HttpPost]
  219. [AllowAnonymous]
  220. public ActionResult Register([Bind(Prefix="Register")]RegisterViewModel model)
  221. {
  222. if (ModelState.IsValid)
  223. {
  224. if (Config.UserConfig.RegistrationEnabled)
  225. {
  226. if (!UserHelper.ValidUsername(Config, model.Username))
  227. {
  228. return Json(new { error = "That username is not valid" });
  229. }
  230. if (!UserHelper.UsernameAvailable(db, Config, model.Username))
  231. {
  232. return Json(new { error = "That username is not available" });
  233. }
  234. if (model.Password != model.ConfirmPassword)
  235. {
  236. return Json(new { error = "Passwords must match" });
  237. }
  238. // PGP Key valid?
  239. if (!string.IsNullOrEmpty(model.PublicKey) && !PGP.IsPublicKey(model.PublicKey))
  240. {
  241. return Json(new { error = "Invalid PGP Public Key" });
  242. }
  243. try
  244. {
  245. User newUser = db.Users.Create();
  246. newUser.JoinDate = DateTime.Now;
  247. newUser.Username = model.Username;
  248. newUser.UserSettings = new UserSettings();
  249. newUser.SecuritySettings = new SecuritySettings();
  250. newUser.BlogSettings = new BlogSettings();
  251. newUser.UploadSettings = new UploadSettings();
  252. if (!string.IsNullOrEmpty(model.PublicKey))
  253. newUser.SecuritySettings.PGPSignature = model.PublicKey;
  254. if (!string.IsNullOrEmpty(model.RecoveryEmail))
  255. newUser.SecuritySettings.RecoveryEmail = model.RecoveryEmail;
  256. UserHelper.AddAccount(db, Config, newUser, model.Password);
  257. // If they have a recovery email, let's send a verification
  258. if (!string.IsNullOrEmpty(model.RecoveryEmail))
  259. {
  260. string verifyCode = UserHelper.CreateRecoveryEmailVerification(db, Config, newUser);
  261. string resetUrl = Url.SubRouteUrl("user", "User.ResetPassword", new { Username = model.Username });
  262. string verifyUrl = Url.SubRouteUrl("user", "User.VerifyRecoveryEmail", new { Code = verifyCode });
  263. UserHelper.SendRecoveryEmailVerification(Config, model.Username, model.RecoveryEmail, resetUrl, verifyUrl);
  264. }
  265. }
  266. catch (Exception ex)
  267. {
  268. return Json(new { error = ex.GetFullMessage(true) });
  269. }
  270. return Login(new LoginViewModel { Username = model.Username, Password = model.Password, RememberMe = false, ReturnUrl = model.ReturnUrl });
  271. }
  272. return Json(new { error = "User Registration is Disabled" });
  273. }
  274. return Json(new { error = "You must include all fields." });
  275. }
  276. [HttpPost]
  277. [ValidateAntiForgeryToken]
  278. 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)
  279. {
  280. if (ModelState.IsValid)
  281. {
  282. try
  283. {
  284. User user = UserHelper.GetUser(db, User.Identity.Name);
  285. if (user != null)
  286. {
  287. bool changePass = false;
  288. string email = string.Format("{0}@{1}", User.Identity.Name, Config.EmailConfig.Domain);
  289. // Changing Password?
  290. if (!string.IsNullOrEmpty(curPass) && (!string.IsNullOrEmpty(newPass) || !string.IsNullOrEmpty(newPassConfirm)))
  291. {
  292. // Old Password Valid?
  293. if (!UserHelper.UserPasswordCorrect(db, Config, user, curPass))
  294. {
  295. return Json(new { error = "Invalid Original Password." });
  296. }
  297. // The New Password Match?
  298. if (newPass != newPassConfirm)
  299. {
  300. return Json(new { error = "New Password Must Match." });
  301. }
  302. changePass = true;
  303. }
  304. // PGP Key valid?
  305. if (!string.IsNullOrEmpty(pgpPublicKey) && !PGP.IsPublicKey(pgpPublicKey))
  306. {
  307. return Json(new { error = "Invalid PGP Public Key" });
  308. }
  309. user.SecuritySettings.PGPSignature = pgpPublicKey;
  310. // Recovery Email
  311. bool newRecovery = false;
  312. if (recoveryEmail != user.SecuritySettings.RecoveryEmail)
  313. {
  314. newRecovery = true;
  315. user.SecuritySettings.RecoveryEmail = recoveryEmail;
  316. user.SecuritySettings.RecoveryVerified = false;
  317. }
  318. // Trusted Devices
  319. user.SecuritySettings.AllowTrustedDevices = allowTrustedDevices;
  320. if (!allowTrustedDevices)
  321. {
  322. // They turned it off, let's clear the trusted devices
  323. user.TrustedDevices.Clear();
  324. List<TrustedDevice> foundDevices = db.TrustedDevices.Where(d => d.UserId == user.UserId).ToList();
  325. if (foundDevices != null)
  326. {
  327. foreach (TrustedDevice device in foundDevices)
  328. {
  329. db.TrustedDevices.Remove(device);
  330. }
  331. }
  332. }
  333. // Two Factor Authentication
  334. bool oldTwoFactor = user.SecuritySettings.TwoFactorEnabled;
  335. user.SecuritySettings.TwoFactorEnabled = twoFactorEnabled;
  336. string newKey = string.Empty;
  337. if (!oldTwoFactor && twoFactorEnabled)
  338. {
  339. // They just enabled it, let's regen the key
  340. newKey = Authenticator.GenerateKey();
  341. }
  342. else if (!twoFactorEnabled)
  343. {
  344. // remove the key when it's disabled
  345. newKey = string.Empty;
  346. }
  347. else
  348. {
  349. // No change, let's use the old value
  350. newKey = user.SecuritySettings.TwoFactorKey;
  351. }
  352. user.SecuritySettings.TwoFactorKey = newKey;
  353. // Profile Info
  354. user.UserSettings.Website = website;
  355. user.UserSettings.Quote = quote;
  356. user.UserSettings.About = about;
  357. // Blogs
  358. user.BlogSettings.Title = blogTitle;
  359. user.BlogSettings.Description = blogDesc;
  360. // Uploads
  361. user.UploadSettings.SaveKey = saveKey;
  362. user.UploadSettings.ServerSideEncrypt = serverSideEncrypt;
  363. UserHelper.EditAccount(db, Config, user, changePass, newPass);
  364. // If they have a recovery email, let's send a verification
  365. if (!string.IsNullOrEmpty(recoveryEmail) && newRecovery)
  366. {
  367. string verifyCode = UserHelper.CreateRecoveryEmailVerification(db, Config, user);
  368. string resetUrl = Url.SubRouteUrl("user", "User.ResetPassword", new { Username = user.Username });
  369. string verifyUrl = Url.SubRouteUrl("user", "User.VerifyRecoveryEmail", new { Code = verifyCode });
  370. UserHelper.SendRecoveryEmailVerification(Config, user.Username, user.SecuritySettings.RecoveryEmail, resetUrl, verifyUrl);
  371. }
  372. if (!oldTwoFactor && twoFactorEnabled)
  373. {
  374. return Json(new { result = new { checkAuth = true, key = newKey, qrUrl = Url.SubRouteUrl("user", "User.Action", new { action = "GenerateAuthQrCode", key = newKey }) } });
  375. }
  376. return Json(new { result = true });
  377. }
  378. return Json(new { error = "User does not exist" });
  379. }
  380. catch (Exception ex)
  381. {
  382. return Json(new { error = ex.GetFullMessage(true) });
  383. }
  384. }
  385. return Json(new { error = "Invalid Parameters" });
  386. }
  387. [HttpPost]
  388. [ValidateAntiForgeryToken]
  389. public ActionResult Delete()
  390. {
  391. if (ModelState.IsValid)
  392. {
  393. try
  394. {
  395. User user = UserHelper.GetUser(db, User.Identity.Name);
  396. if (user != null)
  397. {
  398. UserHelper.DeleteAccount(db, Config, user);
  399. // Sign Out
  400. Logout();
  401. return Json(new { result = true });
  402. }
  403. }
  404. catch (Exception ex)
  405. {
  406. return Json(new { error = ex.GetFullMessage(true) });
  407. }
  408. }
  409. return Json(new { error = "Unable to delete user" });
  410. }
  411. [HttpGet]
  412. public ActionResult VerifyRecoveryEmail(string code)
  413. {
  414. bool verified = true;
  415. if (string.IsNullOrEmpty(code))
  416. verified &= false;
  417. verified &= UserHelper.VerifyRecoveryEmail(db, Config, User.Identity.Name, code);
  418. RecoveryEmailVerificationViewModel model = new RecoveryEmailVerificationViewModel();
  419. model.Success = verified;
  420. return View("/Areas/User/Views/User/ViewRecoveryEmailVerification.cshtml", model);
  421. }
  422. [HttpPost]
  423. [ValidateAntiForgeryToken]
  424. public ActionResult ResendVerifyRecoveryEmail()
  425. {
  426. if (ModelState.IsValid)
  427. {
  428. try
  429. {
  430. User user = UserHelper.GetUser(db, User.Identity.Name);
  431. if (user != null)
  432. {
  433. // If they have a recovery email, let's send a verification
  434. if (!string.IsNullOrEmpty(user.SecuritySettings.RecoveryEmail))
  435. {
  436. if (!user.SecuritySettings.RecoveryVerified)
  437. {
  438. string verifyCode = UserHelper.CreateRecoveryEmailVerification(db, Config, user);
  439. string resetUrl = Url.SubRouteUrl("user", "User.ResetPassword", new { Username = user.Username });
  440. string verifyUrl = Url.SubRouteUrl("user", "User.VerifyRecoveryEmail", new { Code = verifyCode });
  441. UserHelper.SendRecoveryEmailVerification(Config, user.Username, user.SecuritySettings.RecoveryEmail, resetUrl, verifyUrl);
  442. return Json(new { result = true });
  443. }
  444. return Json(new { error = "The recovery email is already verified" });
  445. }
  446. }
  447. }
  448. catch (Exception ex)
  449. {
  450. return Json(new { error = ex.GetFullMessage(true) });
  451. }
  452. }
  453. return Json(new { error = "Unable to resend verification" });
  454. }
  455. [HttpGet]
  456. [AllowAnonymous]
  457. public ActionResult ResetPassword(string username)
  458. {
  459. ResetPasswordViewModel model = new ResetPasswordViewModel();
  460. model.Username = username;
  461. return View("/Areas/User/Views/User/ResetPassword.cshtml", model);
  462. }
  463. [HttpPost]
  464. [AllowAnonymous]
  465. [ValidateAntiForgeryToken]
  466. public ActionResult SendResetPasswordVerification(string username)
  467. {
  468. if (ModelState.IsValid)
  469. {
  470. try
  471. {
  472. User user = UserHelper.GetUser(db, username);
  473. if (user != null)
  474. {
  475. // If they have a recovery email, let's send a verification
  476. if (!string.IsNullOrEmpty(user.SecuritySettings.RecoveryEmail) && user.SecuritySettings.RecoveryVerified)
  477. {
  478. string verifyCode = UserHelper.CreateResetPasswordVerification(db, Config, user);
  479. string resetUrl = Url.SubRouteUrl("user", "User.VerifyResetPassword", new { Username = user.Username, Code = verifyCode });
  480. UserHelper.SendResetPasswordVerification(Config, user.Username, user.SecuritySettings.RecoveryEmail, resetUrl);
  481. return Json(new { result = true });
  482. }
  483. return Json(new { error = "The username doesn't have a recovery email specified" });
  484. }
  485. return Json(new { error = "The username is not valid" });
  486. }
  487. catch (Exception ex)
  488. {
  489. return Json(new { error = ex.GetFullMessage(true) });
  490. }
  491. }
  492. return Json(new { error = "Unable to send reset link" });
  493. }
  494. [HttpGet]
  495. [AllowAnonymous]
  496. public ActionResult VerifyResetPassword(string username, string code)
  497. {
  498. bool verified = true;
  499. if (string.IsNullOrEmpty(code))
  500. verified &= false;
  501. verified &= UserHelper.VerifyResetPassword(db, Config, username, code);
  502. if (verified)
  503. {
  504. // The password reset code is valid, let's log them in
  505. User user = UserHelper.GetUser(db, username);
  506. user.LastSeen = DateTime.Now;
  507. db.Entry(user).State = EntityState.Modified;
  508. db.SaveChanges();
  509. HttpCookie authcookie = UserHelper.CreateAuthCookie(user.Username, false, Request.Url.Host.GetDomain(), Request.IsLocal);
  510. Response.Cookies.Add(authcookie);
  511. }
  512. ResetPasswordVerificationViewModel model = new ResetPasswordVerificationViewModel();
  513. model.Success = verified;
  514. return View("/Areas/User/Views/User/ResetPasswordVerification.cshtml", model);
  515. }
  516. [HttpPost]
  517. [ValidateAntiForgeryToken]
  518. public ActionResult SetUserPassword(string password, string confirmPassword)
  519. {
  520. if (ModelState.IsValid)
  521. {
  522. try
  523. {
  524. User user = UserHelper.GetUser(db, User.Identity.Name);
  525. if (user != null)
  526. {
  527. if (string.IsNullOrEmpty(password))
  528. {
  529. return Json(new { error = "Password must not be empty" });
  530. }
  531. if (password != confirmPassword)
  532. {
  533. return Json(new { error = "Passwords must match" });
  534. }
  535. UserHelper.EditAccount(db, Config, user, true, password);
  536. return Json(new { result = true });
  537. }
  538. return Json(new { error = "User does not exist" });
  539. }
  540. catch (Exception ex)
  541. {
  542. return Json(new { error = ex.GetFullMessage(true) });
  543. }
  544. }
  545. return Json(new { error = "Unable to reset user password" });
  546. }
  547. [HttpGet]
  548. [AllowAnonymous]
  549. public ActionResult ConfirmTwoFactorAuth(string returnUrl, bool rememberMe)
  550. {
  551. User user = (User)Session["AuthenticatedUser"];
  552. if (user != null)
  553. {
  554. ViewBag.Title = "Unknown Device - " + Config.Title;
  555. ViewBag.Description = "We do not recognize this device.";
  556. TwoFactorViewModel model = new TwoFactorViewModel();
  557. model.ReturnUrl = returnUrl;
  558. model.RememberMe = rememberMe;
  559. model.AllowTrustedDevice = user.SecuritySettings.AllowTrustedDevices;
  560. return View("/Areas/User/Views/User/TwoFactorCheck.cshtml", model);
  561. }
  562. return Redirect(Url.SubRouteUrl("error", "Error.Http403"));
  563. }
  564. [HttpPost]
  565. [AllowAnonymous]
  566. [ValidateAntiForgeryToken]
  567. public ActionResult ConfirmAuthenticatorCode(string code, string returnUrl, bool rememberMe, bool rememberDevice, string deviceName)
  568. {
  569. User user = (User)Session["AuthenticatedUser"];
  570. if (user != null)
  571. {
  572. if (user.SecuritySettings.TwoFactorEnabled)
  573. {
  574. string key = user.SecuritySettings.TwoFactorKey;
  575. TimeAuthenticator ta = new TimeAuthenticator(usedCodeManager: usedCodesManager);
  576. bool isValid = ta.CheckCode(key, code, user);
  577. if (isValid)
  578. {
  579. // the code was valid, let's log them in!
  580. HttpCookie authcookie = UserHelper.CreateAuthCookie(user.Username, rememberMe, Request.Url.Host.GetDomain(), Request.IsLocal);
  581. Response.Cookies.Add(authcookie);
  582. if (user.SecuritySettings.AllowTrustedDevices && rememberDevice)
  583. {
  584. // They want to remember the device, and have allow trusted devices on
  585. HttpCookie trustedDeviceCookie = UserHelper.CreateTrustedDeviceCookie(user.Username, Request.Url.Host.GetDomain(), Request.IsLocal);
  586. Response.Cookies.Add(trustedDeviceCookie);
  587. TrustedDevice device = new TrustedDevice();
  588. device.UserId = user.UserId;
  589. device.Name = (string.IsNullOrEmpty(deviceName)) ? "Unknown" : deviceName;
  590. device.DateSeen = DateTime.Now;
  591. device.Token = trustedDeviceCookie.Value;
  592. // Add the token
  593. db.TrustedDevices.Add(device);
  594. db.SaveChanges();
  595. }
  596. if (string.IsNullOrEmpty(returnUrl))
  597. returnUrl = Request.UrlReferrer.AbsoluteUri.ToString();
  598. return Json(new { result = returnUrl });
  599. }
  600. return Json(new { error = "Invalid Authentication Code" });
  601. }
  602. return Json(new { error = "User does not have Two Factor Authentication enabled" });
  603. }
  604. return Json(new { error = "User does not exist" });
  605. }
  606. [HttpPost]
  607. [ValidateAntiForgeryToken]
  608. public ActionResult VerifyAuthenticatorCode(string code)
  609. {
  610. User user = UserHelper.GetUser(db, User.Identity.Name);
  611. if (user != null)
  612. {
  613. if (user.SecuritySettings.TwoFactorEnabled)
  614. {
  615. string key = user.SecuritySettings.TwoFactorKey;
  616. TimeAuthenticator ta = new TimeAuthenticator(usedCodeManager: usedCodesManager);
  617. bool isValid = ta.CheckCode(key, code, user);
  618. if (isValid)
  619. {
  620. return Json(new { result = true });
  621. }
  622. return Json(new { error = "Invalid Authentication Code" });
  623. }
  624. return Json(new { error = "User does not have Two Factor Authentication enabled" });
  625. }
  626. return Json(new { error = "User does not exist" });
  627. }
  628. [HttpGet]
  629. public ActionResult GenerateAuthQrCode(string key)
  630. {
  631. var ProvisionUrl = string.Format("otpauth://totp/{0}:{1}?secret={2}", Config.Title, User.Identity.Name, key);
  632. QRCodeGenerator qrGenerator = new QRCodeGenerator();
  633. QRCodeData qrCodeData = qrGenerator.CreateQrCode(ProvisionUrl, QRCodeGenerator.ECCLevel.Q);
  634. QRCode qrCode = new QRCode(qrCodeData);
  635. Bitmap qrCodeImage = qrCode.GetGraphic(20);
  636. return File(Helpers.Utility.ImageToByte(qrCodeImage), "image/png");
  637. }
  638. [HttpPost]
  639. [ValidateAntiForgeryToken]
  640. public ActionResult ClearTrustedDevices()
  641. {
  642. try
  643. {
  644. User user = UserHelper.GetUser(db, User.Identity.Name);
  645. if (user != null)
  646. {
  647. if (user.SecuritySettings.AllowTrustedDevices)
  648. {
  649. // let's clear the trusted devices
  650. user.TrustedDevices.Clear();
  651. List<TrustedDevice> foundDevices = db.TrustedDevices.Where(d => d.UserId == user.UserId).ToList();
  652. if (foundDevices != null)
  653. {
  654. foreach (TrustedDevice device in foundDevices)
  655. {
  656. db.TrustedDevices.Remove(device);
  657. }
  658. }
  659. db.Entry(user).State = EntityState.Modified;
  660. db.SaveChanges();
  661. return Json(new { result = true });
  662. }
  663. return Json(new { error = "User does not allow trusted devices" });
  664. }
  665. return Json(new { error = "User does not exist" });
  666. }
  667. catch (Exception ex)
  668. {
  669. return Json(new { error = ex.GetFullMessage(true) });
  670. }
  671. }
  672. }
  673. }