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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362
  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. using IdentityServer4.Services;
  28. using Microsoft.AspNetCore.Identity;
  29. using IdentityModel.Client;
  30. using System.Net.Http;
  31. using Newtonsoft.Json.Linq;
  32. using Teknik.Security;
  33. using Microsoft.IdentityModel.Tokens;
  34. using IdentityModel;
  35. using System.Security.Cryptography;
  36. using System.IdentityModel.Tokens.Jwt;
  37. using Microsoft.AspNetCore.Http;
  38. using IdentityServer4.Models;
  39. namespace Teknik.Areas.Users.Controllers
  40. {
  41. [Authorize]
  42. [Area("User")]
  43. public class UserController : DefaultController
  44. {
  45. private static readonly UsedCodesManager usedCodesManager = new UsedCodesManager();
  46. private const string _AuthSessionKey = "AuthenticatedUser";
  47. private readonly IHttpContextAccessor _httpContextAccessor;
  48. private ISession _session => _httpContextAccessor.HttpContext.Session;
  49. private readonly LogoutSessionManager _logoutSessions;
  50. public UserController(ILogger<Logger> logger, Config config, TeknikEntities dbContext, LogoutSessionManager logoutSessions, IHttpContextAccessor httpContextAccessor) : base(logger, config, dbContext)
  51. {
  52. _logoutSessions = logoutSessions;
  53. _httpContextAccessor = httpContextAccessor;
  54. }
  55. [HttpGet]
  56. public IActionResult Login(string returnUrl)
  57. {
  58. // Let's double check their email and git accounts to make sure they exist
  59. string email = UserHelper.GetUserEmailAddress(_config, User.Identity.Name);
  60. if (_config.EmailConfig.Enabled && !UserHelper.UserEmailExists(_config, email))
  61. {
  62. //UserHelper.AddUserEmail(_config, email, model.Password);
  63. }
  64. if (_config.GitConfig.Enabled && !UserHelper.UserGitExists(_config, User.Identity.Name))
  65. {
  66. //UserHelper.AddUserGit(_config, User.Identity.Name, model.Password);
  67. }
  68. if (!string.IsNullOrEmpty(returnUrl))
  69. {
  70. return Redirect(returnUrl);
  71. }
  72. return Redirect(Url.SubRouteUrl("www", "Home.Index"));
  73. }
  74. [HttpGet]
  75. public async Task Logout()
  76. {
  77. // these are the sub & sid to signout
  78. //var sub = User.FindFirst("sub")?.Value;
  79. //var sid = User.FindFirst("sid")?.Value;
  80. await HttpContext.SignOutAsync("Cookies");
  81. await HttpContext.SignOutAsync("oidc");
  82. //_logoutSessions.Add(sub, sid);
  83. }
  84. [AllowAnonymous]
  85. public IActionResult GetPremium()
  86. {
  87. ViewBag.Title = "Get a Premium Account";
  88. GetPremiumViewModel model = new GetPremiumViewModel();
  89. return View(model);
  90. }
  91. [HttpGet]
  92. [AllowAnonymous]
  93. public IActionResult Register(string inviteCode, string ReturnUrl)
  94. {
  95. RegisterViewModel model = new RegisterViewModel();
  96. model.InviteCode = inviteCode;
  97. model.ReturnUrl = ReturnUrl;
  98. return View("/Areas/User/Views/User/ViewRegistration.cshtml", model);
  99. }
  100. [HttpOptions]
  101. [HttpPost]
  102. [AllowAnonymous]
  103. public async Task<IActionResult> Register([Bind(Prefix = "Register")]RegisterViewModel model)
  104. {
  105. model.Error = false;
  106. model.ErrorMessage = string.Empty;
  107. if (ModelState.IsValid)
  108. {
  109. if (_config.UserConfig.RegistrationEnabled)
  110. {
  111. if (!model.Error && !UserHelper.ValidUsername(_config, model.Username))
  112. {
  113. model.Error = true;
  114. model.ErrorMessage = "That username is not valid";
  115. }
  116. if (!model.Error && !(await UserHelper.UsernameAvailable(_dbContext, _config, model.Username)))
  117. {
  118. model.Error = true;
  119. model.ErrorMessage = "That username is not available";
  120. }
  121. if (!model.Error && model.Password != model.ConfirmPassword)
  122. {
  123. model.Error = true;
  124. model.ErrorMessage = "Passwords must match";
  125. }
  126. // Validate the Invite Code
  127. if (!model.Error && _config.UserConfig.InviteCodeRequired && string.IsNullOrEmpty(model.InviteCode))
  128. {
  129. model.Error = true;
  130. model.ErrorMessage = "An Invite Code is required to register";
  131. }
  132. if (!model.Error && !string.IsNullOrEmpty(model.InviteCode) && _dbContext.InviteCodes.Where(c => c.Code == model.InviteCode && c.Active && c.ClaimedUser == null).FirstOrDefault() == null)
  133. {
  134. model.Error = true;
  135. model.ErrorMessage = "Invalid Invite Code";
  136. }
  137. if (!model.Error)
  138. {
  139. try
  140. {
  141. await UserHelper.CreateAccount(_dbContext, _config, Url, model.Username, model.Password, model.RecoveryEmail, model.InviteCode);
  142. }
  143. catch (Exception ex)
  144. {
  145. model.Error = true;
  146. model.ErrorMessage = ex.GetFullMessage(true);
  147. }
  148. if (!model.Error)
  149. {
  150. // Let's log them in
  151. return GenerateActionResult(new { success = true, redirectUrl = Url.SubRouteUrl("account", "User.Login", new { returnUrl = model.ReturnUrl }) }, Redirect(Url.SubRouteUrl("account", "User.Login", new { returnUrl = model.ReturnUrl })));
  152. }
  153. }
  154. }
  155. if (!model.Error)
  156. {
  157. model.Error = true;
  158. model.ErrorMessage = "User Registration is Disabled";
  159. }
  160. }
  161. else
  162. {
  163. model.Error = true;
  164. model.ErrorMessage = "Missing Required Fields";
  165. }
  166. return GenerateActionResult(new { error = model.ErrorMessage }, View("/Areas/User/Views/User/ViewRegistration.cshtml", model));
  167. }
  168. // GET: Profile/Profile
  169. [AllowAnonymous]
  170. public async Task<IActionResult> ViewProfile(string username)
  171. {
  172. if (string.IsNullOrEmpty(username))
  173. {
  174. username = User.Identity.Name;
  175. }
  176. ProfileViewModel model = new ProfileViewModel();
  177. ViewBag.Title = "User Does Not Exist";
  178. ViewBag.Description = "The User does not exist";
  179. try
  180. {
  181. User user = UserHelper.GetUser(_dbContext, username);
  182. if (user != null)
  183. {
  184. ViewBag.Title = username + "'s Profile";
  185. ViewBag.Description = "Viewing " + username + "'s Profile";
  186. model.UserID = user.UserId;
  187. model.Username = user.Username;
  188. if (_config.EmailConfig.Enabled)
  189. {
  190. model.Email = string.Format("{0}@{1}", user.Username, _config.EmailConfig.Domain);
  191. }
  192. // Get the user claims for this user
  193. model.IdentityUserInfo = await IdentityHelper.GetIdentityUserInfo(_config, user.Username);
  194. model.LastSeen = UserHelper.GetLastAccountActivity(_dbContext, _config, user.Username, model.IdentityUserInfo);
  195. model.UserSettings = user.UserSettings;
  196. model.BlogSettings = user.BlogSettings;
  197. model.UploadSettings = user.UploadSettings;
  198. model.Uploads = _dbContext.Uploads.Where(u => u.UserId == user.UserId).OrderByDescending(u => u.DateUploaded).ToList();
  199. model.Pastes = _dbContext.Pastes.Where(u => u.UserId == user.UserId).OrderByDescending(u => u.DatePosted).ToList();
  200. model.ShortenedUrls = _dbContext.ShortenedUrls.Where(s => s.UserId == user.UserId).OrderByDescending(s => s.DateAdded).ToList();
  201. model.Vaults = _dbContext.Vaults.Where(v => v.UserId == user.UserId).OrderByDescending(v => v.DateCreated).ToList();
  202. return View(model);
  203. }
  204. model.Error = true;
  205. model.ErrorMessage = "The user does not exist";
  206. }
  207. catch (Exception ex)
  208. {
  209. model.Error = true;
  210. model.ErrorMessage = ex.GetFullMessage(true);
  211. }
  212. return View(model);
  213. }
  214. public IActionResult ViewServiceData()
  215. {
  216. string username = User.Identity.Name;
  217. ViewServiceDataViewModel model = new ViewServiceDataViewModel();
  218. ViewBag.Title = "User Does Not Exist";
  219. ViewBag.Description = "The User does not exist";
  220. try
  221. {
  222. User user = UserHelper.GetUser(_dbContext, username);
  223. if (user != null)
  224. {
  225. ViewBag.Title = "Service Data";
  226. ViewBag.Description = "Viewing all of your service data";
  227. model.Uploads = _dbContext.Uploads.Where(u => u.UserId == user.UserId).OrderByDescending(u => u.DateUploaded).ToList();
  228. model.Pastes = _dbContext.Pastes.Where(u => u.UserId == user.UserId).OrderByDescending(u => u.DatePosted).ToList();
  229. model.ShortenedUrls = _dbContext.ShortenedUrls.Where(s => s.UserId == user.UserId).OrderByDescending(s => s.DateAdded).ToList();
  230. model.Vaults = _dbContext.Vaults.Where(v => v.UserId == user.UserId).OrderByDescending(v => v.DateCreated).ToList();
  231. return View(model);
  232. }
  233. model.Error = true;
  234. model.ErrorMessage = "The user does not exist";
  235. }
  236. catch (Exception ex)
  237. {
  238. model.Error = true;
  239. model.ErrorMessage = ex.GetFullMessage(true);
  240. }
  241. return View(model);
  242. }
  243. public IActionResult Settings()
  244. {
  245. return Redirect(Url.SubRouteUrl("account", "User.ProfileSettings"));
  246. }
  247. public IActionResult ProfileSettings()
  248. {
  249. string username = User.Identity.Name;
  250. User user = UserHelper.GetUser(_dbContext, username);
  251. if (user != null)
  252. {
  253. ViewBag.Title = "Profile Settings";
  254. ViewBag.Description = "Your " + _config.Title + " Profile Settings";
  255. ProfileSettingsViewModel model = new ProfileSettingsViewModel();
  256. model.Page = "Profile";
  257. model.UserID = user.UserId;
  258. model.Username = user.Username;
  259. model.About = user.UserSettings.About;
  260. model.Quote = user.UserSettings.Quote;
  261. model.Website = user.UserSettings.Website;
  262. return View("/Areas/User/Views/User/Settings/ProfileSettings.cshtml", model);
  263. }
  264. return new StatusCodeResult(StatusCodes.Status403Forbidden);
  265. }
  266. public IActionResult AccountSettings()
  267. {
  268. string username = User.Identity.Name;
  269. User user = UserHelper.GetUser(_dbContext, username);
  270. if (user != null)
  271. {
  272. ViewBag.Title = "Account Settings";
  273. ViewBag.Description = "Your " + _config.Title + " Account Settings";
  274. AccountSettingsViewModel model = new AccountSettingsViewModel();
  275. model.Page = "Account";
  276. model.UserID = user.UserId;
  277. model.Username = user.Username;
  278. return View("/Areas/User/Views/User/Settings/AccountSettings.cshtml", model);
  279. }
  280. return new StatusCodeResult(StatusCodes.Status403Forbidden);
  281. }
  282. public async Task<IActionResult> SecuritySettings()
  283. {
  284. string username = User.Identity.Name;
  285. User user = UserHelper.GetUser(_dbContext, username);
  286. if (user != null)
  287. {
  288. ViewBag.Title = "Security Settings";
  289. ViewBag.Description = "Your " + _config.Title + " Security Settings";
  290. SecuritySettingsViewModel model = new SecuritySettingsViewModel();
  291. model.Page = "Security";
  292. model.UserID = user.UserId;
  293. model.Username = user.Username;
  294. // Get the user secure info
  295. IdentityUserInfo userInfo = await IdentityHelper.GetIdentityUserInfo(_config, user.Username);
  296. //model.TrustedDeviceCount = user.TrustedDevices.Count;
  297. //model.AuthTokens = new List<AuthTokenViewModel>();
  298. //foreach (AuthToken token in user.AuthTokens)
  299. //{
  300. // AuthTokenViewModel tokenModel = new AuthTokenViewModel();
  301. // tokenModel.AuthTokenId = token.AuthTokenId;
  302. // tokenModel.Name = token.Name;
  303. // tokenModel.LastDateUsed = token.LastDateUsed;
  304. // model.AuthTokens.Add(tokenModel);
  305. //}
  306. model.PgpPublicKey = userInfo.PGPPublicKey;
  307. model.RecoveryEmail = userInfo.RecoveryEmail;
  308. if (userInfo.RecoveryVerified.HasValue)
  309. model.RecoveryVerified = userInfo.RecoveryVerified.Value;
  310. if (userInfo.TwoFactorEnabled.HasValue)
  311. model.TwoFactorEnabled = userInfo.TwoFactorEnabled.Value;
  312. return View("/Areas/User/Views/User/Settings/SecuritySettings.cshtml", model);
  313. }
  314. return new StatusCodeResult(StatusCodes.Status403Forbidden);
  315. }
  316. public async Task<IActionResult> DeveloperSettings()
  317. {
  318. string username = User.Identity.Name;
  319. User user = UserHelper.GetUser(_dbContext, username);
  320. if (user != null)
  321. {
  322. ViewBag.Title = "Developer Settings";
  323. ViewBag.Description = "Your " + _config.Title + " Developer Settings";
  324. DeveloperSettingsViewModel model = new DeveloperSettingsViewModel();
  325. model.Page = "Developer";
  326. model.UserID = user.UserId;
  327. model.Username = user.Username;
  328. model.AuthTokens = new List<AuthTokenViewModel>();
  329. model.Clients = new List<ClientViewModel>();
  330. //foreach (AuthToken token in user.AuthTokens)
  331. //{
  332. // AuthTokenViewModel tokenModel = new AuthTokenViewModel();
  333. // tokenModel.AuthTokenId = token.AuthTokenId;
  334. // tokenModel.Name = token.Name;
  335. // tokenModel.LastDateUsed = token.LastDateUsed;
  336. // model.AuthTokens.Add(tokenModel);
  337. //}
  338. Client[] clients = await IdentityHelper.GetClients(_config, username);
  339. foreach (Client client in clients)
  340. {
  341. model.Clients.Add(new ClientViewModel()
  342. {
  343. Id = client.ClientId,
  344. Name = client.ClientName,
  345. HomepageUrl = client.ClientUri,
  346. LogoUrl = client.LogoUri,
  347. CallbackUrl = string.Join(',', client.RedirectUris),
  348. AllowedScopes = client.AllowedScopes
  349. });
  350. }
  351. return View("/Areas/User/Views/User/Settings/DeveloperSettings.cshtml", model);
  352. }
  353. return new StatusCodeResult(StatusCodes.Status403Forbidden);
  354. }
  355. public IActionResult InviteSettings()
  356. {
  357. string username = User.Identity.Name;
  358. User user = UserHelper.GetUser(_dbContext, username);
  359. if (user != null)
  360. {
  361. ViewBag.Title = "Invite Settings";
  362. ViewBag.Description = "Your " + _config.Title + " Invite Settings";
  363. InviteSettingsViewModel model = new InviteSettingsViewModel();
  364. model.Page = "Invite";
  365. model.UserID = user.UserId;
  366. model.Username = user.Username;
  367. List<InviteCodeViewModel> availableCodes = new List<InviteCodeViewModel>();
  368. List<InviteCodeViewModel> claimedCodes = new List<InviteCodeViewModel>();
  369. if (user.OwnedInviteCodes != null)
  370. {
  371. foreach (InviteCode inviteCode in user.OwnedInviteCodes.Where(c => c.Active))
  372. {
  373. InviteCodeViewModel inviteCodeViewModel = new InviteCodeViewModel();
  374. inviteCodeViewModel.ClaimedUser = inviteCode.ClaimedUser;
  375. inviteCodeViewModel.Active = inviteCode.Active;
  376. inviteCodeViewModel.Code = inviteCode.Code;
  377. inviteCodeViewModel.InviteCodeId = inviteCode.InviteCodeId;
  378. inviteCodeViewModel.Owner = inviteCode.Owner;
  379. if (inviteCode.ClaimedUser == null)
  380. availableCodes.Add(inviteCodeViewModel);
  381. if (inviteCode.ClaimedUser != null)
  382. claimedCodes.Add(inviteCodeViewModel);
  383. }
  384. }
  385. model.AvailableCodes = availableCodes;
  386. model.ClaimedCodes = claimedCodes;
  387. return View("/Areas/User/Views/User/Settings/InviteSettings.cshtml", model);
  388. }
  389. return new StatusCodeResult(StatusCodes.Status403Forbidden);
  390. }
  391. public IActionResult BlogSettings()
  392. {
  393. string username = User.Identity.Name;
  394. User user = UserHelper.GetUser(_dbContext, username);
  395. if (user != null)
  396. {
  397. ViewBag.Title = "Blog Settings";
  398. ViewBag.Description = "Your " + _config.Title + " Blog Settings";
  399. BlogSettingsViewModel model = new BlogSettingsViewModel();
  400. model.Page = "Blog";
  401. model.UserID = user.UserId;
  402. model.Username = user.Username;
  403. model.Title = user.BlogSettings.Title;
  404. model.Description = user.BlogSettings.Description;
  405. return View("/Areas/User/Views/User/Settings/BlogSettings.cshtml", model);
  406. }
  407. return new StatusCodeResult(StatusCodes.Status403Forbidden);
  408. }
  409. public IActionResult UploadSettings()
  410. {
  411. string username = User.Identity.Name;
  412. User user = UserHelper.GetUser(_dbContext, username);
  413. if (user != null)
  414. {
  415. ViewBag.Title = "Upload Settings";
  416. ViewBag.Description = "Your " + _config.Title + " Upload Settings";
  417. UploadSettingsViewModel model = new UploadSettingsViewModel();
  418. model.Page = "Upload";
  419. model.UserID = user.UserId;
  420. model.Username = user.Username;
  421. model.Encrypt = user.UploadSettings.Encrypt;
  422. model.ExpirationLength = user.UploadSettings.ExpirationLength;
  423. model.ExpirationUnit = user.UploadSettings.ExpirationUnit;
  424. return View("/Areas/User/Views/User/Settings/UploadSettings.cshtml", model);
  425. }
  426. return new StatusCodeResult(StatusCodes.Status403Forbidden);
  427. }
  428. [HttpGet]
  429. [AllowAnonymous]
  430. public async Task<IActionResult> ViewRawPGP(string username)
  431. {
  432. ViewBag.Title = username + "'s Public Key";
  433. ViewBag.Description = "The PGP public key for " + username;
  434. IdentityUserInfo userClaims = await IdentityHelper.GetIdentityUserInfo(_config, username);
  435. if (!string.IsNullOrEmpty(userClaims.PGPPublicKey))
  436. {
  437. return Content(userClaims.PGPPublicKey, "text/plain");
  438. }
  439. return new StatusCodeResult(StatusCodes.Status404NotFound);
  440. }
  441. [HttpPost]
  442. [ValidateAntiForgeryToken]
  443. public IActionResult EditBlog(BlogSettingsViewModel settings)
  444. {
  445. if (ModelState.IsValid)
  446. {
  447. try
  448. {
  449. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  450. if (user != null)
  451. {
  452. // Blogs
  453. user.BlogSettings.Title = settings.Title;
  454. user.BlogSettings.Description = settings.Description;
  455. UserHelper.EditAccount(_dbContext, _config, user);
  456. return Json(new { result = true });
  457. }
  458. return Json(new { error = "User does not exist" });
  459. }
  460. catch (Exception ex)
  461. {
  462. return Json(new { error = ex.GetFullMessage(true) });
  463. }
  464. }
  465. return Json(new { error = "Invalid Parameters" });
  466. }
  467. [HttpPost]
  468. [ValidateAntiForgeryToken]
  469. public IActionResult EditProfile(ProfileSettingsViewModel settings)
  470. {
  471. if (ModelState.IsValid)
  472. {
  473. try
  474. {
  475. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  476. if (user != null)
  477. {
  478. // Profile Info
  479. user.UserSettings.Website = settings.Website;
  480. user.UserSettings.Quote = settings.Quote;
  481. user.UserSettings.About = settings.About;
  482. UserHelper.EditAccount(_dbContext, _config, user);
  483. return Json(new { result = true });
  484. }
  485. return Json(new { error = "User does not exist" });
  486. }
  487. catch (Exception ex)
  488. {
  489. return Json(new { error = ex.GetFullMessage(true) });
  490. }
  491. }
  492. return Json(new { error = "Invalid Parameters" });
  493. }
  494. [HttpPost]
  495. [ValidateAntiForgeryToken]
  496. public async Task<IActionResult> EditSecurity(SecuritySettingsViewModel settings)
  497. {
  498. if (ModelState.IsValid)
  499. {
  500. try
  501. {
  502. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  503. if (user != null)
  504. {
  505. // PGP Key valid?
  506. if (!string.IsNullOrEmpty(settings.PgpPublicKey) && !PGP.IsPublicKey(settings.PgpPublicKey))
  507. {
  508. return Json(new { error = "Invalid PGP Public Key" });
  509. }
  510. // Get the user secure info
  511. IdentityUserInfo userInfo = await IdentityHelper.GetIdentityUserInfo(_config, user.Username);
  512. if (userInfo.PGPPublicKey != settings.PgpPublicKey)
  513. {
  514. var result = await IdentityHelper.UpdatePGPPublicKey(_config, user.Username, settings.PgpPublicKey);
  515. if (!result.Success)
  516. return Json(new { error = result.Message });
  517. }
  518. if (userInfo.RecoveryEmail != settings.RecoveryEmail)
  519. {
  520. var token = await IdentityHelper.UpdateRecoveryEmail(_config, user.Username, settings.RecoveryEmail);
  521. // If they have a recovery email, let's send a verification
  522. if (!string.IsNullOrEmpty(settings.RecoveryEmail))
  523. {
  524. string resetUrl = Url.SubRouteUrl("account", "User.ResetPassword", new { Username = user.Username });
  525. string verifyUrl = Url.SubRouteUrl("account", "User.VerifyRecoveryEmail", new { Username = user.Username, Code = WebUtility.UrlEncode(token) });
  526. UserHelper.SendRecoveryEmailVerification(_config, user.Username, settings.RecoveryEmail, resetUrl, verifyUrl);
  527. }
  528. }
  529. //if (!settings.TwoFactorEnabled && (!userInfo.TwoFactorEnabled.HasValue || userInfo.TwoFactorEnabled.Value))
  530. //{
  531. // var result = await IdentityHelper.Disable2FA(_config, user.Username);
  532. // if (!result.Success)
  533. // return Json(new { error = result.Message });
  534. //}
  535. //UserHelper.EditAccount(_dbContext, _config, user, changePass, settings.NewPassword);
  536. //if (!oldTwoFactor && settings.TwoFactorEnabled)
  537. //{
  538. // return Json(new { result = new { checkAuth = true, key = newKey, qrUrl = Url.SubRouteUrl("account", "User.Action", new { action = "GenerateAuthQrCode", key = newKey }) } });
  539. //}
  540. return Json(new { result = true });
  541. }
  542. return Json(new { error = "User does not exist" });
  543. }
  544. catch (Exception ex)
  545. {
  546. return Json(new { error = ex.GetFullMessage(true) });
  547. }
  548. }
  549. return Json(new { error = "Invalid Parameters" });
  550. }
  551. [HttpPost]
  552. [ValidateAntiForgeryToken]
  553. public IActionResult EditUpload(UploadSettingsViewModel settings)
  554. {
  555. if (ModelState.IsValid)
  556. {
  557. try
  558. {
  559. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  560. if (user != null)
  561. {
  562. // Profile Info
  563. user.UploadSettings.Encrypt = settings.Encrypt;
  564. user.UploadSettings.ExpirationUnit = settings.ExpirationUnit;
  565. user.UploadSettings.ExpirationLength = settings.ExpirationLength;
  566. UserHelper.EditAccount(_dbContext, _config, user);
  567. return Json(new { result = true });
  568. }
  569. return Json(new { error = "User does not exist" });
  570. }
  571. catch (Exception ex)
  572. {
  573. return Json(new { error = ex.GetFullMessage(true) });
  574. }
  575. }
  576. return Json(new { error = "Invalid Parameters" });
  577. }
  578. public async Task<IActionResult> ChangePassword(AccountSettingsViewModel settings)
  579. {
  580. if (ModelState.IsValid)
  581. {
  582. try
  583. {
  584. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  585. if (user != null)
  586. {
  587. // Did they enter their old password
  588. if (string.IsNullOrEmpty(settings.CurrentPassword))
  589. return Json(new { error = "You must enter your current password" });
  590. // Did they enter a new password
  591. if (string.IsNullOrEmpty(settings.NewPassword) || string.IsNullOrEmpty(settings.NewPasswordConfirm))
  592. return Json(new { error = "You must enter your new password" });
  593. // Old Password Valid?
  594. if (!(await UserHelper.UserPasswordCorrect(_config, user.Username, settings.CurrentPassword)))
  595. return Json(new { error = "Invalid Original Password" });
  596. // The New Password Match?
  597. if (settings.NewPassword != settings.NewPasswordConfirm)
  598. return Json(new { error = "New Password must match confirmation" });
  599. // Are password resets enabled?
  600. if (!_config.UserConfig.PasswordResetEnabled)
  601. return Json(new { error = "Password resets are disabled" });
  602. // Change their password
  603. await UserHelper.ChangeAccountPassword(_dbContext, _config, user.Username, settings.CurrentPassword, settings.NewPassword);
  604. return Json(new { result = true });
  605. }
  606. return Json(new { error = "User does not exist" });
  607. }
  608. catch (Exception ex)
  609. {
  610. return Json(new { error = ex.GetFullMessage(true) });
  611. }
  612. }
  613. return Json(new { error = "Invalid Parameters" });
  614. }
  615. [HttpPost]
  616. [ValidateAntiForgeryToken]
  617. public async Task<IActionResult> Delete()
  618. {
  619. if (ModelState.IsValid)
  620. {
  621. try
  622. {
  623. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  624. if (user != null)
  625. {
  626. await UserHelper.DeleteAccount(_dbContext, _config, user);
  627. // Sign Out
  628. await HttpContext.SignOutAsync("Cookies");
  629. await HttpContext.SignOutAsync("oidc");
  630. return Json(new { result = true });
  631. }
  632. }
  633. catch (Exception ex)
  634. {
  635. return Json(new { error = ex.GetFullMessage(true) });
  636. }
  637. }
  638. return Json(new { error = "Unable to delete user" });
  639. }
  640. [HttpGet]
  641. public async Task<IActionResult> VerifyRecoveryEmail(string username, string code)
  642. {
  643. bool verified = true;
  644. if (string.IsNullOrEmpty(code))
  645. verified &= false;
  646. // Is there a code?
  647. if (verified)
  648. {
  649. var result = await IdentityHelper.VerifyRecoveryEmail(_config, username, WebUtility.UrlDecode(code));
  650. verified &= result.Success;
  651. }
  652. RecoveryEmailVerificationViewModel model = new RecoveryEmailVerificationViewModel();
  653. model.Success = verified;
  654. return View("/Areas/User/Views/User/ViewRecoveryEmailVerification.cshtml", model);
  655. }
  656. [HttpPost]
  657. [ValidateAntiForgeryToken]
  658. public async Task<IActionResult> ResendVerifyRecoveryEmail()
  659. {
  660. if (ModelState.IsValid)
  661. {
  662. try
  663. {
  664. IdentityUserInfo userInfo = await IdentityHelper.GetIdentityUserInfo(_config, User.Identity.Name);
  665. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  666. if (user != null)
  667. {
  668. //If they have a recovery email, let's send a verification
  669. if (!string.IsNullOrEmpty(userInfo.RecoveryEmail))
  670. {
  671. if (!userInfo.RecoveryVerified.HasValue || !userInfo.RecoveryVerified.Value)
  672. {
  673. var token = await IdentityHelper.UpdateRecoveryEmail(_config, user.Username, userInfo.RecoveryEmail);
  674. string resetUrl = Url.SubRouteUrl("account", "User.ResetPassword", new { Username = user.Username });
  675. string verifyUrl = Url.SubRouteUrl("account", "User.VerifyRecoveryEmail", new { Username = user.Username, Code = WebUtility.UrlEncode(token) });
  676. UserHelper.SendRecoveryEmailVerification(_config, user.Username, userInfo.RecoveryEmail, resetUrl, verifyUrl);
  677. return Json(new { result = true });
  678. }
  679. return Json(new { error = "The recovery email is already verified" });
  680. }
  681. }
  682. }
  683. catch (Exception ex)
  684. {
  685. return Json(new { error = ex.GetFullMessage(true) });
  686. }
  687. }
  688. return Json(new { error = "Unable to resend verification" });
  689. }
  690. [HttpGet]
  691. [AllowAnonymous]
  692. public IActionResult ResetPassword(string username)
  693. {
  694. ResetPasswordViewModel model = new ResetPasswordViewModel();
  695. model.Username = username;
  696. return View("/Areas/User/Views/User/ResetPassword.cshtml", model);
  697. }
  698. [HttpPost]
  699. [AllowAnonymous]
  700. [ValidateAntiForgeryToken]
  701. public async Task<IActionResult> SendResetPasswordVerification(string username)
  702. {
  703. if (ModelState.IsValid)
  704. {
  705. try
  706. {
  707. User user = UserHelper.GetUser(_dbContext, username);
  708. if (user != null)
  709. {
  710. IdentityUserInfo userClaims = await IdentityHelper.GetIdentityUserInfo(_config, User.Identity.Name);
  711. // If they have a recovery email, let's send a verification
  712. if (!string.IsNullOrEmpty(userClaims.RecoveryEmail) && userClaims.RecoveryVerified.HasValue && userClaims.RecoveryVerified.Value)
  713. {
  714. string verifyCode = await IdentityHelper.GeneratePasswordResetToken(_config, User.Identity.Name);
  715. string resetUrl = Url.SubRouteUrl("account", "User.VerifyResetPassword", new { Username = user.Username, Code = WebUtility.UrlEncode(verifyCode) });
  716. UserHelper.SendResetPasswordVerification(_config, user.Username, userClaims.RecoveryEmail, resetUrl);
  717. return Json(new { result = true });
  718. }
  719. return Json(new { error = "The user doesn't have a recovery email specified, or has not been verified." });
  720. }
  721. return Json(new { error = "The username is not valid" });
  722. }
  723. catch (Exception ex)
  724. {
  725. return Json(new { error = ex.GetFullMessage(true) });
  726. }
  727. }
  728. return Json(new { error = "Unable to send reset link" });
  729. }
  730. [HttpGet]
  731. [AllowAnonymous]
  732. public async Task<IActionResult> VerifyResetPassword(string username, string code)
  733. {
  734. bool verified = true;
  735. if (string.IsNullOrEmpty(code))
  736. verified &= false;
  737. // Is there a code?
  738. if (verified)
  739. {
  740. // The password reset code is valid, let's get their user account for this session
  741. User user = UserHelper.GetUser(_dbContext, username);
  742. _session.SetString(_AuthSessionKey, user.Username);
  743. _session.SetString("AuthCode", WebUtility.UrlDecode(code));
  744. await _session.CommitAsync();
  745. }
  746. ResetPasswordVerificationViewModel model = new ResetPasswordVerificationViewModel();
  747. model.Success = verified;
  748. return View("/Areas/User/Views/User/ResetPasswordVerification.cshtml", model);
  749. }
  750. [HttpPost]
  751. [AllowAnonymous]
  752. [ValidateAntiForgeryToken]
  753. public async Task<IActionResult> SetUserPassword(SetPasswordViewModel passwordViewModel)
  754. {
  755. if (ModelState.IsValid)
  756. {
  757. try
  758. {
  759. await _session.LoadAsync();
  760. string code = _session.GetString("AuthCode");
  761. if (!string.IsNullOrEmpty(code))
  762. {
  763. string username = _session.GetString(_AuthSessionKey);
  764. if (!string.IsNullOrEmpty(username))
  765. {
  766. if (string.IsNullOrEmpty(passwordViewModel.Password))
  767. {
  768. return Json(new { error = "Password must not be empty" });
  769. }
  770. if (passwordViewModel.Password != passwordViewModel.PasswordConfirm)
  771. {
  772. return Json(new { error = "Passwords must match" });
  773. }
  774. try
  775. {
  776. await UserHelper.ResetAccountPassword(_dbContext, _config, username, code, passwordViewModel.Password);
  777. _session.Remove(_AuthSessionKey);
  778. _session.Remove("AuthCode");
  779. return Json(new { result = true });
  780. }
  781. catch (Exception ex)
  782. {
  783. return Json(new { error = ex.Message });
  784. }
  785. }
  786. return Json(new { error = "User does not exist" });
  787. }
  788. return Json(new { error = "Invalid Code" });
  789. }
  790. catch (Exception ex)
  791. {
  792. return Json(new { error = ex.GetFullMessage(true) });
  793. }
  794. }
  795. return Json(new { error = "Unable to reset user password" });
  796. }
  797. [HttpPost]
  798. [ValidateAntiForgeryToken]
  799. public async Task<IActionResult> Generate2FA()
  800. {
  801. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  802. if (user != null)
  803. {
  804. // Get User Identity Info
  805. var userInfo = await IdentityHelper.GetIdentityUserInfo(_config, User.Identity.Name);
  806. if (userInfo.TwoFactorEnabled.HasValue && !userInfo.TwoFactorEnabled.Value)
  807. {
  808. // Validate the code with the identity server
  809. var key = await IdentityHelper.Reset2FAKey(_config, user.Username);
  810. if (!string.IsNullOrEmpty(key))
  811. {
  812. return Json(new { result = true, key = key, qrUrl = Url.SubRouteUrl("account", "User.Action", new { action = "GenerateAuthQrCode", key = key }) });
  813. }
  814. return Json(new { error = "Unable to generate Two Factor Authentication key" });
  815. }
  816. return Json(new { error = "User already has Two Factor Authentication enabled" });
  817. }
  818. return Json(new { error = "User does not exist" });
  819. }
  820. [HttpPost]
  821. [ValidateAntiForgeryToken]
  822. public async Task<IActionResult> VerifyAuthenticatorCode(string code)
  823. {
  824. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  825. if (user != null)
  826. {
  827. // Get User Identity Info
  828. var userInfo = await IdentityHelper.GetIdentityUserInfo(_config, User.Identity.Name);
  829. if (userInfo.TwoFactorEnabled.HasValue && !userInfo.TwoFactorEnabled.Value)
  830. {
  831. // Validate the code with the identity server
  832. var result = await IdentityHelper.Enable2FA(_config, user.Username, code);
  833. if (result.Any())
  834. {
  835. return Json(new { result = true, recoveryCodes = result });
  836. }
  837. return Json(new { error = "Invalid Authentication Code" });
  838. }
  839. return Json(new { error = "User already has Two Factor Authentication enabled" });
  840. }
  841. return Json(new { error = "User does not exist" });
  842. }
  843. [HttpPost]
  844. [ValidateAntiForgeryToken]
  845. public async Task<IActionResult> ResetRecoveryCodes()
  846. {
  847. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  848. if (user != null)
  849. {
  850. // Get User Identity Info
  851. var userInfo = await IdentityHelper.GetIdentityUserInfo(_config, User.Identity.Name);
  852. if (userInfo.TwoFactorEnabled.HasValue && userInfo.TwoFactorEnabled.Value)
  853. {
  854. // Regenerate the recovery codes
  855. var result = await IdentityHelper.GenerateRecoveryCodes(_config, user.Username);
  856. if (result.Any())
  857. {
  858. return Json(new { result = true, recoveryCodes = result });
  859. }
  860. return Json(new { error = "Invalid Authentication Code" });
  861. }
  862. return Json(new { error = "User doesn't have Two Factor Authentication enabled" });
  863. }
  864. return Json(new { error = "User does not exist" });
  865. }
  866. [HttpPost]
  867. [ValidateAntiForgeryToken]
  868. public async Task<IActionResult> Disable2FA()
  869. {
  870. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  871. if (user != null)
  872. {
  873. // Get User Identity Info
  874. var userInfo = await IdentityHelper.GetIdentityUserInfo(_config, User.Identity.Name);
  875. if (userInfo.TwoFactorEnabled.HasValue && userInfo.TwoFactorEnabled.Value)
  876. {
  877. // Validate the code with the identity server
  878. var result = await IdentityHelper.Disable2FA(_config, user.Username);
  879. if (result.Success)
  880. {
  881. return Json(new { result = true });
  882. }
  883. return Json(new { error = result.Message });
  884. }
  885. return Json(new { error = "User doesn't have Two Factor Authentication enabled" });
  886. }
  887. return Json(new { error = "User does not exist" });
  888. }
  889. [HttpGet]
  890. public IActionResult GenerateAuthQrCode(string key)
  891. {
  892. var ProvisionUrl = string.Format("otpauth://totp/{0}:{1}?secret={2}", _config.Title, User.Identity.Name, key);
  893. QRCodeGenerator qrGenerator = new QRCodeGenerator();
  894. QRCodeData qrCodeData = qrGenerator.CreateQrCode(ProvisionUrl, QRCodeGenerator.ECCLevel.Q);
  895. PngByteQRCode qrCode = new PngByteQRCode(qrCodeData);
  896. return File(qrCode.GetGraphic(20), "image/png");
  897. }
  898. [HttpPost]
  899. [ValidateAntiForgeryToken]
  900. public IActionResult ClearTrustedDevices()
  901. {
  902. try
  903. {
  904. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  905. if (user != null)
  906. {
  907. //if (user.SecuritySettings.AllowTrustedDevices)
  908. //{
  909. // // let's clear the trusted devices
  910. // user.TrustedDevices.Clear();
  911. // List<TrustedDevice> foundDevices = _dbContext.TrustedDevices.Where(d => d.UserId == user.UserId).ToList();
  912. // if (foundDevices != null)
  913. // {
  914. // foreach (TrustedDevice device in foundDevices)
  915. // {
  916. // _dbContext.TrustedDevices.Remove(device);
  917. // }
  918. // }
  919. // _dbContext.Entry(user).State = EntityState.Modified;
  920. // _dbContext.SaveChanges();
  921. // return Json(new { result = true });
  922. //}
  923. return Json(new { error = "User does not allow trusted devices" });
  924. }
  925. return Json(new { error = "User does not exist" });
  926. }
  927. catch (Exception ex)
  928. {
  929. return Json(new { error = ex.GetFullMessage(true) });
  930. }
  931. }
  932. [HttpPost]
  933. [ValidateAntiForgeryToken]
  934. public async Task<IActionResult> GenerateToken(string name, [FromServices] ICompositeViewEngine viewEngine)
  935. {
  936. try
  937. {
  938. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  939. if (user != null)
  940. {
  941. //string newTokenStr = UserHelper.GenerateAuthToken(_dbContext, user.Username);
  942. //if (!string.IsNullOrEmpty(newTokenStr))
  943. //{
  944. // AuthToken token = new AuthToken();
  945. // token.UserId = user.UserId;
  946. // token.HashedToken = SHA256.Hash(newTokenStr);
  947. // token.Name = name;
  948. // _dbContext.AuthTokens.Add(token);
  949. // _dbContext.SaveChanges();
  950. // AuthTokenViewModel model = new AuthTokenViewModel();
  951. // model.AuthTokenId = token.AuthTokenId;
  952. // model.Name = token.Name;
  953. // model.LastDateUsed = token.LastDateUsed;
  954. // string renderedView = await RenderPartialViewToString(viewEngine, "~/Areas/User/Views/User/Settings/AuthToken.cshtml", model);
  955. // return Json(new { result = new { token = newTokenStr, html = renderedView } });
  956. //}
  957. return Json(new { error = "Unable to generate Auth Token" });
  958. }
  959. return Json(new { error = "User does not exist" });
  960. }
  961. catch (Exception ex)
  962. {
  963. return Json(new { error = ex.GetFullMessage(true) });
  964. }
  965. }
  966. [HttpPost]
  967. [ValidateAntiForgeryToken]
  968. public IActionResult RevokeAllTokens()
  969. {
  970. try
  971. {
  972. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  973. if (user != null)
  974. {
  975. //user.AuthTokens.Clear();
  976. //List<AuthToken> foundTokens = _dbContext.AuthTokens.Where(d => d.UserId == user.UserId).ToList();
  977. //if (foundTokens != null)
  978. //{
  979. // foreach (AuthToken token in foundTokens)
  980. // {
  981. // _dbContext.AuthTokens.Remove(token);
  982. // }
  983. //}
  984. _dbContext.Entry(user).State = EntityState.Modified;
  985. _dbContext.SaveChanges();
  986. return Json(new { result = true });
  987. }
  988. return Json(new { error = "User does not exist" });
  989. }
  990. catch (Exception ex)
  991. {
  992. return Json(new { error = ex.GetFullMessage(true) });
  993. }
  994. }
  995. [HttpPost]
  996. [ValidateAntiForgeryToken]
  997. public IActionResult EditTokenName(int tokenId, string name)
  998. {
  999. try
  1000. {
  1001. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  1002. if (user != null)
  1003. {
  1004. //AuthToken foundToken = _dbContext.AuthTokens.Where(d => d.UserId == user.UserId && d.AuthTokenId == tokenId).FirstOrDefault();
  1005. //if (foundToken != null)
  1006. //{
  1007. // foundToken.Name = name;
  1008. // _dbContext.Entry(foundToken).State = EntityState.Modified;
  1009. // _dbContext.SaveChanges();
  1010. // return Json(new { result = new { name = name } });
  1011. //}
  1012. return Json(new { error = "Authentication Token does not exist" });
  1013. }
  1014. return Json(new { error = "User does not exist" });
  1015. }
  1016. catch (Exception ex)
  1017. {
  1018. return Json(new { error = ex.GetFullMessage(true) });
  1019. }
  1020. }
  1021. [HttpPost]
  1022. [ValidateAntiForgeryToken]
  1023. public IActionResult DeleteToken(int tokenId)
  1024. {
  1025. try
  1026. {
  1027. User user = UserHelper.GetUser(_dbContext, User.Identity.Name);
  1028. if (user != null)
  1029. {
  1030. //AuthToken foundToken = _dbContext.AuthTokens.Where(d => d.UserId == user.UserId && d.AuthTokenId == tokenId).FirstOrDefault();
  1031. //if (foundToken != null)
  1032. //{
  1033. // _dbContext.AuthTokens.Remove(foundToken);
  1034. // user.AuthTokens.Remove(foundToken);
  1035. // _dbContext.Entry(user).State = EntityState.Modified;
  1036. // _dbContext.SaveChanges();
  1037. // return Json(new { result = true });
  1038. //}
  1039. return Json(new { error = "Authentication Token does not exist" });
  1040. }
  1041. return Json(new { error = "User does not exist" });
  1042. }
  1043. catch (Exception ex)
  1044. {
  1045. return Json(new { error = ex.GetFullMessage(true) });
  1046. }
  1047. }
  1048. [HttpPost]
  1049. [ValidateAntiForgeryToken]
  1050. public async Task<IActionResult> CreateClient(string name, string homepageUrl, string logoUrl, string callbackUrl, [FromServices] ICompositeViewEngine viewEngine)
  1051. {
  1052. try
  1053. {
  1054. if (string.IsNullOrEmpty(name))
  1055. return Json(new { error = "You must enter a client name" });
  1056. if (string.IsNullOrEmpty(callbackUrl))
  1057. return Json(new { error = "You must enter an authorization callback URL" });
  1058. if (!callbackUrl.IsValidUrl())
  1059. return Json(new { error = "Invalid callback URL" });
  1060. if (!string.IsNullOrEmpty(homepageUrl) && !homepageUrl.IsValidUrl())
  1061. return Json(new { error = "Invalid homepage URL" });
  1062. if (!string.IsNullOrEmpty(logoUrl) && !logoUrl.IsValidUrl())
  1063. return Json(new { error = "Invalid logo URL" });
  1064. // Validate the code with the identity server
  1065. var result = await IdentityHelper.CreateClient(_config, User.Identity.Name, name, homepageUrl, logoUrl, callbackUrl, "openid", "role", "account-info", "security-info", "teknik-api.read", "teknik-api.write");
  1066. if (result.Success)
  1067. {
  1068. var client = (JObject)result.Data;
  1069. ClientViewModel model = new ClientViewModel();
  1070. model.Id = client["id"].ToString();
  1071. model.Name = name;
  1072. model.HomepageUrl = homepageUrl;
  1073. model.LogoUrl = logoUrl;
  1074. model.CallbackUrl = callbackUrl;
  1075. string renderedView = await RenderPartialViewToString(viewEngine, "~/Areas/User/Views/User/Settings/ClientView.cshtml", model);
  1076. return Json(new { result = true, clientId = client["id"], secret = client["secret"], html = renderedView });
  1077. }
  1078. return Json(new { error = result.Message });
  1079. }
  1080. catch (Exception ex)
  1081. {
  1082. return Json(new { error = ex.GetFullMessage(true) });
  1083. }
  1084. }
  1085. [HttpPost]
  1086. [ValidateAntiForgeryToken]
  1087. public async Task<IActionResult> GetClient(string clientId)
  1088. {
  1089. Client foundClient = await IdentityHelper.GetClient(_config, User.Identity.Name, clientId);
  1090. if (foundClient != null)
  1091. {
  1092. ClientViewModel model = new ClientViewModel()
  1093. {
  1094. Id = foundClient.ClientId,
  1095. Name = foundClient.ClientName,
  1096. HomepageUrl = foundClient.ClientUri,
  1097. LogoUrl = foundClient.LogoUri,
  1098. CallbackUrl = string.Join(',', foundClient.RedirectUris),
  1099. AllowedScopes = foundClient.AllowedScopes
  1100. };
  1101. return Json(new { result = true, client = model });
  1102. }
  1103. return new StatusCodeResult(StatusCodes.Status403Forbidden);
  1104. }
  1105. [HttpPost]
  1106. [ValidateAntiForgeryToken]
  1107. public async Task<IActionResult> EditClient(string clientId, string name, string homepageUrl, string logoUrl, string callbackUrl, [FromServices] ICompositeViewEngine viewEngine)
  1108. {
  1109. try
  1110. {
  1111. if (string.IsNullOrEmpty(name))
  1112. return Json(new { error = "You must enter a client name" });
  1113. if (string.IsNullOrEmpty(callbackUrl))
  1114. return Json(new { error = "You must enter an authorization callback URL" });
  1115. if (!callbackUrl.IsValidUrl())
  1116. return Json(new { error = "Invalid callback URL" });
  1117. if (!string.IsNullOrEmpty(homepageUrl) && !homepageUrl.IsValidUrl())
  1118. return Json(new { error = "Invalid homepage URL" });
  1119. if (!string.IsNullOrEmpty(logoUrl) && !logoUrl.IsValidUrl())
  1120. return Json(new { error = "Invalid logo URL" });
  1121. Client foundClient = await IdentityHelper.GetClient(_config, User.Identity.Name, clientId);
  1122. if (foundClient == null)
  1123. return Json(new { error = "Client does not exist" });
  1124. // Validate the code with the identity server
  1125. var result = await IdentityHelper.EditClient(_config, User.Identity.Name, clientId, name, homepageUrl, logoUrl, callbackUrl);
  1126. if (result.Success)
  1127. {
  1128. var client = (JObject)result.Data;
  1129. ClientViewModel model = new ClientViewModel();
  1130. model.Id = clientId;
  1131. model.Name = name;
  1132. model.HomepageUrl = homepageUrl;
  1133. model.LogoUrl = logoUrl;
  1134. model.CallbackUrl = callbackUrl;
  1135. string renderedView = await RenderPartialViewToString(viewEngine, "~/Areas/User/Views/User/Settings/ClientView.cshtml", model);
  1136. return Json(new { result = true, clientId = clientId, html = renderedView });
  1137. }
  1138. return Json(new { error = result.Message });
  1139. }
  1140. catch (Exception ex)
  1141. {
  1142. return Json(new { error = ex.GetFullMessage(true) });
  1143. }
  1144. }
  1145. [HttpPost]
  1146. [ValidateAntiForgeryToken]
  1147. public async Task<IActionResult> DeleteClient(string clientId)
  1148. {
  1149. try
  1150. {
  1151. // Validate the code with the identity server
  1152. var result = await IdentityHelper.DeleteClient(_config, clientId);
  1153. if (result.Success)
  1154. {
  1155. return Json(new { result = true });
  1156. }
  1157. return Json(new { error = result.Message });
  1158. }
  1159. catch (Exception ex)
  1160. {
  1161. return Json(new { error = ex.GetFullMessage(true) });
  1162. }
  1163. }
  1164. [HttpPost]
  1165. [ValidateAntiForgeryToken]
  1166. public IActionResult CreateInviteCodeLink(int inviteCodeId)
  1167. {
  1168. try
  1169. {
  1170. InviteCode code = _dbContext.InviteCodes.Where(c => c.InviteCodeId == inviteCodeId).FirstOrDefault();
  1171. if (code != null)
  1172. {
  1173. if (User.Identity.IsAuthenticated)
  1174. {
  1175. if (code.Owner.Username == User.Identity.Name)
  1176. {
  1177. return Json(new { result = Url.SubRouteUrl("account", "User.Register", new { inviteCode = code.Code }) });
  1178. }
  1179. }
  1180. return Json(new { error = "Invite Code not associated with this user" });
  1181. }
  1182. return Json(new { error = "Invalid Invite Code" });
  1183. }
  1184. catch (Exception ex)
  1185. {
  1186. return Json(new { error = ex.GetFullMessage(true) });
  1187. }
  1188. }
  1189. }
  1190. }