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

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