The next generation of the Teknik Services. Written in ASP.NET. https://www.teknik.io/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

UserController.cs 26KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  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. namespace Teknik.Areas.Users.Controllers
  27. {
  28. public class UserController : DefaultController
  29. {
  30. private static readonly UsedCodesManager usedCodesManager = new UsedCodesManager();
  31. private TeknikEntities db = new TeknikEntities();
  32. // GET: Profile/Profile
  33. [TrackPageView]
  34. [AllowAnonymous]
  35. public ActionResult Index(string username)
  36. {
  37. if (string.IsNullOrEmpty(username))
  38. {
  39. username = User.Identity.Name;
  40. }
  41. ProfileViewModel model = new ProfileViewModel();
  42. ViewBag.Title = "User Does Not Exist - " + Config.Title;
  43. ViewBag.Description = "The User does not exist";
  44. try
  45. {
  46. User user = UserHelper.GetUser(db, username);
  47. if (user != null)
  48. {
  49. ViewBag.Title = username + "'s Profile - " + Config.Title;
  50. ViewBag.Description = "Viewing " + username + "'s Profile";
  51. model.UserID = user.UserId;
  52. model.Username = user.Username;
  53. if (Config.EmailConfig.Enabled)
  54. {
  55. model.Email = string.Format("{0}@{1}", user.Username, Config.EmailConfig.Domain);
  56. }
  57. model.JoinDate = user.JoinDate;
  58. model.LastSeen = UserHelper.GetLastAccountActivity(db, Config, user);
  59. model.UserSettings = user.UserSettings;
  60. model.SecuritySettings = user.SecuritySettings;
  61. model.BlogSettings = user.BlogSettings;
  62. model.UploadSettings = user.UploadSettings;
  63. model.Uploads = db.Uploads.Where(u => u.UserId == user.UserId).OrderByDescending(u => u.DateUploaded).ToList();
  64. model.Pastes = db.Pastes.Where(u => u.UserId == user.UserId).OrderByDescending(u => u.DatePosted).ToList();
  65. model.ShortenedUrls = db.ShortenedUrls.Where(s => s.UserId == user.UserId).OrderByDescending(s => s.DateAdded).ToList();
  66. return View(model);
  67. }
  68. model.Error = true;
  69. model.ErrorMessage = "The user does not exist";
  70. }
  71. catch (Exception ex)
  72. {
  73. model.Error = true;
  74. model.ErrorMessage = ex.GetFullMessage(true);
  75. }
  76. return View(model);
  77. }
  78. [TrackPageView]
  79. [AllowAnonymous]
  80. public ActionResult Settings()
  81. {
  82. if (User.Identity.IsAuthenticated)
  83. {
  84. string username = User.Identity.Name;
  85. SettingsViewModel model = new SettingsViewModel();
  86. ViewBag.Title = "User Does Not Exist - " + Config.Title;
  87. ViewBag.Description = "The User does not exist";
  88. User user = UserHelper.GetUser(db, username);
  89. if (user != null)
  90. {
  91. Session["AuthenticatedUser"] = user;
  92. ViewBag.Title = "Settings - " + Config.Title;
  93. ViewBag.Description = "Your " + Config.Title + " Settings";
  94. model.UserID = user.UserId;
  95. model.Username = user.Username;
  96. model.UserSettings = user.UserSettings;
  97. model.SecuritySettings = user.SecuritySettings;
  98. model.BlogSettings = user.BlogSettings;
  99. model.UploadSettings = user.UploadSettings;
  100. return View(model);
  101. }
  102. model.Error = true;
  103. return View(model);
  104. }
  105. return Redirect(Url.SubRouteUrl("error", "Error.Http403"));
  106. }
  107. [HttpGet]
  108. [TrackPageView]
  109. [AllowAnonymous]
  110. public ActionResult ViewRawPGP(string username)
  111. {
  112. ViewBag.Title = username + "'s Public Key - " + Config.Title;
  113. ViewBag.Description = "The PGP public key for " + username;
  114. User user = UserHelper.GetUser(db, username);
  115. if (user != null)
  116. {
  117. if (!string.IsNullOrEmpty(user.SecuritySettings.PGPSignature))
  118. {
  119. return Content(user.SecuritySettings.PGPSignature, "text/plain");
  120. }
  121. }
  122. return Redirect(Url.SubRouteUrl("error", "Error.Http404"));
  123. }
  124. [HttpGet]
  125. [TrackPageView]
  126. [AllowAnonymous]
  127. public ActionResult Login(string ReturnUrl)
  128. {
  129. LoginViewModel model = new LoginViewModel();
  130. model.ReturnUrl = ReturnUrl;
  131. return View("/Areas/User/Views/User/ViewLogin.cshtml", model);
  132. }
  133. [HttpPost]
  134. [AllowAnonymous]
  135. public ActionResult Login([Bind(Prefix = "Login")]LoginViewModel model)
  136. {
  137. if (ModelState.IsValid)
  138. {
  139. string username = model.Username;
  140. User user = UserHelper.GetUser(db, username);
  141. if (user != null)
  142. {
  143. bool userValid = UserHelper.UserPasswordCorrect(db, Config, user, model.Password);
  144. if (userValid)
  145. {
  146. string returnUrl = model.ReturnUrl;
  147. if (user.SecuritySettings.TwoFactorEnabled)
  148. {
  149. // We need to check their device, and two factor them
  150. Session["AuthenticatedUser"] = user;
  151. if (string.IsNullOrEmpty(model.ReturnUrl))
  152. returnUrl = Request.UrlReferrer.AbsoluteUri.ToString();
  153. returnUrl = Url.SubRouteUrl("user", "User.CheckAuthenticatorCode", new { returnUrl = returnUrl, rememberMe = model.RememberMe });
  154. model.ReturnUrl = string.Empty;
  155. }
  156. else
  157. {
  158. returnUrl = Request.UrlReferrer.AbsoluteUri.ToString();
  159. // They don't need two factor auth.
  160. UserHelper.TransferUser(db, Config, user, model.Password);
  161. user.LastSeen = DateTime.Now;
  162. db.Entry(user).State = EntityState.Modified;
  163. db.SaveChanges();
  164. HttpCookie authcookie = UserHelper.CreateAuthCookie(model.Username, model.RememberMe, Request.Url.Host.GetDomain(), Request.IsLocal);
  165. Response.Cookies.Add(authcookie);
  166. }
  167. if (string.IsNullOrEmpty(model.ReturnUrl))
  168. {
  169. return Json(new { result = returnUrl });
  170. }
  171. else
  172. {
  173. return Redirect(model.ReturnUrl);
  174. }
  175. }
  176. }
  177. }
  178. return Json(new { error = "Invalid Username or Password." });
  179. }
  180. public ActionResult Logout()
  181. {
  182. // Get cookie
  183. HttpCookie authCookie = UserHelper.CreateAuthCookie(User.Identity.Name, false, Request.Url.Host.GetDomain(), Request.IsLocal);
  184. // Signout
  185. FormsAuthentication.SignOut();
  186. Session.Abandon();
  187. // Destroy Cookies
  188. authCookie.Expires = DateTime.Now.AddYears(-1);
  189. Response.Cookies.Add(authCookie);
  190. return Redirect(Url.SubRouteUrl("www", "Home.Index"));
  191. }
  192. [HttpGet]
  193. [TrackPageView]
  194. [AllowAnonymous]
  195. public ActionResult Register(string ReturnUrl)
  196. {
  197. RegisterViewModel model = new RegisterViewModel();
  198. model.ReturnUrl = ReturnUrl;
  199. return View("/Areas/User/Views/User/ViewRegistration.cshtml", model);
  200. }
  201. [HttpPost]
  202. [AllowAnonymous]
  203. public ActionResult Register([Bind(Prefix="Register")]RegisterViewModel model)
  204. {
  205. if (ModelState.IsValid)
  206. {
  207. if (Config.UserConfig.RegistrationEnabled)
  208. {
  209. if (!UserHelper.ValidUsername(Config, model.Username))
  210. {
  211. return Json(new { error = "That username is not valid" });
  212. }
  213. if (!UserHelper.UsernameAvailable(db, Config, model.Username))
  214. {
  215. return Json(new { error = "That username is not available" });
  216. }
  217. if (model.Password != model.ConfirmPassword)
  218. {
  219. return Json(new { error = "Passwords must match" });
  220. }
  221. // PGP Key valid?
  222. if (!string.IsNullOrEmpty(model.PublicKey) && !PGP.IsPublicKey(model.PublicKey))
  223. {
  224. return Json(new { error = "Invalid PGP Public Key" });
  225. }
  226. try
  227. {
  228. User newUser = db.Users.Create();
  229. newUser.JoinDate = DateTime.Now;
  230. newUser.Username = model.Username;
  231. newUser.UserSettings = new UserSettings();
  232. newUser.SecuritySettings = new SecuritySettings();
  233. newUser.BlogSettings = new BlogSettings();
  234. newUser.UploadSettings = new UploadSettings();
  235. if (!string.IsNullOrEmpty(model.PublicKey))
  236. newUser.SecuritySettings.PGPSignature = model.PublicKey;
  237. if (!string.IsNullOrEmpty(model.RecoveryEmail))
  238. newUser.SecuritySettings.RecoveryEmail = model.RecoveryEmail;
  239. UserHelper.AddAccount(db, Config, newUser, model.Password);
  240. // If they have a recovery email, let's send a verification
  241. if (!string.IsNullOrEmpty(model.RecoveryEmail))
  242. {
  243. string verifyCode = UserHelper.CreateRecoveryEmailVerification(db, Config, newUser);
  244. string resetUrl = Url.SubRouteUrl("user", "User.ResetPassword", new { Username = model.Username });
  245. string verifyUrl = Url.SubRouteUrl("user", "User.VerifyRecoveryEmail", new { Code = verifyCode });
  246. UserHelper.SendRecoveryEmailVerification(Config, model.Username, model.RecoveryEmail, resetUrl, verifyUrl);
  247. }
  248. }
  249. catch (Exception ex)
  250. {
  251. return Json(new { error = ex.GetFullMessage(true) });
  252. }
  253. return Login(new LoginViewModel { Username = model.Username, Password = model.Password, RememberMe = false, ReturnUrl = model.ReturnUrl });
  254. }
  255. return Json(new { error = "User Registration is Disabled" });
  256. }
  257. return Json(new { error = "You must include all fields." });
  258. }
  259. [HttpPost]
  260. 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)
  261. {
  262. if (ModelState.IsValid)
  263. {
  264. try
  265. {
  266. User user = UserHelper.GetUser(db, User.Identity.Name);
  267. if (user != null)
  268. {
  269. bool changePass = false;
  270. string email = string.Format("{0}@{1}", User.Identity.Name, Config.EmailConfig.Domain);
  271. // Changing Password?
  272. if (!string.IsNullOrEmpty(curPass) && (!string.IsNullOrEmpty(newPass) || !string.IsNullOrEmpty(newPassConfirm)))
  273. {
  274. // Old Password Valid?
  275. if (!UserHelper.UserPasswordCorrect(db, Config, user, curPass))
  276. {
  277. return Json(new { error = "Invalid Original Password." });
  278. }
  279. // The New Password Match?
  280. if (newPass != newPassConfirm)
  281. {
  282. return Json(new { error = "New Password Must Match." });
  283. }
  284. changePass = true;
  285. }
  286. // PGP Key valid?
  287. if (!string.IsNullOrEmpty(pgpPublicKey) && !PGP.IsPublicKey(pgpPublicKey))
  288. {
  289. return Json(new { error = "Invalid PGP Public Key" });
  290. }
  291. user.SecuritySettings.PGPSignature = pgpPublicKey;
  292. bool newRecovery = false;
  293. if (recoveryEmail != user.SecuritySettings.RecoveryEmail)
  294. {
  295. newRecovery = true;
  296. user.SecuritySettings.RecoveryEmail = recoveryEmail;
  297. user.SecuritySettings.RecoveryVerified = false;
  298. }
  299. user.SecuritySettings.TwoFactorEnabled = twoFactorEnabled;
  300. string newKey = string.Empty;
  301. if (twoFactorEnabled)
  302. {
  303. newKey = Authenticator.GenerateKey();
  304. }
  305. user.SecuritySettings.TwoFactorKey = newKey;
  306. user.UserSettings.Website = website;
  307. user.UserSettings.Quote = quote;
  308. user.UserSettings.About = about;
  309. user.BlogSettings.Title = blogTitle;
  310. user.BlogSettings.Description = blogDesc;
  311. user.UploadSettings.SaveKey = saveKey;
  312. user.UploadSettings.ServerSideEncrypt = serverSideEncrypt;
  313. UserHelper.EditAccount(db, Config, user, changePass, newPass);
  314. // If they have a recovery email, let's send a verification
  315. if (!string.IsNullOrEmpty(recoveryEmail) && newRecovery)
  316. {
  317. string verifyCode = UserHelper.CreateRecoveryEmailVerification(db, Config, user);
  318. string resetUrl = Url.SubRouteUrl("user", "User.ResetPassword", new { Username = user.Username });
  319. string verifyUrl = Url.SubRouteUrl("user", "User.VerifyRecoveryEmail", new { Code = verifyCode });
  320. UserHelper.SendRecoveryEmailVerification(Config, user.Username, user.SecuritySettings.RecoveryEmail, resetUrl, verifyUrl);
  321. }
  322. return Json(new { result = true });
  323. }
  324. return Json(new { error = "User does not exist" });
  325. }
  326. catch (Exception ex)
  327. {
  328. return Json(new { error = ex.GetFullMessage(true) });
  329. }
  330. }
  331. return Json(new { error = "Invalid Parameters" });
  332. }
  333. [HttpPost]
  334. public ActionResult Delete()
  335. {
  336. if (ModelState.IsValid)
  337. {
  338. try
  339. {
  340. User user = UserHelper.GetUser(db, User.Identity.Name);
  341. if (user != null)
  342. {
  343. UserHelper.DeleteAccount(db, Config, user);
  344. // Sign Out
  345. Logout();
  346. return Json(new { result = true });
  347. }
  348. }
  349. catch (Exception ex)
  350. {
  351. return Json(new { error = ex.GetFullMessage(true) });
  352. }
  353. }
  354. return Json(new { error = "Unable to delete user" });
  355. }
  356. [HttpGet]
  357. public ActionResult VerifyRecoveryEmail(string code)
  358. {
  359. bool verified = true;
  360. if (string.IsNullOrEmpty(code))
  361. verified &= false;
  362. verified &= UserHelper.VerifyRecoveryEmail(db, Config, User.Identity.Name, code);
  363. RecoveryEmailVerificationViewModel model = new RecoveryEmailVerificationViewModel();
  364. model.Success = verified;
  365. return View("/Areas/User/Views/User/ViewRecoveryEmailVerification.cshtml", model);
  366. }
  367. [HttpPost]
  368. public ActionResult ResendVerifyRecoveryEmail()
  369. {
  370. if (ModelState.IsValid)
  371. {
  372. try
  373. {
  374. User user = UserHelper.GetUser(db, User.Identity.Name);
  375. if (user != null)
  376. {
  377. // If they have a recovery email, let's send a verification
  378. if (!string.IsNullOrEmpty(user.SecuritySettings.RecoveryEmail))
  379. {
  380. if (!user.SecuritySettings.RecoveryVerified)
  381. {
  382. string verifyCode = UserHelper.CreateRecoveryEmailVerification(db, Config, user);
  383. string resetUrl = Url.SubRouteUrl("user", "User.ResetPassword", new { Username = user.Username });
  384. string verifyUrl = Url.SubRouteUrl("user", "User.VerifyRecoveryEmail", new { Code = verifyCode });
  385. UserHelper.SendRecoveryEmailVerification(Config, user.Username, user.SecuritySettings.RecoveryEmail, resetUrl, verifyUrl);
  386. return Json(new { result = true });
  387. }
  388. return Json(new { error = "The recovery email is already verified" });
  389. }
  390. }
  391. }
  392. catch (Exception ex)
  393. {
  394. return Json(new { error = ex.GetFullMessage(true) });
  395. }
  396. }
  397. return Json(new { error = "Unable to resend verification" });
  398. }
  399. [HttpGet]
  400. [AllowAnonymous]
  401. public ActionResult ResetPassword(string username)
  402. {
  403. ResetPasswordViewModel model = new ResetPasswordViewModel();
  404. model.Username = username;
  405. return View("/Areas/User/Views/User/ResetPassword.cshtml", model);
  406. }
  407. [HttpPost]
  408. [AllowAnonymous]
  409. public ActionResult SendResetPasswordVerification(string username)
  410. {
  411. if (ModelState.IsValid)
  412. {
  413. try
  414. {
  415. User user = UserHelper.GetUser(db, username);
  416. if (user != null)
  417. {
  418. // If they have a recovery email, let's send a verification
  419. if (!string.IsNullOrEmpty(user.SecuritySettings.RecoveryEmail) && user.SecuritySettings.RecoveryVerified)
  420. {
  421. string verifyCode = UserHelper.CreateResetPasswordVerification(db, Config, user);
  422. string resetUrl = Url.SubRouteUrl("user", "User.VerifyResetPassword", new { Username = user.Username, Code = verifyCode });
  423. UserHelper.SendResetPasswordVerification(Config, user.Username, user.SecuritySettings.RecoveryEmail, resetUrl);
  424. return Json(new { result = true });
  425. }
  426. return Json(new { error = "The username doesn't have a recovery email specified" });
  427. }
  428. return Json(new { error = "The username is not valid" });
  429. }
  430. catch (Exception ex)
  431. {
  432. return Json(new { error = ex.GetFullMessage(true) });
  433. }
  434. }
  435. return Json(new { error = "Unable to send reset link" });
  436. }
  437. [HttpGet]
  438. [AllowAnonymous]
  439. public ActionResult VerifyResetPassword(string username, string code)
  440. {
  441. bool verified = true;
  442. if (string.IsNullOrEmpty(code))
  443. verified &= false;
  444. verified &= UserHelper.VerifyResetPassword(db, Config, username, code);
  445. if (verified)
  446. {
  447. // The password reset code is valid, let's log them in
  448. User user = UserHelper.GetUser(db, username);
  449. user.LastSeen = DateTime.Now;
  450. db.Entry(user).State = EntityState.Modified;
  451. db.SaveChanges();
  452. HttpCookie authcookie = UserHelper.CreateAuthCookie(user.Username, false, Request.Url.Host.GetDomain(), Request.IsLocal);
  453. Response.Cookies.Add(authcookie);
  454. }
  455. ResetPasswordVerificationViewModel model = new ResetPasswordVerificationViewModel();
  456. model.Success = verified;
  457. return View("/Areas/User/Views/User/ResetPasswordVerification.cshtml", model);
  458. }
  459. [HttpPost]
  460. public ActionResult SetUserPassword(string password, string confirmPassword)
  461. {
  462. if (ModelState.IsValid)
  463. {
  464. try
  465. {
  466. User user = UserHelper.GetUser(db, User.Identity.Name);
  467. if (user != null)
  468. {
  469. if (string.IsNullOrEmpty(password))
  470. {
  471. return Json(new { error = "Password must not be empty" });
  472. }
  473. if (password != confirmPassword)
  474. {
  475. return Json(new { error = "Passwords must match" });
  476. }
  477. UserHelper.EditAccount(db, Config, user, true, password);
  478. return Json(new { result = true });
  479. }
  480. return Json(new { error = "User does not exist" });
  481. }
  482. catch (Exception ex)
  483. {
  484. return Json(new { error = ex.GetFullMessage(true) });
  485. }
  486. }
  487. return Json(new { error = "Unable to reset user password" });
  488. }
  489. [HttpGet]
  490. [AllowAnonymous]
  491. public ActionResult ConfirmTwoFactorAuth(string returnUrl, bool rememberMe)
  492. {
  493. ViewBag.Title = "Unknown Device - " + Config.Title;
  494. ViewBag.Description = "We do not recognize this device.";
  495. LoginViewModel model = new LoginViewModel();
  496. model.ReturnUrl = returnUrl;
  497. model.RememberMe = rememberMe;
  498. return View("/Areas/User/Views/User/TwoFactorCheck.cshtml", model);
  499. }
  500. [HttpPost]
  501. [AllowAnonymous]
  502. public ActionResult ConfirmAuthenticatorCode(string code, string returnUrl, bool rememberMe)
  503. {
  504. User user = (User)Session["AuthenticatedUser"];
  505. if (user != null)
  506. {
  507. if (user.SecuritySettings.TwoFactorEnabled)
  508. {
  509. string key = user.SecuritySettings.TwoFactorKey;
  510. TimeAuthenticator ta = new TimeAuthenticator(usedCodeManager: usedCodesManager);
  511. bool isValid = ta.CheckCode(key, code, user);
  512. if (isValid)
  513. {
  514. // the code was valid, let's log them in!
  515. HttpCookie authcookie = UserHelper.CreateAuthCookie(user.Username, rememberMe, Request.Url.Host.GetDomain(), Request.IsLocal);
  516. Response.Cookies.Add(authcookie);
  517. if (string.IsNullOrEmpty(returnUrl))
  518. returnUrl = Request.UrlReferrer.AbsoluteUri.ToString();
  519. return Json(new { result = returnUrl });
  520. }
  521. return Json(new { error = "Invalid Authentication Code" });
  522. }
  523. return Json(new { error = "User does not have Two Factor Authentication enabled" });
  524. }
  525. return Json(new { error = "User does not exist" });
  526. }
  527. [HttpPost]
  528. public ActionResult VerifyAuthenticatorCode(string code)
  529. {
  530. User user = UserHelper.GetUser(db, User.Identity.Name);
  531. if (user != null)
  532. {
  533. if (user.SecuritySettings.TwoFactorEnabled)
  534. {
  535. string key = user.SecuritySettings.TwoFactorKey;
  536. TimeAuthenticator ta = new TimeAuthenticator(usedCodeManager: usedCodesManager);
  537. bool isValid = ta.CheckCode(key, code, user);
  538. if (isValid)
  539. {
  540. return Json(new { result = true });
  541. }
  542. return Json(new { error = "Invalid Authentication Code" });
  543. }
  544. return Json(new { error = "User does not have Two Factor Authentication enabled" });
  545. }
  546. return Json(new { error = "User does not exist" });
  547. }
  548. [HttpGet]
  549. public ActionResult GenerateAuthQrCode(string key)
  550. {
  551. var ProvisionUrl = string.Format("otpauth://totp/{0}:{1}?secret={2}", Config.Title, User.Identity.Name, key);
  552. QRCodeGenerator qrGenerator = new QRCodeGenerator();
  553. QRCodeData qrCodeData = qrGenerator.CreateQrCode(ProvisionUrl, QRCodeGenerator.ECCLevel.Q);
  554. SvgQRCode qrCode = new SvgQRCode(qrCodeData);
  555. string qrCodeImage = qrCode.GetGraphic(20);
  556. return File(Encoding.UTF8.GetBytes(qrCodeImage), "image/svg+xml");
  557. }
  558. }
  559. }