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 53KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Teknik.Areas.Users.Models;
  5. using Teknik.Areas.Users.ViewModels;
  6. using Teknik.Controllers;
  7. using Teknik.Utilities;
  8. using Teknik.Areas.Users.Utility;
  9. using Teknik.Filters;
  10. using QRCoder;
  11. using TwoStepsAuthenticator;
  12. using Teknik.Attributes;
  13. using Teknik.Utilities.Cryptography;
  14. using Microsoft.Extensions.Logging;
  15. using Teknik.Configuration;
  16. using Teknik.Data;
  17. using Microsoft.AspNetCore.Authorization;
  18. using Microsoft.AspNetCore.Mvc;
  19. using Microsoft.EntityFrameworkCore;
  20. using System.Net;
  21. using Microsoft.AspNetCore.Mvc.ViewEngines;
  22. using System.Threading.Tasks;
  23. using Teknik.Logging;
  24. using System.Security.Claims;
  25. using Microsoft.AspNetCore.Authentication.Cookies;
  26. using Microsoft.AspNetCore.Authentication;
  27. namespace Teknik.Areas.Users.Controllers
  28. {
  29. [TeknikAuthorize]
  30. [Area("User")]
  31. public class UserController : DefaultController
  32. {
  33. public UserController(ILogger<Logger> logger, Config config, TeknikEntities dbContext) : base(logger, config, dbContext) { }
  34. private static readonly UsedCodesManager usedCodesManager = new UsedCodesManager();
  35. private const string _AuthSessionKey = "AuthenticatedUser";
  36. [TrackPageView]
  37. [AllowAnonymous]
  38. public IActionResult GetPremium()
  39. {
  40. ViewBag.Title = "Get a Premium Account - " + _config.Title;
  41. GetPremiumViewModel model = new GetPremiumViewModel();
  42. return View(model);
  43. }
  44. // GET: Profile/Profile
  45. [TrackPageView]
  46. [AllowAnonymous]
  47. public IActionResult ViewProfile(string username)
  48. {
  49. if (string.IsNullOrEmpty(username))
  50. {
  51. username = User.Identity.Name;
  52. }
  53. ProfileViewModel model = new ProfileViewModel();
  54. ViewBag.Title = "User Does Not Exist - " + _config.Title;
  55. ViewBag.Description = "The User does not exist";
  56. try
  57. {
  58. User user = UserHelper.GetUser(_dbContext, username);
  59. if (user != null)
  60. {
  61. ViewBag.Title = username + "'s Profile - " + _config.Title;
  62. ViewBag.Description = "Viewing " + username + "'s Profile";
  63. model.UserID = user.UserId;
  64. model.Username = user.Username;
  65. if (_config.EmailConfig.Enabled)
  66. {
  67. model.Email = string.Format("{0}@{1}", user.Username, _config.EmailConfig.Domain);
  68. }
  69. model.JoinDate = user.JoinDate;
  70. model.LastSeen = UserHelper.GetLastAccountActivity(_dbContext, _config, user);
  71. model.AccountType = user.AccountType;
  72. model.AccountStatus = user.AccountStatus;
  73. model.UserSettings = user.UserSettings;
  74. model.SecuritySettings = user.SecuritySettings;
  75. model.BlogSettings = user.BlogSettings;
  76. model.UploadSettings = user.UploadSettings;
  77. model.Uploads = _dbContext.Uploads.Where(u => u.UserId == user.UserId).OrderByDescending(u => u.DateUploaded).ToList();
  78. model.Pastes = _dbContext.Pastes.Where(u => u.UserId == user.UserId).OrderByDescending(u => u.DatePosted).ToList();
  79. model.ShortenedUrls = _dbContext.ShortenedUrls.Where(s => s.UserId == user.UserId).OrderByDescending(s => s.DateAdded).ToList();
  80. model.Vaults = _dbContext.Vaults.Where(v => v.UserId == user.UserId).OrderByDescending(v => v.DateCreated).ToList();
  81. return View(model);
  82. }
  83. model.Error = true;
  84. model.ErrorMessage = "The user does not exist";
  85. }
  86. catch (Exception ex)
  87. {
  88. model.Error = true;
  89. model.ErrorMessage = ex.GetFullMessage(true);
  90. }
  91. return View(model);
  92. }
  93. [TrackPageView]
  94. public IActionResult Settings()
  95. {
  96. return Redirect(Url.SubRouteUrl("user", "User.SecuritySettings"));
  97. }
  98. [TrackPageView]
  99. public IActionResult ProfileSettings()
  100. {
  101. string username = User.Identity.Name;
  102. User user = UserHelper.GetUser(_dbContext, username);
  103. if (user != null)
  104. {
  105. HttpContext.Session.Set(_AuthSessionKey, user.Username);
  106. ViewBag.Title = "Profile Settings - " + _config.Title;
  107. ViewBag.Description = "Your " + _config.Title + " Profile Settings";
  108. ProfileSettingsViewModel model = new ProfileSettingsViewModel();
  109. model.Page = "Profile";
  110. model.UserID = user.UserId;
  111. model.Username = user.Username;
  112. model.About = user.UserSettings.About;
  113. model.Quote = user.UserSettings.Quote;
  114. model.Website = user.UserSettings.Website;
  115. return View("/Areas/User/Views/User/Settings/ProfileSettings.cshtml", model);
  116. }
  117. return Redirect(Url.SubRouteUrl("error", "Error.Http403"));
  118. }
  119. [TrackPageView]
  120. public IActionResult SecuritySettings()
  121. {
  122. string username = User.Identity.Name;
  123. User user = UserHelper.GetUser(_dbContext, username);
  124. if (user != null)
  125. {
  126. HttpContext.Session.Set(_AuthSessionKey, user.Username);
  127. ViewBag.Title = "Security Settings - " + _config.Title;
  128. ViewBag.Description = "Your " + _config.Title + " Security Settings";
  129. SecuritySettingsViewModel model = new SecuritySettingsViewModel();
  130. model.Page = "Security";
  131. model.UserID = user.UserId;
  132. model.Username = user.Username;
  133. model.TrustedDeviceCount = user.TrustedDevices.Count;
  134. model.AuthTokens = new List<AuthTokenViewModel>();
  135. foreach (AuthToken token in user.AuthTokens)
  136. {
  137. AuthTokenViewModel tokenModel = new AuthTokenViewModel();
  138. tokenModel.AuthTokenId = token.AuthTokenId;
  139. tokenModel.Name = token.Name;
  140. tokenModel.LastDateUsed = token.LastDateUsed;
  141. model.AuthTokens.Add(tokenModel);
  142. }
  143. model.PgpPublicKey = user.SecuritySettings.PGPSignature;
  144. model.RecoveryEmail = user.SecuritySettings.RecoveryEmail;
  145. model.RecoveryVerified = user.SecuritySettings.RecoveryVerified;
  146. model.AllowTrustedDevices = user.SecuritySettings.AllowTrustedDevices;
  147. model.TwoFactorEnabled = user.SecuritySettings.TwoFactorEnabled;
  148. model.TwoFactorKey = user.SecuritySettings.TwoFactorKey;
  149. return View("/Areas/User/Views/User/Settings/SecuritySettings.cshtml", model);
  150. }
  151. return Redirect(Url.SubRouteUrl("error", "Error.Http403"));
  152. }
  153. [TrackPageView]
  154. public IActionResult InviteSettings()
  155. {
  156. string username = User.Identity.Name;
  157. User user = UserHelper.GetUser(_dbContext, username);
  158. if (user != null)
  159. {
  160. HttpContext.Session.Set(_AuthSessionKey, user.Username);
  161. ViewBag.Title = "Invite Settings - " + _config.Title;
  162. ViewBag.Description = "Your " + _config.Title + " Invite Settings";
  163. InviteSettingsViewModel model = new InviteSettingsViewModel();
  164. model.Page = "Invite";
  165. model.UserID = user.UserId;
  166. model.Username = user.Username;
  167. List<InviteCodeViewModel> availableCodes = new List<InviteCodeViewModel>();
  168. List<InviteCodeViewModel> claimedCodes = new List<InviteCodeViewModel>();
  169. if (user.OwnedInviteCodes != null)
  170. {
  171. foreach (InviteCode inviteCode in user.OwnedInviteCodes.Where(c => c.Active))
  172. {
  173. InviteCodeViewModel inviteCodeViewModel = new InviteCodeViewModel();
  174. inviteCodeViewModel.ClaimedUser = inviteCode.ClaimedUser;
  175. inviteCodeViewModel.Active = inviteCode.Active;
  176. inviteCodeViewModel.Code = inviteCode.Code;
  177. inviteCodeViewModel.InviteCodeId = inviteCode.InviteCodeId;
  178. inviteCodeViewModel.Owner = inviteCode.Owner;
  179. if (inviteCode.ClaimedUser == null)
  180. availableCodes.Add(inviteCodeViewModel);
  181. if (inviteCode.ClaimedUser != null)
  182. claimedCodes.Add(inviteCodeViewModel);
  183. }
  184. }
  185. model.AvailableCodes = availableCodes;
  186. model.ClaimedCodes = claimedCodes;
  187. return View("/Areas/User/Views/User/Settings/InviteSettings.cshtml", model);
  188. }
  189. return Redirect(Url.SubRouteUrl("error", "Error.Http403"));
  190. }
  191. [TrackPageView]
  192. public IActionResult BlogSettings()
  193. {
  194. string username = User.Identity.Name;
  195. User user = UserHelper.GetUser(_dbContext, username);
  196. if (user != null)
  197. {
  198. HttpContext.Session.Set(_AuthSessionKey, user.Username);
  199. ViewBag.Title = "Blog Settings - " + _config.Title;
  200. ViewBag.Description = "Your " + _config.Title + " Blog Settings";
  201. BlogSettingsViewModel model = new BlogSettingsViewModel();
  202. model.Page = "Blog";
  203. model.UserID = user.UserId;
  204. model.Username = user.Username;
  205. model.Title = user.BlogSettings.Title;
  206. model.Description = user.BlogSettings.Description;
  207. return View("/Areas/User/Views/User/Settings/BlogSettings.cshtml", model);
  208. }
  209. return Redirect(Url.SubRouteUrl("error", "Error.Http403"));
  210. }
  211. [TrackPageView]
  212. public IActionResult UploadSettings()
  213. {
  214. string username = User.Identity.Name;
  215. User user = UserHelper.GetUser(_dbContext, username);
  216. if (user != null)
  217. {
  218. HttpContext.Session.Set(_AuthSessionKey, user.Username);
  219. ViewBag.Title = "Upload Settings - " + _config.Title;
  220. ViewBag.Description = "Your " + _config.Title + " Upload Settings";
  221. UploadSettingsViewModel model = new UploadSettingsViewModel();
  222. model.Page = "Upload";
  223. model.UserID = user.UserId;
  224. model.Username = user.Username;
  225. model.Encrypt = user.UploadSettings.Encrypt;
  226. return View("/Areas/User/Views/User/Settings/UploadSettings.cshtml", model);
  227. }
  228. return Redirect(Url.SubRouteUrl("error", "Error.Http403"));
  229. }
  230. [HttpGet]
  231. [TrackPageView]
  232. [AllowAnonymous]
  233. public IActionResult ViewRawPGP(string username)
  234. {
  235. ViewBag.Title = username + "'s Public Key - " + _config.Title;
  236. ViewBag.Description = "The PGP public key for " + username;
  237. User user = UserHelper.GetUser(_dbContext, username);
  238. if (user != null)
  239. {
  240. if (!string.IsNullOrEmpty(user.SecuritySettings.PGPSignature))
  241. {
  242. return Content(user.SecuritySettings.PGPSignature, "text/plain");
  243. }
  244. }
  245. return Redirect(Url.SubRouteUrl("error", "Error.Http404"));
  246. }
  247. [HttpGet]
  248. [TrackPageView]
  249. [AllowAnonymous]
  250. public IActionResult Login(string ReturnUrl)
  251. {
  252. LoginViewModel model = new LoginViewModel();
  253. model.ReturnUrl = ReturnUrl;
  254. return View("/Areas/User/Views/User/ViewLogin.cshtml", model);
  255. }
  256. [HttpPost]
  257. [AllowAnonymous]
  258. public async Task<IActionResult> Login([Bind(Prefix = "Login")]LoginViewModel model)
  259. {
  260. if (ModelState.IsValid)
  261. {
  262. string username = model.Username;
  263. User user = UserHelper.GetUser(_dbContext, username);
  264. if (user != null)
  265. {
  266. bool userValid = UserHelper.UserPasswordCorrect(_dbContext, _config, user, model.Password);
  267. if (userValid)
  268. {
  269. // Perform transfer actions on the account
  270. UserHelper.TransferUser(_dbContext, _config, user, model.Password);
  271. user.LastSeen = DateTime.Now;
  272. _dbContext.Entry(user).State = EntityState.Modified;
  273. _dbContext.SaveChanges();
  274. // Make sure they aren't banned or anything
  275. if (user.AccountStatus == AccountStatus.Banned)
  276. {
  277. model.Error = true;
  278. model.ErrorMessage = "Account has been banned.";
  279. return GenerateActionResult(new { error = model.ErrorMessage }, View("/Areas/User/Views/User/ViewLogin.cshtml", model));
  280. }
  281. // Let's double check their email and git accounts to make sure they exist
  282. string email = UserHelper.GetUserEmailAddress(_config, username);
  283. if (_config.EmailConfig.Enabled && !UserHelper.UserEmailExists(_config, email))
  284. {
  285. UserHelper.AddUserEmail(_config, email, model.Password);
  286. }
  287. if (_config.GitConfig.Enabled && !UserHelper.UserGitExists(_config, username))
  288. {
  289. UserHelper.AddUserGit(_config, username, model.Password);
  290. }
  291. bool twoFactor = false;
  292. string returnUrl = model.ReturnUrl;
  293. if (user.SecuritySettings.TwoFactorEnabled)
  294. {
  295. twoFactor = true;
  296. // We need to check their device, and two factor them
  297. if (user.SecuritySettings.AllowTrustedDevices)
  298. {
  299. // Check for the trusted device cookie
  300. string token = Request.Cookies[Constants.TRUSTEDDEVICECOOKIE + "_" + username];
  301. if (!string.IsNullOrEmpty(token))
  302. {
  303. if (user.TrustedDevices.Where(d => d.Token == token).FirstOrDefault() != null)
  304. {
  305. // The device token is attached to the user, let's let it slide
  306. twoFactor = false;
  307. }
  308. }
  309. }
  310. }
  311. if (twoFactor)
  312. {
  313. HttpContext.Session.Set(_AuthSessionKey, user.Username);
  314. if (string.IsNullOrEmpty(model.ReturnUrl))
  315. returnUrl = Request.Headers["Referer"].ToString();
  316. returnUrl = Url.SubRouteUrl("user", "User.CheckAuthenticatorCode", new { returnUrl = returnUrl, rememberMe = model.RememberMe });
  317. model.ReturnUrl = string.Empty;
  318. }
  319. else
  320. {
  321. returnUrl = Request.Headers["Referer"].ToString();
  322. // They don't need two factor auth.
  323. await SignInUser(user, (string.IsNullOrEmpty(model.ReturnUrl)) ? returnUrl : model.ReturnUrl, model.RememberMe);
  324. }
  325. if (string.IsNullOrEmpty(model.ReturnUrl))
  326. {
  327. return GenerateActionResult(new { result = returnUrl }, Redirect(returnUrl));
  328. }
  329. else
  330. {
  331. return Redirect(model.ReturnUrl);
  332. }
  333. }
  334. }
  335. }
  336. model.Error = true;
  337. model.ErrorMessage = "Invalid Username or Password.";
  338. return GenerateActionResult(new { error = model.ErrorMessage }, View("/Areas/User/Views/User/ViewLogin.cshtml", model));
  339. }
  340. public async Task<IActionResult> Logout()
  341. {
  342. await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
  343. return Redirect(Url.SubRouteUrl("www", "Home.Index"));
  344. }
  345. [HttpGet]
  346. [TrackPageView]
  347. [AllowAnonymous]
  348. public IActionResult Register(string inviteCode, string ReturnUrl)
  349. {
  350. RegisterViewModel model = new RegisterViewModel();
  351. model.InviteCode = inviteCode;
  352. model.ReturnUrl = ReturnUrl;
  353. return View("/Areas/User/Views/User/ViewRegistration.cshtml", model);
  354. }
  355. [HttpPost]
  356. [AllowAnonymous]
  357. public async Task<IActionResult> Register([Bind(Prefix = "Register")]RegisterViewModel model)
  358. {
  359. model.Error = false;
  360. model.ErrorMessage = string.Empty;
  361. if (ModelState.IsValid)
  362. {
  363. if (_config.UserConfig.RegistrationEnabled)
  364. {
  365. if (!model.Error && !UserHelper.ValidUsername(_config, model.Username))
  366. {
  367. model.Error = true;
  368. model.ErrorMessage = "That username is not valid";
  369. }
  370. if (!model.Error && !UserHelper.UsernameAvailable(_dbContext, _config, model.Username))
  371. {
  372. model.Error = true;
  373. model.ErrorMessage = "That username is not available";
  374. }
  375. if (!model.Error && model.Password != model.ConfirmPassword)
  376. {
  377. model.Error = true;
  378. model.ErrorMessage = "Passwords must match";
  379. }
  380. // Validate the Invite Code
  381. if (!model.Error && _config.UserConfig.InviteCodeRequired && string.IsNullOrEmpty(model.InviteCode))
  382. {
  383. model.Error = true;
  384. model.ErrorMessage = "An Invite Code is required to register";
  385. }
  386. if (!model.Error && !string.IsNullOrEmpty(model.InviteCode) && _dbContext.InviteCodes.Where(c => c.Code == model.InviteCode && c.Active && c.ClaimedUser == null).FirstOrDefault() == null)
  387. {
  388. model.Error = true;
  389. model.ErrorMessage = "Invalid Invite Code";
  390. }
  391. // PGP Key valid?
  392. if (!model.Error && !string.IsNullOrEmpty(model.PublicKey) && !PGP.IsPublicKey(model.PublicKey))
  393. {
  394. model.Error = true;
  395. model.ErrorMessage = "Invalid PGP Public Key";
  396. }
  397. if (!model.Error)
  398. {
  399. try
  400. {
  401. User newUser = new User();
  402. newUser.JoinDate = DateTime.Now;
  403. newUser.Username = model.Username;
  404. newUser.UserSettings = new UserSettings();
  405. newUser.SecuritySettings = new SecuritySettings();
  406. newUser.BlogSettings = new BlogSettings();
  407. newUser.UploadSettings = new UploadSettings();
  408. if (!string.IsNullOrEmpty(model.PublicKey))
  409. newUser.SecuritySettings.PGPSignature = model.PublicKey;
  410. if (!string.IsNullOrEmpty(model.RecoveryEmail))
  411. newUser.SecuritySettings.RecoveryEmail = model.RecoveryEmail;
  412. // if they provided an invite code, let's assign them to it
  413. if (!string.IsNullOrEmpty(model.InviteCode))
  414. {
  415. InviteCode code = _dbContext.InviteCodes.Where(c => c.Code == model.InviteCode).FirstOrDefault();
  416. _dbContext.Entry(code).State = EntityState.Modified;
  417. _dbContext.SaveChanges();
  418. newUser.ClaimedInviteCode = code;
  419. }
  420. UserHelper.AddAccount(_dbContext, _config, newUser, model.Password);
  421. // If they have a recovery email, let's send a verification
  422. if (!string.IsNullOrEmpty(model.RecoveryEmail))
  423. {
  424. string verifyCode = UserHelper.CreateRecoveryEmailVerification(_dbContext, _config, newUser);
  425. string resetUrl = Url.SubRouteUrl("user", "User.ResetPassword", new { Username = model.Username });
  426. string verifyUrl = Url.SubRouteUrl("user", "User.VerifyRecoveryEmail", new { Code = verifyCode });
  427. UserHelper.SendRecoveryEmailVerification(_config, model.Username, model.RecoveryEmail, resetUrl, verifyUrl);
  428. }
  429. }
  430. catch (Exception ex)
  431. {
  432. model.Error = true;
  433. model.ErrorMessage = ex.GetFullMessage(true);
  434. }
  435. if (!model.Error)
  436. {
  437. return await Login(new LoginViewModel { Username = model.Username, Password = model.Password, RememberMe = false, ReturnUrl = model.ReturnUrl });
  438. }
  439. }
  440. }
  441. if (!model.Error)
  442. {
  443. model.Error = true;
  444. model.ErrorMessage = "User Registration is Disabled";
  445. }
  446. }
  447. else
  448. {
  449. model.Error = true;
  450. model.ErrorMessage = "Missing Required Fields";
  451. }
  452. return GenerateActionResult(new { error = model.ErrorMessage }, View("/Areas/User/Views/User/ViewRegistration.cshtml", model));
  453. }
  454. [HttpPost]
  455. [ValidateAntiForgeryToken]
  456. public IActionResult EditBlog(BlogSettingsViewModel settings)
  457. {
  458. if (ModelState.IsValid)
  459. {
  460. try
  461. {
  462. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  463. if (user != null)
  464. {
  465. // Blogs
  466. user.BlogSettings.Title = settings.Title;
  467. user.BlogSettings.Description = settings.Description;
  468. UserHelper.EditAccount(_dbContext, _config, user);
  469. return Json(new { result = true });
  470. }
  471. return Json(new { error = "User does not exist" });
  472. }
  473. catch (Exception ex)
  474. {
  475. return Json(new { error = ex.GetFullMessage(true) });
  476. }
  477. }
  478. return Json(new { error = "Invalid Parameters" });
  479. }
  480. [HttpPost]
  481. [ValidateAntiForgeryToken]
  482. public IActionResult EditProfile(ProfileSettingsViewModel settings)
  483. {
  484. if (ModelState.IsValid)
  485. {
  486. try
  487. {
  488. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  489. if (user != null)
  490. {
  491. // Profile Info
  492. user.UserSettings.Website = settings.Website;
  493. user.UserSettings.Quote = settings.Quote;
  494. user.UserSettings.About = settings.About;
  495. UserHelper.EditAccount(_dbContext, _config, user);
  496. return Json(new { result = true });
  497. }
  498. return Json(new { error = "User does not exist" });
  499. }
  500. catch (Exception ex)
  501. {
  502. return Json(new { error = ex.GetFullMessage(true) });
  503. }
  504. }
  505. return Json(new { error = "Invalid Parameters" });
  506. }
  507. [HttpPost]
  508. [ValidateAntiForgeryToken]
  509. public IActionResult EditSecurity(SecuritySettingsViewModel settings)
  510. {
  511. if (ModelState.IsValid)
  512. {
  513. try
  514. {
  515. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  516. if (user != null)
  517. {
  518. bool changePass = false;
  519. // Changing Password?
  520. if (!string.IsNullOrEmpty(settings.CurrentPassword) && (!string.IsNullOrEmpty(settings.NewPassword) || !string.IsNullOrEmpty(settings.NewPasswordConfirm)))
  521. {
  522. // Old Password Valid?
  523. if (!UserHelper.UserPasswordCorrect(_dbContext, _config, user, settings.CurrentPassword))
  524. {
  525. return Json(new { error = "Invalid Original Password." });
  526. }
  527. // The New Password Match?
  528. if (settings.NewPassword != settings.NewPasswordConfirm)
  529. {
  530. return Json(new { error = "New Password Must Match." });
  531. }
  532. // Are password resets enabled?
  533. if (!_config.UserConfig.PasswordResetEnabled)
  534. {
  535. return Json(new { error = "Password resets are disabled." });
  536. }
  537. changePass = true;
  538. }
  539. // PGP Key valid?
  540. if (!string.IsNullOrEmpty(settings.PgpPublicKey) && !PGP.IsPublicKey(settings.PgpPublicKey))
  541. {
  542. return Json(new { error = "Invalid PGP Public Key" });
  543. }
  544. user.SecuritySettings.PGPSignature = settings.PgpPublicKey;
  545. // Recovery Email
  546. bool newRecovery = false;
  547. if (settings.RecoveryEmail != user.SecuritySettings.RecoveryEmail)
  548. {
  549. newRecovery = true;
  550. user.SecuritySettings.RecoveryEmail = settings.RecoveryEmail;
  551. user.SecuritySettings.RecoveryVerified = false;
  552. }
  553. // Trusted Devices
  554. user.SecuritySettings.AllowTrustedDevices = settings.AllowTrustedDevices;
  555. if (!settings.AllowTrustedDevices)
  556. {
  557. // They turned it off, let's clear the trusted devices
  558. user.TrustedDevices.Clear();
  559. List<TrustedDevice> foundDevices = _dbContext.TrustedDevices.Where(d => d.UserId == user.UserId).ToList();
  560. if (foundDevices != null)
  561. {
  562. foreach (TrustedDevice device in foundDevices)
  563. {
  564. _dbContext.TrustedDevices.Remove(device);
  565. }
  566. }
  567. }
  568. // Two Factor Authentication
  569. bool oldTwoFactor = user.SecuritySettings.TwoFactorEnabled;
  570. user.SecuritySettings.TwoFactorEnabled = settings.TwoFactorEnabled;
  571. string newKey = string.Empty;
  572. if (!oldTwoFactor && settings.TwoFactorEnabled)
  573. {
  574. // They just enabled it, let's regen the key
  575. newKey = Authenticator.GenerateKey();
  576. // New key, so let's upsert their key into git
  577. if (_config.GitConfig.Enabled)
  578. {
  579. UserHelper.CreateUserGitTwoFactor(_config, user.Username, newKey, DateTimeHelper.GetUnixTimestamp());
  580. }
  581. }
  582. else if (!settings.TwoFactorEnabled)
  583. {
  584. // remove the key when it's disabled
  585. newKey = string.Empty;
  586. // Removed the key, so delete it from git as well
  587. if (_config.GitConfig.Enabled)
  588. {
  589. UserHelper.DeleteUserGitTwoFactor(_config, user.Username);
  590. }
  591. }
  592. else
  593. {
  594. // No change, let's use the old value
  595. newKey = user.SecuritySettings.TwoFactorKey;
  596. }
  597. user.SecuritySettings.TwoFactorKey = newKey;
  598. UserHelper.EditAccount(_dbContext, _config, user, changePass, settings.NewPassword);
  599. // If they have a recovery email, let's send a verification
  600. if (!string.IsNullOrEmpty(settings.RecoveryEmail) && newRecovery)
  601. {
  602. string verifyCode = UserHelper.CreateRecoveryEmailVerification(_dbContext, _config, user);
  603. string resetUrl = Url.SubRouteUrl("user", "User.ResetPassword", new { Username = user.Username });
  604. string verifyUrl = Url.SubRouteUrl("user", "User.VerifyRecoveryEmail", new { Code = verifyCode });
  605. UserHelper.SendRecoveryEmailVerification(_config, user.Username, user.SecuritySettings.RecoveryEmail, resetUrl, verifyUrl);
  606. }
  607. if (!oldTwoFactor && settings.TwoFactorEnabled)
  608. {
  609. return Json(new { result = new { checkAuth = true, key = newKey, qrUrl = Url.SubRouteUrl("user", "User.Action", new { action = "GenerateAuthQrCode", key = newKey }) } });
  610. }
  611. return Json(new { result = true });
  612. }
  613. return Json(new { error = "User does not exist" });
  614. }
  615. catch (Exception ex)
  616. {
  617. return Json(new { error = ex.GetFullMessage(true) });
  618. }
  619. }
  620. return Json(new { error = "Invalid Parameters" });
  621. }
  622. [HttpPost]
  623. [ValidateAntiForgeryToken]
  624. public IActionResult EditUpload(UploadSettingsViewModel settings)
  625. {
  626. if (ModelState.IsValid)
  627. {
  628. try
  629. {
  630. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  631. if (user != null)
  632. {
  633. // Profile Info
  634. user.UploadSettings.Encrypt = settings.Encrypt;
  635. UserHelper.EditAccount(_dbContext, _config, user);
  636. return Json(new { result = true });
  637. }
  638. return Json(new { error = "User does not exist" });
  639. }
  640. catch (Exception ex)
  641. {
  642. return Json(new { error = ex.GetFullMessage(true) });
  643. }
  644. }
  645. return Json(new { error = "Invalid Parameters" });
  646. }
  647. [HttpPost]
  648. [ValidateAntiForgeryToken]
  649. public async Task<IActionResult> Delete()
  650. {
  651. if (ModelState.IsValid)
  652. {
  653. try
  654. {
  655. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  656. if (user != null)
  657. {
  658. UserHelper.DeleteAccount(_dbContext, _config, user);
  659. // Sign Out
  660. await Logout();
  661. return Json(new { result = true });
  662. }
  663. }
  664. catch (Exception ex)
  665. {
  666. return Json(new { error = ex.GetFullMessage(true) });
  667. }
  668. }
  669. return Json(new { error = "Unable to delete user" });
  670. }
  671. [HttpGet]
  672. public IActionResult VerifyRecoveryEmail(string code)
  673. {
  674. bool verified = true;
  675. if (string.IsNullOrEmpty(code))
  676. verified &= false;
  677. // Is there a code?
  678. if (verified)
  679. {
  680. verified &= UserHelper.VerifyRecoveryEmail(_dbContext, _config, User.Identity.Name, code);
  681. }
  682. RecoveryEmailVerificationViewModel model = new RecoveryEmailVerificationViewModel();
  683. model.Success = verified;
  684. return View("/Areas/User/Views/User/ViewRecoveryEmailVerification.cshtml", model);
  685. }
  686. [HttpPost]
  687. [ValidateAntiForgeryToken]
  688. public IActionResult ResendVerifyRecoveryEmail()
  689. {
  690. if (ModelState.IsValid)
  691. {
  692. try
  693. {
  694. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  695. if (user != null)
  696. {
  697. // If they have a recovery email, let's send a verification
  698. if (!string.IsNullOrEmpty(user.SecuritySettings.RecoveryEmail))
  699. {
  700. if (!user.SecuritySettings.RecoveryVerified)
  701. {
  702. string verifyCode = UserHelper.CreateRecoveryEmailVerification(_dbContext, _config, user);
  703. string resetUrl = Url.SubRouteUrl("user", "User.ResetPassword", new { Username = user.Username });
  704. string verifyUrl = Url.SubRouteUrl("user", "User.VerifyRecoveryEmail", new { Code = verifyCode });
  705. UserHelper.SendRecoveryEmailVerification(_config, user.Username, user.SecuritySettings.RecoveryEmail, resetUrl, verifyUrl);
  706. return Json(new { result = true });
  707. }
  708. return Json(new { error = "The recovery email is already verified" });
  709. }
  710. }
  711. }
  712. catch (Exception ex)
  713. {
  714. return Json(new { error = ex.GetFullMessage(true) });
  715. }
  716. }
  717. return Json(new { error = "Unable to resend verification" });
  718. }
  719. [HttpGet]
  720. [AllowAnonymous]
  721. public IActionResult ResetPassword(string username)
  722. {
  723. ResetPasswordViewModel model = new ResetPasswordViewModel();
  724. model.Username = username;
  725. return View("/Areas/User/Views/User/ResetPassword.cshtml", model);
  726. }
  727. [HttpPost]
  728. [AllowAnonymous]
  729. [ValidateAntiForgeryToken]
  730. public IActionResult SendResetPasswordVerification(string username)
  731. {
  732. if (ModelState.IsValid)
  733. {
  734. try
  735. {
  736. User user = UserHelper.GetUser(_dbContext, username);
  737. if (user != null)
  738. {
  739. // If they have a recovery email, let's send a verification
  740. if (!string.IsNullOrEmpty(user.SecuritySettings.RecoveryEmail) && user.SecuritySettings.RecoveryVerified)
  741. {
  742. string verifyCode = UserHelper.CreateResetPasswordVerification(_dbContext, _config, user);
  743. string resetUrl = Url.SubRouteUrl("user", "User.VerifyResetPassword", new { Username = user.Username, Code = verifyCode });
  744. UserHelper.SendResetPasswordVerification(_config, user.Username, user.SecuritySettings.RecoveryEmail, resetUrl);
  745. return Json(new { result = true });
  746. }
  747. return Json(new { error = "The username doesn't have a recovery email specified" });
  748. }
  749. return Json(new { error = "The username is not valid" });
  750. }
  751. catch (Exception ex)
  752. {
  753. return Json(new { error = ex.GetFullMessage(true) });
  754. }
  755. }
  756. return Json(new { error = "Unable to send reset link" });
  757. }
  758. [HttpGet]
  759. [AllowAnonymous]
  760. public IActionResult VerifyResetPassword(string username, string code)
  761. {
  762. bool verified = true;
  763. if (string.IsNullOrEmpty(code))
  764. verified &= false;
  765. // Is there a code?
  766. if (verified)
  767. {
  768. verified &= UserHelper.VerifyResetPassword(_dbContext, _config, username, code);
  769. if (verified)
  770. {
  771. // The password reset code is valid, let's get their user account for this session
  772. User user = UserHelper.GetUser(_dbContext, username);
  773. HttpContext.Session.Set(_AuthSessionKey, user.Username);
  774. HttpContext.Session.Set("AuthCode", code);
  775. }
  776. }
  777. ResetPasswordVerificationViewModel model = new ResetPasswordVerificationViewModel();
  778. model.Success = verified;
  779. return View("/Areas/User/Views/User/ResetPasswordVerification.cshtml", model);
  780. }
  781. [HttpPost]
  782. [AllowAnonymous]
  783. [ValidateAntiForgeryToken]
  784. public IActionResult SetUserPassword(SetPasswordViewModel passwordViewModel)
  785. {
  786. if (ModelState.IsValid)
  787. {
  788. try
  789. {
  790. string code = HttpContext.Session.Get<string>("AuthCode");
  791. if (!string.IsNullOrEmpty(code))
  792. {
  793. string username = HttpContext.Session.Get<string>(_AuthSessionKey);
  794. if (!string.IsNullOrEmpty(username))
  795. {
  796. if (string.IsNullOrEmpty(passwordViewModel.Password))
  797. {
  798. return Json(new { error = "Password must not be empty" });
  799. }
  800. if (passwordViewModel.Password != passwordViewModel.PasswordConfirm)
  801. {
  802. return Json(new { error = "Passwords must match" });
  803. }
  804. User newUser = UserHelper.GetUser(_dbContext, username);
  805. UserHelper.EditAccount(_dbContext, _config, newUser, true, passwordViewModel.Password);
  806. return Json(new { result = true });
  807. }
  808. return Json(new { error = "User does not exist" });
  809. }
  810. return Json(new { error = "Invalid Code" });
  811. }
  812. catch (Exception ex)
  813. {
  814. return Json(new { error = ex.GetFullMessage(true) });
  815. }
  816. }
  817. return Json(new { error = "Unable to reset user password" });
  818. }
  819. [HttpGet]
  820. [AllowAnonymous]
  821. public IActionResult ConfirmTwoFactorAuth(string returnUrl, bool rememberMe)
  822. {
  823. string username = HttpContext.Session.Get<string>(_AuthSessionKey);
  824. if (!string.IsNullOrEmpty(username))
  825. {
  826. User user = UserHelper.GetUser(_dbContext, username);
  827. ViewBag.Title = "Unknown Device - " + _config.Title;
  828. ViewBag.Description = "We do not recognize this device.";
  829. TwoFactorViewModel model = new TwoFactorViewModel();
  830. model.ReturnUrl = returnUrl;
  831. model.RememberMe = rememberMe;
  832. model.AllowTrustedDevice = user.SecuritySettings.AllowTrustedDevices;
  833. return View("/Areas/User/Views/User/TwoFactorCheck.cshtml", model);
  834. }
  835. return Redirect(Url.SubRouteUrl("error", "Error.Http403"));
  836. }
  837. [HttpPost]
  838. [AllowAnonymous]
  839. [ValidateAntiForgeryToken]
  840. public async Task<IActionResult> ConfirmAuthenticatorCode(string code, string returnUrl, bool rememberMe, bool rememberDevice, string deviceName)
  841. {
  842. string username = HttpContext.Session.Get<string>(_AuthSessionKey);
  843. if (!string.IsNullOrEmpty(username))
  844. {
  845. User user = UserHelper.GetUser(_dbContext, username);
  846. if (user.SecuritySettings.TwoFactorEnabled)
  847. {
  848. string key = user.SecuritySettings.TwoFactorKey;
  849. TimeAuthenticator ta = new TimeAuthenticator(usedCodeManager: usedCodesManager);
  850. bool isValid = ta.CheckCode(key, code, user);
  851. if (isValid)
  852. {
  853. // the code was valid, let's log them in!
  854. await SignInUser(user, returnUrl, rememberMe);
  855. if (user.SecuritySettings.AllowTrustedDevices && rememberDevice)
  856. {
  857. // They want to remember the device, and have allow trusted devices on
  858. var cookieOptions = UserHelper.CreateTrustedDeviceCookie(_config, user.Username, Request.Host.Host.GetDomain(), Request.IsLocal());
  859. Response.Cookies.Append(Constants.TRUSTEDDEVICECOOKIE + "_" + username, cookieOptions.Item2, cookieOptions.Item1);
  860. TrustedDevice device = new TrustedDevice();
  861. device.UserId = user.UserId;
  862. device.Name = (string.IsNullOrEmpty(deviceName)) ? "Unknown" : deviceName;
  863. device.DateSeen = DateTime.Now;
  864. device.Token = cookieOptions.Item2;
  865. // Add the token
  866. _dbContext.TrustedDevices.Add(device);
  867. _dbContext.SaveChanges();
  868. }
  869. if (string.IsNullOrEmpty(returnUrl))
  870. returnUrl = Request.Headers["Referer"].ToString();
  871. return Json(new { result = returnUrl });
  872. }
  873. return Json(new { error = "Invalid Authentication Code" });
  874. }
  875. return Json(new { error = "User does not have Two Factor Authentication enabled" });
  876. }
  877. return Json(new { error = "User does not exist" });
  878. }
  879. [HttpPost]
  880. [ValidateAntiForgeryToken]
  881. public IActionResult VerifyAuthenticatorCode(string code)
  882. {
  883. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  884. if (user != null)
  885. {
  886. if (user.SecuritySettings.TwoFactorEnabled)
  887. {
  888. string key = user.SecuritySettings.TwoFactorKey;
  889. TimeAuthenticator ta = new TimeAuthenticator(usedCodeManager: usedCodesManager);
  890. bool isValid = ta.CheckCode(key, code, user);
  891. if (isValid)
  892. {
  893. return Json(new { result = true });
  894. }
  895. return Json(new { error = "Invalid Authentication Code" });
  896. }
  897. return Json(new { error = "User does not have Two Factor Authentication enabled" });
  898. }
  899. return Json(new { error = "User does not exist" });
  900. }
  901. [HttpGet]
  902. public IActionResult GenerateAuthQrCode(string key)
  903. {
  904. var ProvisionUrl = string.Format("otpauth://totp/{0}:{1}?secret={2}", _config.Title, User.Identity.Name, key);
  905. QRCodeGenerator qrGenerator = new QRCodeGenerator();
  906. QRCodeData qrCodeData = qrGenerator.CreateQrCode(ProvisionUrl, QRCodeGenerator.ECCLevel.Q);
  907. PngByteQRCode qrCode = new PngByteQRCode(qrCodeData);
  908. return File(qrCode.GetGraphic(20), "image/png");
  909. }
  910. [HttpPost]
  911. [ValidateAntiForgeryToken]
  912. public IActionResult ClearTrustedDevices()
  913. {
  914. try
  915. {
  916. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  917. if (user != null)
  918. {
  919. if (user.SecuritySettings.AllowTrustedDevices)
  920. {
  921. // let's clear the trusted devices
  922. user.TrustedDevices.Clear();
  923. List<TrustedDevice> foundDevices = _dbContext.TrustedDevices.Where(d => d.UserId == user.UserId).ToList();
  924. if (foundDevices != null)
  925. {
  926. foreach (TrustedDevice device in foundDevices)
  927. {
  928. _dbContext.TrustedDevices.Remove(device);
  929. }
  930. }
  931. _dbContext.Entry(user).State = EntityState.Modified;
  932. _dbContext.SaveChanges();
  933. return Json(new { result = true });
  934. }
  935. return Json(new { error = "User does not allow trusted devices" });
  936. }
  937. return Json(new { error = "User does not exist" });
  938. }
  939. catch (Exception ex)
  940. {
  941. return Json(new { error = ex.GetFullMessage(true) });
  942. }
  943. }
  944. [HttpPost]
  945. [ValidateAntiForgeryToken]
  946. public async Task<IActionResult> GenerateToken(string name, [FromServices] ICompositeViewEngine viewEngine)
  947. {
  948. try
  949. {
  950. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  951. if (user != null)
  952. {
  953. string newTokenStr = UserHelper.GenerateAuthToken(_dbContext, user.Username);
  954. if (!string.IsNullOrEmpty(newTokenStr))
  955. {
  956. AuthToken token = new AuthToken();
  957. token.UserId = user.UserId;
  958. token.HashedToken = SHA256.Hash(newTokenStr);
  959. token.Name = name;
  960. _dbContext.AuthTokens.Add(token);
  961. _dbContext.SaveChanges();
  962. AuthTokenViewModel model = new AuthTokenViewModel();
  963. model.AuthTokenId = token.AuthTokenId;
  964. model.Name = token.Name;
  965. model.LastDateUsed = token.LastDateUsed;
  966. string renderedView = await RenderPartialViewToString(viewEngine, "~/Areas/User/Views/User/Settings/AuthToken.cshtml", model);
  967. return Json(new { result = new { token = newTokenStr, html = renderedView } });
  968. }
  969. return Json(new { error = "Unable to generate Auth Token" });
  970. }
  971. return Json(new { error = "User does not exist" });
  972. }
  973. catch (Exception ex)
  974. {
  975. return Json(new { error = ex.GetFullMessage(true) });
  976. }
  977. }
  978. [HttpPost]
  979. [ValidateAntiForgeryToken]
  980. public IActionResult RevokeAllTokens()
  981. {
  982. try
  983. {
  984. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  985. if (user != null)
  986. {
  987. user.AuthTokens.Clear();
  988. List<AuthToken> foundTokens = _dbContext.AuthTokens.Where(d => d.UserId == user.UserId).ToList();
  989. if (foundTokens != null)
  990. {
  991. foreach (AuthToken token in foundTokens)
  992. {
  993. _dbContext.AuthTokens.Remove(token);
  994. }
  995. }
  996. _dbContext.Entry(user).State = EntityState.Modified;
  997. _dbContext.SaveChanges();
  998. return Json(new { result = true });
  999. }
  1000. return Json(new { error = "User does not exist" });
  1001. }
  1002. catch (Exception ex)
  1003. {
  1004. return Json(new { error = ex.GetFullMessage(true) });
  1005. }
  1006. }
  1007. [HttpPost]
  1008. [ValidateAntiForgeryToken]
  1009. public IActionResult EditTokenName(int tokenId, string name)
  1010. {
  1011. try
  1012. {
  1013. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  1014. if (user != null)
  1015. {
  1016. AuthToken foundToken = _dbContext.AuthTokens.Where(d => d.UserId == user.UserId && d.AuthTokenId == tokenId).FirstOrDefault();
  1017. if (foundToken != null)
  1018. {
  1019. foundToken.Name = name;
  1020. _dbContext.Entry(foundToken).State = EntityState.Modified;
  1021. _dbContext.SaveChanges();
  1022. return Json(new { result = new { name = name } });
  1023. }
  1024. return Json(new { error = "Authentication Token does not exist" });
  1025. }
  1026. return Json(new { error = "User does not exist" });
  1027. }
  1028. catch (Exception ex)
  1029. {
  1030. return Json(new { error = ex.GetFullMessage(true) });
  1031. }
  1032. }
  1033. [HttpPost]
  1034. [ValidateAntiForgeryToken]
  1035. public IActionResult DeleteToken(int tokenId)
  1036. {
  1037. try
  1038. {
  1039. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  1040. if (user != null)
  1041. {
  1042. AuthToken foundToken = _dbContext.AuthTokens.Where(d => d.UserId == user.UserId && d.AuthTokenId == tokenId).FirstOrDefault();
  1043. if (foundToken != null)
  1044. {
  1045. _dbContext.AuthTokens.Remove(foundToken);
  1046. user.AuthTokens.Remove(foundToken);
  1047. _dbContext.Entry(user).State = EntityState.Modified;
  1048. _dbContext.SaveChanges();
  1049. return Json(new { result = true });
  1050. }
  1051. return Json(new { error = "Authentication Token does not exist" });
  1052. }
  1053. return Json(new { error = "User does not exist" });
  1054. }
  1055. catch (Exception ex)
  1056. {
  1057. return Json(new { error = ex.GetFullMessage(true) });
  1058. }
  1059. }
  1060. [HttpPost]
  1061. [ValidateAntiForgeryToken]
  1062. public IActionResult CreateInviteCodeLink(int inviteCodeId)
  1063. {
  1064. try
  1065. {
  1066. InviteCode code = _dbContext.InviteCodes.Where(c => c.InviteCodeId == inviteCodeId).FirstOrDefault();
  1067. if (code != null)
  1068. {
  1069. if (User.Identity.IsAuthenticated)
  1070. {
  1071. if (code.Owner.Username == User.Identity.Name)
  1072. {
  1073. return Json(new { result = Url.SubRouteUrl("user", "User.Register", new { inviteCode = code.Code }) });
  1074. }
  1075. }
  1076. return Json(new { error = "Invite Code not associated with this user" });
  1077. }
  1078. return Json(new { error = "Invalid Invite Code" });
  1079. }
  1080. catch (Exception ex)
  1081. {
  1082. return Json(new { error = ex.GetFullMessage(true) });
  1083. }
  1084. }
  1085. private async Task SignInUser(User user, string returnUrl, bool rememberMe)
  1086. {
  1087. var claims = new List<Claim>
  1088. {
  1089. new Claim(ClaimTypes.Name, user.Username)
  1090. };
  1091. // Add their roles
  1092. foreach (var role in user.UserRoles)
  1093. {
  1094. claims.Add(new Claim(ClaimTypes.Role, role.Role.Name));
  1095. }
  1096. var claimsIdentity = new ClaimsIdentity(claims, CookieAuthenticationDefaults.AuthenticationScheme);
  1097. var authProps = new AuthenticationProperties
  1098. {
  1099. IsPersistent = rememberMe,
  1100. ExpiresUtc = DateTime.UtcNow.AddMonths(1),
  1101. RedirectUri = returnUrl
  1102. };
  1103. await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity), authProps);
  1104. }
  1105. }
  1106. }