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.

UserHelper.cs 55KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.Entity;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Net;
  7. using System.Net.Mail;
  8. using System.Runtime.InteropServices;
  9. using System.Security.Cryptography;
  10. using System.Text;
  11. using System.Text.RegularExpressions;
  12. using System.Threading.Tasks;
  13. using System.Web;
  14. using System.Web.Security;
  15. using Teknik.Areas.Blog.Models;
  16. using Teknik.Areas.Shortener.Models;
  17. using Teknik.Areas.Users.Models;
  18. using Teknik.Configuration;
  19. using Teknik.Utilities;
  20. using Teknik.Models;
  21. using Teknik.Utilities.Cryptography;
  22. using MD5 = Teknik.Utilities.Cryptography.MD5;
  23. using SHA256 = Teknik.Utilities.Cryptography.SHA256;
  24. using SHA384 = Teknik.Utilities.Cryptography.SHA384;
  25. namespace Teknik.Areas.Users.Utility
  26. {
  27. public static class UserHelper
  28. {
  29. #region Account Management
  30. public static List<string> GetReservedUsernames(Config config)
  31. {
  32. List<string> foundNames = new List<string>();
  33. if (config != null)
  34. {
  35. string path = config.UserConfig.ReservedUsernameDefinitionFile;
  36. if (File.Exists(path))
  37. {
  38. string[] names = File.ReadAllLines(path);
  39. foundNames = names.ToList();
  40. }
  41. }
  42. return foundNames;
  43. }
  44. public static bool UsernameReserved(Config config, string username)
  45. {
  46. // Load reserved usernames
  47. List<string> reserved = GetReservedUsernames(config);
  48. return (reserved.Exists(u => u.ToLower() == username.ToLower()));
  49. }
  50. public static bool ValidUsername(Config config, string username)
  51. {
  52. bool isValid = true;
  53. // Must be something there
  54. isValid &= !string.IsNullOrEmpty(username);
  55. // Is the format correct?
  56. Regex reg = new Regex(config.UserConfig.UsernameFilter);
  57. isValid &= reg.IsMatch(username);
  58. // Meets the min length?
  59. isValid &= (username.Length >= config.UserConfig.MinUsernameLength);
  60. // Meets the max length?
  61. isValid &= (username.Length <= config.UserConfig.MaxUsernameLength);
  62. return isValid;
  63. }
  64. public static bool UsernameAvailable(TeknikEntities db, Config config, string username)
  65. {
  66. bool isAvailable = true;
  67. isAvailable &= ValidUsername(config, username);
  68. isAvailable &= !UsernameReserved(config, username);
  69. isAvailable &= !UserExists(db, username);
  70. isAvailable &= !UserEmailExists(config, GetUserEmailAddress(config, username));
  71. isAvailable &= !UserGitExists(config, username);
  72. return isAvailable;
  73. }
  74. public static DateTime GetLastAccountActivity(TeknikEntities db, Config config, User user)
  75. {
  76. try
  77. {
  78. DateTime lastActive = new DateTime(1900, 1, 1);
  79. DateTime emailLastActive = UserEmailLastActive(config, GetUserEmailAddress(config, user.Username));
  80. if (lastActive < emailLastActive)
  81. lastActive = emailLastActive;
  82. DateTime gitLastActive = UserGitLastActive(config, user.Username);
  83. if (lastActive < gitLastActive)
  84. lastActive = gitLastActive;
  85. DateTime userLastActive = UserLastActive(db, config, user);
  86. if (lastActive < userLastActive)
  87. lastActive = userLastActive;
  88. return lastActive;
  89. }
  90. catch (Exception ex)
  91. {
  92. throw new Exception("Unable to determine last account activity.", ex);
  93. }
  94. }
  95. public static string GeneratePassword(Config config, User user, string password)
  96. {
  97. try
  98. {
  99. string username = user.Username.ToLower();
  100. if (user.Transfers.ToList().Exists(t => t.Type == TransferTypes.CaseSensitivePassword))
  101. {
  102. username = user.Username;
  103. }
  104. byte[] hashBytes = SHA384.Hash(username, password);
  105. string hash = hashBytes.ToHex();
  106. if (user.Transfers.ToList().Exists(t => t.Type == TransferTypes.ASCIIPassword))
  107. {
  108. hash = Encoding.ASCII.GetString(hashBytes);
  109. }
  110. if (user.Transfers.ToList().Exists(t => t.Type == TransferTypes.Sha256Password))
  111. {
  112. hash = SHA256.Hash(password, config.Salt1, config.Salt2);
  113. }
  114. return hash;
  115. }
  116. catch (Exception ex)
  117. {
  118. throw new Exception("Unable to generate password.", ex);
  119. }
  120. }
  121. public static string GenerateAuthToken(TeknikEntities db, string username)
  122. {
  123. try
  124. {
  125. bool validToken = false;
  126. string token = string.Empty;
  127. while (!validToken)
  128. {
  129. username = username.ToLower();
  130. byte[] hashBytes = SHA384.Hash(username, StringHelper.RandomString(24));
  131. token = hashBytes.ToHex();
  132. // Make sure it isn't a duplicate
  133. string hashedToken = SHA256.Hash(token);
  134. if (!db.AuthTokens.Where(t => t.HashedToken == hashedToken).Any())
  135. {
  136. validToken = true;
  137. }
  138. }
  139. return token;
  140. }
  141. catch (Exception ex)
  142. {
  143. throw new Exception("Unable to generate user auth token.", ex);
  144. }
  145. }
  146. public static void AddAccount(TeknikEntities db, Config config, User user, string password)
  147. {
  148. try
  149. {
  150. // Create an Email Account
  151. AddUserEmail(config, GetUserEmailAddress(config, user.Username), password);
  152. // Create a Git Account
  153. AddUserGit(config, user.Username, password);
  154. // Add User
  155. AddUser(db, config, user, password);
  156. }
  157. catch (Exception ex)
  158. {
  159. throw new Exception("Unable to create account.", ex);
  160. }
  161. }
  162. public static void EditAccount(TeknikEntities db, Config config, User user, bool changePass, string password)
  163. {
  164. try
  165. {
  166. // Changing Password?
  167. if (changePass)
  168. {
  169. // Make sure they have a git and email account before resetting their password
  170. string email = GetUserEmailAddress(config, user.Username);
  171. if (config.EmailConfig.Enabled && !UserEmailExists(config, email))
  172. {
  173. AddUserEmail(config, email, password);
  174. }
  175. if (config.GitConfig.Enabled && !UserGitExists(config, user.Username))
  176. {
  177. AddUserGit(config, user.Username, password);
  178. }
  179. // Change email password
  180. EditUserEmailPassword(config, GetUserEmailAddress(config, user.Username), password);
  181. // Update Git password
  182. EditUserGitPassword(config, user.Username, password);
  183. }
  184. // Update User
  185. EditUser(db, config, user, changePass, password);
  186. }
  187. catch (Exception ex)
  188. {
  189. throw new Exception("Unable to edit account.", ex);
  190. }
  191. }
  192. public static void EditAccountType(TeknikEntities db, Config config, string username, AccountType type)
  193. {
  194. try
  195. {
  196. if (!UserExists(db, username))
  197. throw new Exception($"The user provided does not exist: {username}");
  198. // Get the user to edit
  199. User user = GetUser(db, username);
  200. string email = GetUserEmailAddress(config, username);
  201. // Edit the user type
  202. user.AccountType = type;
  203. EditUser(db, config, user);
  204. // Add/Remove account type features depending on the type
  205. switch (type)
  206. {
  207. case AccountType.Basic:
  208. // Set the email size to 1GB
  209. EditUserEmailMaxSize(config, email, config.EmailConfig.MaxSize);
  210. // Set the email max/day to 100
  211. EditUserEmailMaxEmailsPerDay(config, email, 100);
  212. break;
  213. case AccountType.Premium:
  214. // Set the email size to 5GB
  215. EditUserEmailMaxSize(config, email, 5000);
  216. // Set the email max/day to infinite (-1)
  217. EditUserEmailMaxEmailsPerDay(config, email, -1);
  218. break;
  219. }
  220. }
  221. catch (Exception ex)
  222. {
  223. throw new Exception($"Unable to edit the account type [{type}] for: {username}", ex);
  224. }
  225. }
  226. public static void EditAccountStatus(TeknikEntities db, Config config, string username, AccountStatus status)
  227. {
  228. try
  229. {
  230. if (!UserExists(db, username))
  231. throw new Exception($"The user provided does not exist: {username}");
  232. // Get the user to edit
  233. User user = GetUser(db, username);
  234. string email = GetUserEmailAddress(config, username);
  235. // Edit the user type
  236. user.AccountStatus = status;
  237. EditUser(db, config, user);
  238. // Add/Remove account type features depending on the type
  239. switch (status)
  240. {
  241. case AccountStatus.Active:
  242. // Enable Email
  243. EnableUserEmail(config, email);
  244. // Enable Git
  245. EnableUserGit(config, username);
  246. break;
  247. case AccountStatus.Banned:
  248. // Disable Email
  249. DisableUserEmail(config, email);
  250. // Disable Git
  251. DisableUserGit(config, username);
  252. break;
  253. }
  254. }
  255. catch (Exception ex)
  256. {
  257. throw new Exception($"Unable to edit the account status [{status}] for: {username}", ex);
  258. }
  259. }
  260. public static void DeleteAccount(TeknikEntities db, Config config, User user)
  261. {
  262. try
  263. {
  264. // Delete Email Account
  265. if (UserEmailExists(config, GetUserEmailAddress(config, user.Username)))
  266. DeleteUserEmail(config, GetUserEmailAddress(config, user.Username));
  267. // Delete Git Account
  268. if (UserGitExists(config, user.Username))
  269. DeleteUserGit(config, user.Username);
  270. // Delete User Account
  271. DeleteUser(db, config, user);
  272. }
  273. catch (Exception ex)
  274. {
  275. throw new Exception("Unable to delete account.", ex);
  276. }
  277. }
  278. #endregion
  279. #region User Management
  280. public static User GetUser(TeknikEntities db, string username)
  281. {
  282. User user = db.Users.Where(b => b.Username == username).FirstOrDefault();
  283. if (user != null)
  284. {
  285. user.UserSettings = db.UserSettings.Find(user.UserId);
  286. user.SecuritySettings = db.SecuritySettings.Find(user.UserId);
  287. user.BlogSettings = db.BlogSettings.Find(user.UserId);
  288. user.UploadSettings = db.UploadSettings.Find(user.UserId);
  289. }
  290. return user;
  291. }
  292. public static User GetUserFromToken(TeknikEntities db, string username, string token)
  293. {
  294. if (token != null && !string.IsNullOrEmpty(username))
  295. {
  296. string hashedToken = SHA256.Hash(token);
  297. return db.Users.FirstOrDefault(u => u.AuthTokens.Select(a => a.HashedToken).Contains(hashedToken) && u.Username == username);
  298. }
  299. return null;
  300. }
  301. public static bool UserExists(TeknikEntities db, string username)
  302. {
  303. User user = GetUser(db, username);
  304. if (user != null)
  305. {
  306. return true;
  307. }
  308. return false;
  309. }
  310. public static DateTime UserLastActive(TeknikEntities db, Config config, User user)
  311. {
  312. try
  313. {
  314. DateTime lastActive = new DateTime(1900, 1, 1);
  315. if (lastActive < user.LastSeen)
  316. lastActive = user.LastSeen;
  317. return lastActive;
  318. }
  319. catch (Exception ex)
  320. {
  321. throw new Exception("Unable to determine last user activity.", ex);
  322. }
  323. }
  324. public static void UpdateTokenLastUsed(TeknikEntities db, string username, string token, DateTime lastUsed)
  325. {
  326. User foundUser = GetUser(db, username);
  327. if (foundUser != null)
  328. {
  329. // Update the user's last seen date
  330. if (foundUser.LastSeen < lastUsed)
  331. {
  332. foundUser.LastSeen = lastUsed;
  333. db.Entry(foundUser).State = EntityState.Modified;
  334. }
  335. string hashedToken = SHA256.Hash(token);
  336. List<AuthToken> tokens = foundUser.AuthTokens.Where(t => t.HashedToken == hashedToken).ToList();
  337. if (tokens != null)
  338. {
  339. foreach (AuthToken foundToken in tokens)
  340. {
  341. foundToken.LastDateUsed = lastUsed;
  342. db.Entry(foundToken).State = EntityState.Modified;
  343. }
  344. }
  345. db.SaveChanges();
  346. }
  347. }
  348. public static bool UserPasswordCorrect(TeknikEntities db, Config config, User user, string password)
  349. {
  350. try
  351. {
  352. string hash = GeneratePassword(config, user, password);
  353. return db.Users.Any(b => b.Username == user.Username && b.HashedPassword == hash);
  354. }
  355. catch (Exception ex)
  356. {
  357. throw new Exception("Unable to determine if password is correct.", ex);
  358. }
  359. }
  360. public static bool UserTokenCorrect(TeknikEntities db, string username, string token)
  361. {
  362. User foundUser = GetUserFromToken(db, username, token);
  363. if (foundUser != null)
  364. {
  365. return true;
  366. }
  367. return false;
  368. }
  369. public static bool UserHasRoles(User user, params string[] roles)
  370. {
  371. bool hasRole = true;
  372. if (user != null)
  373. {
  374. // Check if they have the role specified
  375. if (roles.Any())
  376. {
  377. foreach (string role in roles)
  378. {
  379. if (!string.IsNullOrEmpty(role))
  380. {
  381. if (user.Groups.Where(g => g.Roles.Where(r => role == r.Name).Any()).Any())
  382. {
  383. // They have the role!
  384. return true;
  385. }
  386. else
  387. {
  388. // They don't have this role, so let's reset the hasRole
  389. hasRole = false;
  390. }
  391. }
  392. else
  393. {
  394. // Only set this if we haven't failed once already
  395. hasRole &= true;
  396. }
  397. }
  398. }
  399. else
  400. {
  401. // No roles to check, so they pass!
  402. return true;
  403. }
  404. }
  405. else
  406. {
  407. hasRole = false;
  408. }
  409. return hasRole;
  410. }
  411. public static void TransferUser(TeknikEntities db, Config config, User user, string password)
  412. {
  413. try
  414. {
  415. List<TransferType> transfers = user.Transfers.ToList();
  416. for (int i = 0; i < transfers.Count; i++)
  417. {
  418. TransferType transfer = transfers[i];
  419. switch (transfer.Type)
  420. {
  421. case TransferTypes.Sha256Password:
  422. case TransferTypes.CaseSensitivePassword:
  423. case TransferTypes.ASCIIPassword:
  424. user.HashedPassword = SHA384.Hash(user.Username.ToLower(), password).ToHex();
  425. break;
  426. default:
  427. break;
  428. }
  429. user.Transfers.Remove(transfer);
  430. }
  431. db.Entry(user).State = EntityState.Modified;
  432. db.SaveChanges();
  433. }
  434. catch (Exception ex)
  435. {
  436. throw new Exception("Unable to transfer user info.", ex);
  437. }
  438. }
  439. public static void AddUser(TeknikEntities db, Config config, User user, string password)
  440. {
  441. try
  442. {
  443. // Add User
  444. user.HashedPassword = GeneratePassword(config, user, password);
  445. db.Users.Add(user);
  446. db.SaveChanges();
  447. // Generate blog for the user
  448. var newBlog = db.Blogs.Create();
  449. newBlog.UserId = user.UserId;
  450. db.Blogs.Add(newBlog);
  451. db.SaveChanges();
  452. }
  453. catch (Exception ex)
  454. {
  455. throw new Exception("Unable to create user.", ex);
  456. }
  457. }
  458. public static void EditUser(TeknikEntities db, Config config, User user)
  459. {
  460. EditUser(db, config, user, false, string.Empty);
  461. }
  462. public static void EditUser(TeknikEntities db, Config config, User user, bool changePass, string password)
  463. {
  464. try
  465. {
  466. // Changing Password?
  467. if (changePass)
  468. {
  469. // Update User password
  470. user.HashedPassword = SHA384.Hash(user.Username.ToLower(), password).ToHex();
  471. // Remove any password transfer items for the account
  472. for (int i = 0; i < user.Transfers.Count; i++)
  473. {
  474. TransferType type = user.Transfers.ToList()[i];
  475. if (type.Type == TransferTypes.ASCIIPassword || type.Type == TransferTypes.CaseSensitivePassword || type.Type == TransferTypes.Sha256Password)
  476. {
  477. user.Transfers.Remove(type);
  478. i--;
  479. }
  480. }
  481. }
  482. db.Entry(user).State = EntityState.Modified;
  483. db.SaveChanges();
  484. }
  485. catch (Exception ex)
  486. {
  487. throw new Exception(string.Format("Unable to edit user {0}.", user.Username), ex);
  488. }
  489. }
  490. public static void DeleteUser(TeknikEntities db, Config config, User user)
  491. {
  492. try
  493. {
  494. // Update uploads
  495. List<Upload.Models.Upload> uploads = db.Uploads.Where(u => u.User.Username == user.Username).ToList();
  496. if (uploads != null)
  497. {
  498. foreach (Upload.Models.Upload upload in uploads)
  499. {
  500. upload.UserId = null;
  501. db.Entry(upload).State = EntityState.Modified;
  502. }
  503. db.SaveChanges();
  504. }
  505. // Update pastes
  506. List<Paste.Models.Paste> pastes = db.Pastes.Where(u => u.User.Username == user.Username).ToList();
  507. if (pastes != null)
  508. {
  509. foreach (Paste.Models.Paste paste in pastes)
  510. {
  511. paste.UserId = null;
  512. db.Entry(paste).State = EntityState.Modified;
  513. }
  514. db.SaveChanges();
  515. }
  516. // Update shortened urls
  517. List<ShortenedUrl> shortUrls = db.ShortenedUrls.Where(u => u.User.Username == user.Username).ToList();
  518. if (shortUrls != null)
  519. {
  520. foreach (ShortenedUrl shortUrl in shortUrls)
  521. {
  522. shortUrl.UserId = null;
  523. db.Entry(shortUrl).State = EntityState.Modified;
  524. }
  525. db.SaveChanges();
  526. }
  527. // Update vaults
  528. List<Vault.Models.Vault> vaults = db.Vaults.Where(u => u.User.Username == user.Username).ToList();
  529. if (vaults != null)
  530. {
  531. foreach (Vault.Models.Vault vault in vaults)
  532. {
  533. vault.UserId = null;
  534. db.Entry(vault).State = EntityState.Modified;
  535. }
  536. db.SaveChanges();
  537. }
  538. // Delete Blogs
  539. Blog.Models.Blog blog = db.Blogs.Where(u => u.User.Username == user.Username).FirstOrDefault();
  540. if (blog != null)
  541. {
  542. db.Blogs.Remove(blog);
  543. db.SaveChanges();
  544. }
  545. // Delete post comments
  546. List<BlogPostComment> postComments = db.BlogComments.Where(u => u.User.Username == user.Username).ToList();
  547. if (postComments != null)
  548. {
  549. foreach (BlogPostComment postComment in postComments)
  550. {
  551. db.BlogComments.Remove(postComment);
  552. }
  553. db.SaveChanges();
  554. }
  555. // Delete podcast comments
  556. List<Podcast.Models.PodcastComment> podComments = db.PodcastComments.Where(u => u.User.Username == user.Username).ToList();
  557. if (podComments != null)
  558. {
  559. foreach (Podcast.Models.PodcastComment podComment in podComments)
  560. {
  561. db.PodcastComments.Remove(podComment);
  562. }
  563. db.SaveChanges();
  564. }
  565. // Delete Recovery Email Verifications
  566. List<RecoveryEmailVerification> verCodes = db.RecoveryEmailVerifications.Where(r => r.User.Username == user.Username).ToList();
  567. if (verCodes != null)
  568. {
  569. foreach (RecoveryEmailVerification verCode in verCodes)
  570. {
  571. db.RecoveryEmailVerifications.Remove(verCode);
  572. }
  573. db.SaveChanges();
  574. }
  575. // Delete Password Reset Verifications
  576. List<ResetPasswordVerification> verPass = db.ResetPasswordVerifications.Where(r => r.User.Username == user.Username).ToList();
  577. if (verPass != null)
  578. {
  579. foreach (ResetPasswordVerification ver in verPass)
  580. {
  581. db.ResetPasswordVerifications.Remove(ver);
  582. }
  583. db.SaveChanges();
  584. }
  585. // Delete User
  586. db.Users.Remove(user);
  587. db.SaveChanges();
  588. }
  589. catch (Exception ex)
  590. {
  591. throw new Exception(string.Format("Unable to delete user {0}.", user.Username), ex);
  592. }
  593. }
  594. public static string CreateRecoveryEmailVerification(TeknikEntities db, Config config, User user)
  595. {
  596. // Check to see if there already is a verification code for the user
  597. List<RecoveryEmailVerification> verCodes = db.RecoveryEmailVerifications.Where(r => r.User.Username == user.Username).ToList();
  598. if (verCodes != null && verCodes.Any())
  599. {
  600. foreach (RecoveryEmailVerification verCode in verCodes)
  601. {
  602. db.RecoveryEmailVerifications.Remove(verCode);
  603. }
  604. }
  605. // Create a new verification code and add it
  606. string verifyCode = StringHelper.RandomString(24);
  607. RecoveryEmailVerification ver = new RecoveryEmailVerification();
  608. ver.UserId = user.UserId;
  609. ver.Code = verifyCode;
  610. ver.DateCreated = DateTime.Now;
  611. db.RecoveryEmailVerifications.Add(ver);
  612. db.SaveChanges();
  613. return verifyCode;
  614. }
  615. public static void SendRecoveryEmailVerification(Config config, string username, string email, string resetUrl, string verifyUrl)
  616. {
  617. SmtpClient client = new SmtpClient();
  618. client.Host = config.ContactConfig.EmailAccount.Host;
  619. client.Port = config.ContactConfig.EmailAccount.Port;
  620. client.EnableSsl = config.ContactConfig.EmailAccount.SSL;
  621. client.DeliveryMethod = SmtpDeliveryMethod.Network;
  622. client.UseDefaultCredentials = true;
  623. client.Credentials = new NetworkCredential(config.ContactConfig.EmailAccount.Username, config.ContactConfig.EmailAccount.Password);
  624. client.Timeout = 5000;
  625. MailMessage mail = new MailMessage(config.ContactConfig.EmailAccount.EmailAddress, email);
  626. mail.Subject = "Recovery Email Validation";
  627. mail.Body = string.Format(@"Hello {0},
  628. Welcome to Teknik!
  629. You are recieving this email because you have specified this email address as your recovery email. In the event that you forget your password, you can visit {1} and request a temporary password reset key be sent to this email. You will then be able to reset and choose a new password.
  630. In order to verify that you own this email, please click the following link or paste it into your browser: {2}
  631. If you recieved this email and you did not sign up for an account, please email us at {3} and ignore the verification link.
  632. Thank you and enjoy!
  633. - Teknik Administration", username, resetUrl, verifyUrl, config.SupportEmail);
  634. mail.BodyEncoding = UTF8Encoding.UTF8;
  635. mail.DeliveryNotificationOptions = DeliveryNotificationOptions.Never;
  636. client.Send(mail);
  637. }
  638. public static bool VerifyRecoveryEmail(TeknikEntities db, Config config, string username, string code)
  639. {
  640. User user = GetUser(db, username);
  641. RecoveryEmailVerification verCode = db.RecoveryEmailVerifications.Where(r => r.User.Username == username && r.Code == code).FirstOrDefault();
  642. if (verCode != null)
  643. {
  644. // We have a match, so clear out the verifications for that user
  645. List<RecoveryEmailVerification> verCodes = db.RecoveryEmailVerifications.Where(r => r.User.Username == username).ToList();
  646. if (verCodes != null && verCodes.Any())
  647. {
  648. foreach (RecoveryEmailVerification ver in verCodes)
  649. {
  650. db.RecoveryEmailVerifications.Remove(ver);
  651. }
  652. }
  653. // Update the user
  654. user.SecuritySettings.RecoveryVerified = true;
  655. db.Entry(user).State = EntityState.Modified;
  656. db.SaveChanges();
  657. return true;
  658. }
  659. return false;
  660. }
  661. public static string CreateResetPasswordVerification(TeknikEntities db, Config config, User user)
  662. {
  663. // Check to see if there already is a verification code for the user
  664. List<ResetPasswordVerification> verCodes = db.ResetPasswordVerifications.Where(r => r.User.Username == user.Username).ToList();
  665. if (verCodes != null && verCodes.Any())
  666. {
  667. foreach (ResetPasswordVerification verCode in verCodes)
  668. {
  669. db.ResetPasswordVerifications.Remove(verCode);
  670. }
  671. }
  672. // Create a new verification code and add it
  673. string verifyCode = StringHelper.RandomString(24);
  674. ResetPasswordVerification ver = new ResetPasswordVerification();
  675. ver.UserId = user.UserId;
  676. ver.Code = verifyCode;
  677. ver.DateCreated = DateTime.Now;
  678. db.ResetPasswordVerifications.Add(ver);
  679. db.SaveChanges();
  680. return verifyCode;
  681. }
  682. public static void SendResetPasswordVerification(Config config, string username, string email, string resetUrl)
  683. {
  684. SmtpClient client = new SmtpClient();
  685. client.Host = config.ContactConfig.EmailAccount.Host;
  686. client.Port = config.ContactConfig.EmailAccount.Port;
  687. client.EnableSsl = config.ContactConfig.EmailAccount.SSL;
  688. client.DeliveryMethod = SmtpDeliveryMethod.Network;
  689. client.UseDefaultCredentials = true;
  690. client.Credentials = new NetworkCredential(config.ContactConfig.EmailAccount.Username, config.ContactConfig.EmailAccount.Password);
  691. client.Timeout = 5000;
  692. MailMessage mail = new MailMessage(config.ContactConfig.EmailAccount.EmailAddress, email);
  693. mail.Subject = "Password Reset Request";
  694. mail.Body = string.Format(@"Hello {0},
  695. You are recieving this email because either you or someone has requested a password reset for your account and this email was specified as the recovery email.
  696. To proceed in resetting your password, please click the following link or paste it into your browser: {1}
  697. If you recieved this email and you did not reset your password, you can ignore this email and email us at {2} to prevent it occuring again.
  698. - Teknik Administration", username, resetUrl, config.SupportEmail);
  699. mail.BodyEncoding = UTF8Encoding.UTF8;
  700. mail.DeliveryNotificationOptions = DeliveryNotificationOptions.Never;
  701. client.Send(mail);
  702. }
  703. public static bool VerifyResetPassword(TeknikEntities db, Config config, string username, string code)
  704. {
  705. User user = GetUser(db, username);
  706. ResetPasswordVerification verCode = db.ResetPasswordVerifications.Where(r => r.User.Username == username && r.Code == code).FirstOrDefault();
  707. if (verCode != null)
  708. {
  709. // We have a match, so clear out the verifications for that user
  710. List<ResetPasswordVerification> verCodes = db.ResetPasswordVerifications.Where(r => r.User.Username == username).ToList();
  711. if (verCodes != null && verCodes.Any())
  712. {
  713. foreach (ResetPasswordVerification ver in verCodes)
  714. {
  715. db.ResetPasswordVerifications.Remove(ver);
  716. }
  717. }
  718. db.SaveChanges();
  719. return true;
  720. }
  721. return false;
  722. }
  723. #endregion
  724. #region Email Management
  725. public static string GetUserEmailAddress(Config config, string username)
  726. {
  727. return string.Format("{0}@{1}", username, config.EmailConfig.Domain);
  728. }
  729. public static bool UserEmailExists(Config config, string email)
  730. {
  731. // If Email Server is enabled
  732. if (config.EmailConfig.Enabled)
  733. {
  734. // Connect to hmailserver COM
  735. var app = new hMailServer.Application();
  736. app.Connect();
  737. app.Authenticate(config.EmailConfig.Username, config.EmailConfig.Password);
  738. try
  739. {
  740. var domain = app.Domains.ItemByName[config.EmailConfig.Domain];
  741. var account = domain.Accounts.ItemByAddress[email];
  742. // We didn't error out, so the email exists
  743. return true;
  744. }
  745. catch { }
  746. }
  747. return false;
  748. }
  749. public static DateTime UserEmailLastActive(Config config, string email)
  750. {
  751. DateTime lastActive = new DateTime(1900, 1, 1);
  752. if (config.EmailConfig.Enabled)
  753. {
  754. var app = new hMailServer.Application();
  755. app.Connect();
  756. app.Authenticate(config.EmailConfig.Username, config.EmailConfig.Password);
  757. try
  758. {
  759. var domain = app.Domains.ItemByName[config.EmailConfig.Domain];
  760. var account = domain.Accounts.ItemByAddress[email];
  761. DateTime lastEmail = (DateTime)account.LastLogonTime;
  762. if (lastActive < lastEmail)
  763. lastActive = lastEmail;
  764. }
  765. catch { }
  766. }
  767. return lastActive;
  768. }
  769. public static void AddUserEmail(Config config, string email, string password)
  770. {
  771. try
  772. {
  773. // If Email Server is enabled
  774. if (config.EmailConfig.Enabled)
  775. {
  776. // Connect to hmailserver COM
  777. var app = new hMailServer.Application();
  778. app.Connect();
  779. app.Authenticate(config.EmailConfig.Username, config.EmailConfig.Password);
  780. var domain = app.Domains.ItemByName[config.EmailConfig.Domain];
  781. var newAccount = domain.Accounts.Add();
  782. newAccount.Address = email;
  783. newAccount.Password = password;
  784. newAccount.Active = true;
  785. newAccount.MaxSize = config.EmailConfig.MaxSize;
  786. newAccount.Save();
  787. }
  788. }
  789. catch (Exception ex)
  790. {
  791. throw new Exception("Unable to add email.", ex);
  792. }
  793. }
  794. public static void EnableUserEmail(Config config, string email)
  795. {
  796. EditUserEmailActivity(config, email, true);
  797. }
  798. public static void DisableUserEmail(Config config, string email)
  799. {
  800. EditUserEmailActivity(config, email, false);
  801. }
  802. public static void EditUserEmailActivity(Config config, string email, bool active)
  803. {
  804. try
  805. {
  806. // If Email Server is enabled
  807. if (config.EmailConfig.Enabled)
  808. {
  809. var app = new hMailServer.Application();
  810. app.Connect();
  811. app.Authenticate(config.EmailConfig.Username, config.EmailConfig.Password);
  812. var domain = app.Domains.ItemByName[config.EmailConfig.Domain];
  813. var account = domain.Accounts.ItemByAddress[email];
  814. account.Active = active;
  815. account.Save();
  816. }
  817. }
  818. catch (Exception ex)
  819. {
  820. throw new Exception("Unable to edit email account mailbox size.", ex);
  821. }
  822. }
  823. public static void EditUserEmailPassword(Config config, string email, string password)
  824. {
  825. try
  826. {
  827. // If Email Server is enabled
  828. if (config.EmailConfig.Enabled)
  829. {
  830. var app = new hMailServer.Application();
  831. app.Connect();
  832. app.Authenticate(config.EmailConfig.Username, config.EmailConfig.Password);
  833. var domain = app.Domains.ItemByName[config.EmailConfig.Domain];
  834. var account = domain.Accounts.ItemByAddress[email];
  835. account.Password = password;
  836. account.Save();
  837. }
  838. }
  839. catch (Exception ex)
  840. {
  841. throw new Exception("Unable to edit email account password.", ex);
  842. }
  843. }
  844. public static void EditUserEmailMaxSize(Config config, string email, int size)
  845. {
  846. try
  847. {
  848. // If Email Server is enabled
  849. if (config.EmailConfig.Enabled)
  850. {
  851. var app = new hMailServer.Application();
  852. app.Connect();
  853. app.Authenticate(config.EmailConfig.Username, config.EmailConfig.Password);
  854. var domain = app.Domains.ItemByName[config.EmailConfig.Domain];
  855. var account = domain.Accounts.ItemByAddress[email];
  856. account.MaxSize = size;
  857. account.Save();
  858. }
  859. }
  860. catch (Exception ex)
  861. {
  862. throw new Exception("Unable to edit email account mailbox size.", ex);
  863. }
  864. }
  865. public static void EditUserEmailMaxEmailsPerDay(Config config, string email, int maxPerDay)
  866. {
  867. try
  868. {
  869. // If Email Server is enabled
  870. if (config.EmailConfig.Enabled)
  871. {
  872. // We need to check the actual git database
  873. MysqlDatabase mySQL = new MysqlDatabase(config.EmailConfig.CounterDatabase.Server, config.EmailConfig.CounterDatabase.Database, config.EmailConfig.CounterDatabase.Username, config.EmailConfig.CounterDatabase.Password, config.EmailConfig.CounterDatabase.Port);
  874. string sql = @"INSERT INTO mailcounter.counts (qname, lastdate, qlimit, count) VALUES ({1}, NOW(), {0}, 0)
  875. ON DUPLICATE KEY UPDATE qlimit = {0}";
  876. mySQL.Execute(sql, new object[] { maxPerDay, email });
  877. }
  878. }
  879. catch (Exception ex)
  880. {
  881. throw new Exception("Unable to edit email account mailbox size.", ex);
  882. }
  883. }
  884. public static void DeleteUserEmail(Config config, string email)
  885. {
  886. try
  887. {
  888. // If Email Server is enabled
  889. if (config.EmailConfig.Enabled)
  890. {
  891. var app = new hMailServer.Application();
  892. app.Connect();
  893. app.Authenticate(config.EmailConfig.Username, config.EmailConfig.Password);
  894. var domain = app.Domains.ItemByName[config.EmailConfig.Domain];
  895. var account = domain.Accounts.ItemByAddress[email];
  896. if (account != null)
  897. {
  898. account.Delete();
  899. }
  900. }
  901. }
  902. catch (Exception ex)
  903. {
  904. throw new Exception("Unable to delete email account.", ex);
  905. }
  906. }
  907. #endregion
  908. #region Git Management
  909. public static bool UserGitExists(Config config, string username)
  910. {
  911. if (config.GitConfig.Enabled)
  912. {
  913. try
  914. {
  915. Uri baseUri = new Uri(config.GitConfig.Host);
  916. Uri finalUri = new Uri(baseUri, "api/v1/users/" + username + "?token=" + config.GitConfig.AccessToken);
  917. WebRequest request = WebRequest.Create(finalUri);
  918. request.Method = "GET";
  919. HttpWebResponse response = (HttpWebResponse)request.GetResponse();
  920. if (response.StatusCode == HttpStatusCode.OK)
  921. {
  922. return true;
  923. }
  924. }
  925. catch { }
  926. }
  927. return false;
  928. }
  929. public static DateTime UserGitLastActive(Config config, string username)
  930. {
  931. DateTime lastActive = new DateTime(1900, 1, 1);
  932. if (config.GitConfig.Enabled)
  933. {
  934. // Git user exists?
  935. if (!UserGitExists(config, username))
  936. {
  937. throw new Exception($"Git User '{username}' does not exist.");
  938. }
  939. string email = GetUserEmailAddress(config, username);
  940. // We need to check the actual git database
  941. MysqlDatabase mySQL = new MysqlDatabase(config.GitConfig.Database.Server, config.GitConfig.Database.Database, config.GitConfig.Database.Username, config.GitConfig.Database.Password, config.GitConfig.Database.Port);
  942. string sql = @"SELECT
  943. CASE
  944. WHEN MAX(gogs.action.created) >= MAX(gogs.user.updated) THEN MAX(gogs.action.created)
  945. WHEN MAX(gogs.user.updated) >= MAX(gogs.action.created) THEN MAX(gogs.user.updated)
  946. ELSE MAX(gogs.user.updated)
  947. END AS LastUpdate
  948. FROM gogs.user
  949. LEFT JOIN gogs.action ON gogs.user.id = gogs.action.act_user_id
  950. WHERE gogs.user.login_name = {0}";
  951. var results = mySQL.Query(sql, new object[] { email });
  952. if (results != null && results.Any())
  953. {
  954. var result = results.First();
  955. DateTime tmpLast = lastActive;
  956. DateTime.TryParse(result["LastUpdate"].ToString(), out tmpLast);
  957. if (lastActive < tmpLast)
  958. lastActive = tmpLast;
  959. }
  960. }
  961. return lastActive;
  962. }
  963. public static void AddUserGit(Config config, string username, string password)
  964. {
  965. try
  966. {
  967. // If Git is enabled
  968. if (config.GitConfig.Enabled)
  969. {
  970. string email = GetUserEmailAddress(config, username);
  971. // Add gogs user
  972. using (var client = new WebClient())
  973. {
  974. var obj = new { source_id = config.GitConfig.SourceId, username = username, email = email, login_name = email, password = password };
  975. string json = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
  976. client.Headers[HttpRequestHeader.ContentType] = "application/json";
  977. Uri baseUri = new Uri(config.GitConfig.Host);
  978. Uri finalUri = new Uri(baseUri, "api/v1/admin/users?token=" + config.GitConfig.AccessToken);
  979. string result = client.UploadString(finalUri, "POST", json);
  980. }
  981. }
  982. }
  983. catch (Exception ex)
  984. {
  985. throw new Exception("Unable to add git account.", ex);
  986. }
  987. }
  988. public static void EditUserGitPassword(Config config, string username, string password)
  989. {
  990. try
  991. {
  992. // If Git is enabled
  993. if (config.GitConfig.Enabled)
  994. {
  995. // Git user exists?
  996. if (!UserGitExists(config, username))
  997. {
  998. throw new Exception($"Git User '{username}' does not exist.");
  999. }
  1000. string email = GetUserEmailAddress(config, username);
  1001. using (var client = new WebClient())
  1002. {
  1003. var obj = new {source_id = config.GitConfig.SourceId, email = email, login_name = email, password = password};
  1004. string json = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
  1005. client.Headers[HttpRequestHeader.ContentType] = "application/json";
  1006. Uri baseUri = new Uri(config.GitConfig.Host);
  1007. Uri finalUri = new Uri(baseUri, "api/v1/admin/users/" + username + "?token=" + config.GitConfig.AccessToken);
  1008. string result = client.UploadString(finalUri, "PATCH", json);
  1009. }
  1010. }
  1011. }
  1012. catch (Exception ex)
  1013. {
  1014. throw new Exception("Unable to edit git account password.", ex);
  1015. }
  1016. }
  1017. public static void EnableUserGit(Config config, string username)
  1018. {
  1019. EditUserGitActivity(config, username, true);
  1020. }
  1021. public static void DisableUserGit(Config config, string username)
  1022. {
  1023. EditUserGitActivity(config, username, false);
  1024. }
  1025. public static void EditUserGitActivity(Config config, string username, bool active)
  1026. {
  1027. try
  1028. {
  1029. // If Git is enabled
  1030. if (config.GitConfig.Enabled)
  1031. {
  1032. // Git user exists?
  1033. if (!UserGitExists(config, username))
  1034. {
  1035. throw new Exception($"Git User '{username}' does not exist.");
  1036. }
  1037. string email = GetUserEmailAddress(config, username);
  1038. using (var client = new WebClient())
  1039. {
  1040. var obj = new { active = active, email = email };
  1041. string json = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
  1042. client.Headers[HttpRequestHeader.ContentType] = "application/json";
  1043. Uri baseUri = new Uri(config.GitConfig.Host);
  1044. Uri finalUri = new Uri(baseUri, "api/v1/admin/users/" + username + "?token=" + config.GitConfig.AccessToken);
  1045. string result = client.UploadString(finalUri, "PATCH", json);
  1046. }
  1047. }
  1048. }
  1049. catch (Exception ex)
  1050. {
  1051. throw new Exception("Unable to edit git account password.", ex);
  1052. }
  1053. }
  1054. public static void CreateUserGitTwoFactor(Config config, string username, string secret, int unixTime)
  1055. {
  1056. try
  1057. {
  1058. // If Git is enabled
  1059. if (config.GitConfig.Enabled)
  1060. {
  1061. // Git user exists?
  1062. if (!UserGitExists(config, username))
  1063. {
  1064. throw new Exception($"Git User '{username}' does not exist.");
  1065. }
  1066. // Generate the scratch token
  1067. string token = StringHelper.RandomString(8);
  1068. // Get the Encryption Key from the git secret key
  1069. byte[] keyBytes = MD5.Hash(Encoding.UTF8.GetBytes(config.GitConfig.SecretKey));
  1070. // Modify the input secret
  1071. byte[] secBytes = Encoding.UTF8.GetBytes(secret);
  1072. // Generate the encrypted secret using AES CGM
  1073. byte[] encValue = Aes128CFB.Encrypt(secBytes, keyBytes);
  1074. string finalSecret = Convert.ToBase64String(encValue);
  1075. // Create connection to the DB
  1076. MysqlDatabase mySQL = new MysqlDatabase(config.GitConfig.Database.Server, config.GitConfig.Database.Database, config.GitConfig.Database.Username, config.GitConfig.Database.Password, config.GitConfig.Database.Port);
  1077. mySQL.MysqlErrorEvent += (sender, s) =>
  1078. {
  1079. throw new Exception("Unable to edit git account two factor. Mysql Exception: " + s);
  1080. };
  1081. // Get the user's UID
  1082. string email = GetUserEmailAddress(config, username);
  1083. string userSelect = @"SELECT gogs.user.id FROM gogs.user WHERE gogs.user.login_name = {0}";
  1084. var uid = mySQL.ScalarQuery(userSelect, new object[] { email });
  1085. // See if they have Two Factor already
  1086. string sqlSelect = @"SELECT tf.id
  1087. FROM gogs.two_factor tf
  1088. LEFT JOIN gogs.user u ON u.id = tf.uid
  1089. WHERE u.login_name = {0}";
  1090. var result = mySQL.ScalarQuery(sqlSelect, new object[] { email });
  1091. if (result != null)
  1092. {
  1093. // They have an entry! Let's update it
  1094. string update = @"UPDATE gogs.two_factor tf SET tf.uid = {1}, tf.secret = {2}, tf.scratch_token = {3}, tf.updated_unix = {4} WHERE tf.id = {0}";
  1095. mySQL.Execute(update, new object[] { result, uid, finalSecret, token, unixTime });
  1096. }
  1097. else
  1098. {
  1099. // They need a new entry
  1100. string insert = @"INSERT INTO gogs.two_factor (uid, secret, scratch_token, created_unix, updated_unix) VALUES ({0}, {1}, {2}, {3}, {4})";
  1101. mySQL.Execute(insert, new object[] { uid, finalSecret, token, unixTime, 0 });
  1102. }
  1103. }
  1104. }
  1105. catch (Exception ex)
  1106. {
  1107. throw new Exception("Unable to edit git account two factor.", ex);
  1108. }
  1109. }
  1110. public static void DeleteUserGitTwoFactor(Config config, string username)
  1111. {
  1112. try
  1113. {
  1114. // If Git is enabled
  1115. if (config.GitConfig.Enabled)
  1116. {
  1117. // Git user exists?
  1118. if (!UserGitExists(config, username))
  1119. {
  1120. throw new Exception($"Git User '{username}' does not exist.");
  1121. }
  1122. // Create connection to the DB
  1123. MysqlDatabase mySQL = new MysqlDatabase(config.GitConfig.Database.Server, config.GitConfig.Database.Database, config.GitConfig.Database.Username, config.GitConfig.Database.Password, config.GitConfig.Database.Port);
  1124. // Get the user's UID
  1125. string email = GetUserEmailAddress(config, username);
  1126. // See if they have Two Factor already
  1127. string deleteSql = @"DELETE tf.*
  1128. FROM gogs.two_factor tf
  1129. LEFT JOIN gogs.user u ON u.id = tf.uid
  1130. WHERE u.login_name = {0}";
  1131. mySQL.Execute(deleteSql, new object[] { email });
  1132. }
  1133. }
  1134. catch (Exception ex)
  1135. {
  1136. throw new Exception("Unable to delete git account two factor.", ex);
  1137. }
  1138. }
  1139. public static void DeleteUserGit(Config config, string username)
  1140. {
  1141. try
  1142. {
  1143. // If Git is enabled
  1144. if (config.GitConfig.Enabled)
  1145. {
  1146. // Git user exists?
  1147. if (!UserGitExists(config, username))
  1148. {
  1149. throw new Exception($"Git User '{username}' does not exist.");
  1150. }
  1151. try
  1152. {
  1153. Uri baseUri = new Uri(config.GitConfig.Host);
  1154. Uri finalUri = new Uri(baseUri, "api/v1/admin/users/" + username + "?token=" + config.GitConfig.AccessToken);
  1155. WebRequest request = WebRequest.Create(finalUri);
  1156. request.Method = "DELETE";
  1157. HttpWebResponse response = (HttpWebResponse)request.GetResponse();
  1158. if (response.StatusCode != HttpStatusCode.NotFound && response.StatusCode != HttpStatusCode.OK && response.StatusCode != HttpStatusCode.NoContent)
  1159. {
  1160. throw new Exception("Unable to delete git account. Response Code: " + response.StatusCode);
  1161. }
  1162. }
  1163. catch (HttpException htex)
  1164. {
  1165. if (htex.GetHttpCode() != 404)
  1166. throw new Exception("Unable to delete git account. Http Exception: " + htex.Message);
  1167. }
  1168. catch (Exception ex)
  1169. {
  1170. // This error signifies the user doesn't exist, so we can continue deleting
  1171. if (ex.Message != "The remote server returned an error: (404) Not Found.")
  1172. {
  1173. throw new Exception("Unable to delete git account. Exception: " + ex.Message);
  1174. }
  1175. }
  1176. }
  1177. }
  1178. catch (Exception ex)
  1179. {
  1180. throw new Exception("Unable to delete git account.", ex);
  1181. }
  1182. }
  1183. #endregion
  1184. public static HttpCookie CreateAuthCookie(string username, bool remember, string domain, bool local)
  1185. {
  1186. DateTime curTime = DateTime.Now;
  1187. DateTime expireTime = curTime.AddMonths(1);
  1188. Config config = Config.Load();
  1189. FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(
  1190. 1,
  1191. username,
  1192. curTime,
  1193. expireTime,
  1194. remember,
  1195. username
  1196. );
  1197. string encTicket = FormsAuthentication.Encrypt(ticket);
  1198. HttpCookie authcookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
  1199. authcookie.HttpOnly = true;
  1200. authcookie.Secure = true;
  1201. if (remember)
  1202. {
  1203. authcookie.Expires = expireTime;
  1204. }
  1205. // Set domain dependent on where it's being ran from
  1206. if (local) // localhost
  1207. {
  1208. authcookie.Domain = null;
  1209. }
  1210. else if (config.DevEnvironment) // dev.example.com
  1211. {
  1212. authcookie.Domain = string.Format("dev.{0}", domain);
  1213. }
  1214. else // A production instance
  1215. {
  1216. authcookie.Domain = string.Format(".{0}", domain);
  1217. }
  1218. return authcookie;
  1219. }
  1220. public static HttpCookie CreateTrustedDeviceCookie(string username, string domain, bool local)
  1221. {
  1222. Config config = Config.Load();
  1223. byte[] time = BitConverter.GetBytes(DateTime.UtcNow.ToBinary());
  1224. byte[] key = Guid.NewGuid().ToByteArray();
  1225. string token = Convert.ToBase64String(time.Concat(key).ToArray());
  1226. HttpCookie trustCookie = new HttpCookie(Constants.TRUSTEDDEVICECOOKIE + "_" + username);
  1227. trustCookie.Value = token;
  1228. trustCookie.HttpOnly = true;
  1229. trustCookie.Secure = true;
  1230. trustCookie.Expires = DateTime.Now.AddYears(1);
  1231. // Set domain dependent on where it's being ran from
  1232. if (local) // localhost
  1233. {
  1234. trustCookie.Domain = null;
  1235. }
  1236. else if (config.DevEnvironment) // dev.example.com
  1237. {
  1238. trustCookie.Domain = string.Format("dev.{0}", domain);
  1239. }
  1240. else // A production instance
  1241. {
  1242. trustCookie.Domain = string.Format(".{0}", domain);
  1243. }
  1244. return trustCookie;
  1245. }
  1246. }
  1247. }