The next generation of the Teknik Services. Written in ASP.NET. Fork for blog tags.
Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.

UserHelper.cs 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.Entity;
  4. using System.Linq;
  5. using System.Net;
  6. using System.Runtime.InteropServices;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Web;
  10. using System.Web.Security;
  11. using Teknik.Areas.Blog.Models;
  12. using Teknik.Areas.Shortener.Models;
  13. using Teknik.Areas.Users.Models;
  14. using Teknik.Configuration;
  15. using Teknik.Helpers;
  16. using Teknik.Models;
  17. namespace Teknik.Areas.Users.Utility
  18. {
  19. public static class UserHelper
  20. {
  21. #region User Management
  22. public static User GetUser(TeknikEntities db, string username)
  23. {
  24. User user = db.Users.Where(b => b.Username == username).FirstOrDefault();
  25. if (user != null)
  26. {
  27. user.UserSettings = db.UserSettings.Find(user.UserId);
  28. user.BlogSettings = db.BlogSettings.Find(user.UserId);
  29. user.UploadSettings = db.UploadSettings.Find(user.UserId);
  30. }
  31. return user;
  32. }
  33. public static bool UserExists(TeknikEntities db, string username)
  34. {
  35. User user = GetUser(db, username);
  36. if (user != null)
  37. {
  38. return true;
  39. }
  40. return false;
  41. }
  42. public static bool ValidUsername(TeknikEntities db, Config config, string username)
  43. {
  44. bool isValid = true;
  45. if (config.UserConfig.ReservedUsernames.Exists(u => u.ToLower() == username.ToLower()))
  46. isValid = false;
  47. return isValid;
  48. }
  49. public static bool UsernameAvailable(TeknikEntities db, Config config, string username)
  50. {
  51. bool isAvailable = true;
  52. isAvailable &= ValidUsername(db, config, username);
  53. isAvailable &= !UserExists(db, username);
  54. isAvailable &= !UserEmailExists(config, username);
  55. isAvailable &= !UserGitExists(config, username);
  56. return isAvailable;
  57. }
  58. public static DateTime GetLastActivity(TeknikEntities db, Config config, User user)
  59. {
  60. try
  61. {
  62. DateTime lastActive = new DateTime(1900, 1, 1);
  63. string email = string.Format("{0}@{1}", user.Username, config.EmailConfig.Domain);
  64. DateTime emailLastActive = UserEmailLastActive(config, user.Username);
  65. if (lastActive < emailLastActive)
  66. lastActive = emailLastActive;
  67. DateTime gitLastActive = UserGitLastActive(config, user.Username);
  68. if (lastActive < gitLastActive)
  69. lastActive = gitLastActive;
  70. if (lastActive < user.LastSeen)
  71. lastActive = user.LastSeen;
  72. return lastActive;
  73. }
  74. catch (Exception ex)
  75. {
  76. throw new Exception("Unable to determine last activity.", ex);
  77. }
  78. }
  79. public static void AddUser(TeknikEntities db, Config config, User user, string password)
  80. {
  81. try
  82. {
  83. // Create an Email Account
  84. AddUserEmail(config, user, password);
  85. // Create a Git Account
  86. AddUserGit(config, user, password);
  87. // Add User
  88. user.HashedPassword = SHA384.Hash(user.Username, password);
  89. db.Users.Add(user);
  90. db.SaveChanges();
  91. // Generate blog for the user
  92. var newBlog = db.Blogs.Create();
  93. newBlog.UserId = user.UserId;
  94. db.Blogs.Add(newBlog);
  95. db.SaveChanges();
  96. }
  97. catch (Exception ex)
  98. {
  99. throw new Exception("Unable to create user.", ex);
  100. }
  101. }
  102. public static void EditUser(TeknikEntities db, Config config, User user, bool changePass, string password)
  103. {
  104. try
  105. {
  106. string email = string.Format("{0}@{1}", user.Username, config.EmailConfig.Domain);
  107. // Changing Password?
  108. if (changePass)
  109. {
  110. // Change email password
  111. EditUserEmailPassword(config, user, password);
  112. // Update Git password
  113. EditUserGitPassword(config, user, password);
  114. // Update User password
  115. user.HashedPassword = SHA384.Hash(user.Username, password);
  116. }
  117. db.Entry(user).State = EntityState.Modified;
  118. db.SaveChanges();
  119. }
  120. catch (Exception ex)
  121. {
  122. throw new Exception("Unable to edit user.", ex);
  123. }
  124. }
  125. public static void DeleteUser(TeknikEntities db, Config config, User user)
  126. {
  127. try
  128. {
  129. // Delete Email Account
  130. DeleteUserEmail(config, user);
  131. // Delete Git Account
  132. DeleteUserGit(config, user);
  133. // Update uploads
  134. List<Upload.Models.Upload> uploads = db.Uploads.Include("User").Where(u => u.User.Username == user.Username).ToList();
  135. if (uploads != null)
  136. {
  137. foreach (Upload.Models.Upload upload in uploads)
  138. {
  139. upload.UserId = null;
  140. db.Entry(upload).State = EntityState.Modified;
  141. }
  142. }
  143. // Update pastes
  144. List<Paste.Models.Paste> pastes = db.Pastes.Include("User").Where(u => u.User.Username == user.Username).ToList();
  145. if (pastes != null)
  146. {
  147. foreach (Paste.Models.Paste paste in pastes)
  148. {
  149. paste.UserId = null;
  150. db.Entry(paste).State = EntityState.Modified;
  151. }
  152. }
  153. // Update shortened urls
  154. List<ShortenedUrl> shortUrls = db.ShortenedUrls.Include("User").Where(u => u.User.Username == user.Username).ToList();
  155. if (shortUrls != null)
  156. {
  157. foreach (ShortenedUrl shortUrl in shortUrls)
  158. {
  159. shortUrl.UserId = null;
  160. db.Entry(shortUrl).State = EntityState.Modified;
  161. }
  162. }
  163. // Delete Blogs
  164. Blog.Models.Blog blog = db.Blogs.Include("BlogPosts").Include("BlogPosts.Comments").Include("User").Where(u => u.User.Username == user.Username).FirstOrDefault();
  165. if (blog != null)
  166. {
  167. db.Blogs.Remove(blog);
  168. }
  169. // Delete post comments
  170. List<BlogPostComment> postComments = db.BlogComments.Include("User").Where(u => u.User.Username == user.Username).ToList();
  171. if (postComments != null)
  172. {
  173. foreach (BlogPostComment postComment in postComments)
  174. {
  175. db.BlogComments.Remove(postComment);
  176. }
  177. }
  178. // Delete podcast comments
  179. List<Podcast.Models.PodcastComment> podComments = db.PodcastComments.Include("User").Where(u => u.User.Username == user.Username).ToList();
  180. if (podComments != null)
  181. {
  182. foreach (Podcast.Models.PodcastComment podComment in podComments)
  183. {
  184. db.PodcastComments.Remove(podComment);
  185. }
  186. }
  187. // Delete User
  188. db.Users.Remove(user);
  189. db.SaveChanges();
  190. }
  191. catch (Exception ex)
  192. {
  193. throw new Exception("Unable to delete user.", ex);
  194. }
  195. }
  196. #endregion
  197. #region Email Management
  198. public static bool UserEmailExists(Config config, string username)
  199. {
  200. // If Email Server is enabled
  201. if (config.EmailConfig.Enabled)
  202. {
  203. string email = string.Format("{0}@{1}", username, config.EmailConfig.Domain);
  204. // Connect to hmailserver COM
  205. var app = new hMailServer.Application();
  206. app.Connect();
  207. app.Authenticate(config.EmailConfig.Username, config.EmailConfig.Password);
  208. try
  209. {
  210. var domain = app.Domains.ItemByName[config.EmailConfig.Domain];
  211. var account = domain.Accounts.ItemByAddress[email];
  212. // We didn't error out, so the email exists
  213. return true;
  214. }
  215. catch { }
  216. }
  217. return false;
  218. }
  219. public static DateTime UserEmailLastActive(Config config, string username)
  220. {
  221. DateTime lastActive = new DateTime(1900, 1, 1);
  222. if (config.EmailConfig.Enabled)
  223. {
  224. string email = string.Format("{0}@{1}", username, config.EmailConfig.Domain);
  225. var app = new hMailServer.Application();
  226. app.Connect();
  227. app.Authenticate(config.EmailConfig.Username, config.EmailConfig.Password);
  228. try
  229. {
  230. var domain = app.Domains.ItemByName[config.EmailConfig.Domain];
  231. var account = domain.Accounts.ItemByAddress[email];
  232. DateTime lastEmail = (DateTime)account.LastLogonTime;
  233. if (lastActive < lastEmail)
  234. lastActive = lastEmail;
  235. }
  236. catch { }
  237. }
  238. return lastActive;
  239. }
  240. public static void AddUserEmail(Config config, User user, string password)
  241. {
  242. try
  243. {
  244. // If Email Server is enabled
  245. if (config.EmailConfig.Enabled)
  246. {
  247. string email = string.Format("{0}@{1}", user.Username, config.EmailConfig.Domain);
  248. // Connect to hmailserver COM
  249. var app = new hMailServer.Application();
  250. app.Connect();
  251. app.Authenticate(config.EmailConfig.Username, config.EmailConfig.Password);
  252. var domain = app.Domains.ItemByName[config.EmailConfig.Domain];
  253. var newAccount = domain.Accounts.Add();
  254. newAccount.Address = email;
  255. newAccount.Password = password;
  256. newAccount.Active = true;
  257. newAccount.MaxSize = config.EmailConfig.MaxSize;
  258. newAccount.Save();
  259. }
  260. }
  261. catch (Exception ex)
  262. {
  263. throw new Exception("Unable to add email.", ex);
  264. }
  265. }
  266. public static void EditUserEmailPassword(Config config, User user, string password)
  267. {
  268. try
  269. {
  270. // If Email Server is enabled
  271. if (config.EmailConfig.Enabled)
  272. {
  273. string email = string.Format("{0}@{1}", user.Username, config.EmailConfig.Domain);
  274. var app = new hMailServer.Application();
  275. app.Connect();
  276. app.Authenticate(config.EmailConfig.Username, config.EmailConfig.Password);
  277. var domain = app.Domains.ItemByName[config.EmailConfig.Domain];
  278. var account = domain.Accounts.ItemByAddress[email];
  279. account.Password = password;
  280. account.Save();
  281. }
  282. }
  283. catch (Exception ex)
  284. {
  285. throw new Exception("Unable to edit email account password.", ex);
  286. }
  287. }
  288. public static void DeleteUserEmail(Config config, User user)
  289. {
  290. try
  291. {
  292. // If Email Server is enabled
  293. if (config.EmailConfig.Enabled)
  294. {
  295. string email = string.Format("{0}@{1}", user.Username, config.EmailConfig.Domain);
  296. var app = new hMailServer.Application();
  297. app.Connect();
  298. app.Authenticate(config.EmailConfig.Username, config.EmailConfig.Password);
  299. var domain = app.Domains.ItemByName[config.EmailConfig.Domain];
  300. var account = domain.Accounts.ItemByAddress[string.Format("{0}@{1}", user.Username, config.EmailConfig.Domain)];
  301. if (account != null)
  302. {
  303. account.Delete();
  304. }
  305. }
  306. }
  307. catch (Exception ex)
  308. {
  309. throw new Exception("Unable to delete email account.", ex);
  310. }
  311. }
  312. #endregion
  313. #region Git Management
  314. public static bool UserGitExists(Config config, string username)
  315. {
  316. if (config.GitConfig.Enabled)
  317. {
  318. try
  319. {
  320. Uri baseUri = new Uri(config.GitConfig.Host);
  321. Uri finalUri = new Uri(baseUri, "api/v1/users/" + username + "?token=" + config.GitConfig.AccessToken);
  322. WebRequest request = WebRequest.Create(finalUri);
  323. request.Method = "GET";
  324. HttpWebResponse response = (HttpWebResponse)request.GetResponse();
  325. if (response.StatusCode == HttpStatusCode.OK)
  326. {
  327. return true;
  328. }
  329. }
  330. catch { }
  331. }
  332. return false;
  333. }
  334. public static DateTime UserGitLastActive(Config config, string username)
  335. {
  336. DateTime lastActive = new DateTime(1900, 1, 1);
  337. if (config.GitConfig.Enabled)
  338. {
  339. string email = string.Format("{0}@{1}", username, config.EmailConfig.Domain);
  340. // We need to check the actual git database
  341. MysqlDatabase mySQL = new MysqlDatabase(config.GitConfig.Database);
  342. string sql = @"SELECT MAX(gogs.repository.updated) AS LastUpdate
  343. FROM gogs.repository
  344. INNER JOIN gogs.user
  345. WHERE gogs.user.login_name = {0} AND gogs.user.id = gogs.repository.owner_id";
  346. object result = mySQL.ScalarQuery(sql, new object[] { email });
  347. if (result != null)
  348. {
  349. DateTime tmpLast = lastActive;
  350. DateTime.TryParse(result.ToString(), out tmpLast);
  351. if (lastActive < tmpLast)
  352. lastActive = tmpLast;
  353. }
  354. }
  355. return lastActive;
  356. }
  357. public static void AddUserGit(Config config, User user, string password)
  358. {
  359. try
  360. {
  361. // If Git is enabled
  362. if (config.GitConfig.Enabled)
  363. {
  364. string email = string.Format("{0}@{1}", user.Username, config.EmailConfig.Domain);
  365. // Add gogs user
  366. using (var client = new WebClient())
  367. {
  368. var obj = new { source_id = config.GitConfig.SourceId, username = user.Username, email = email, login_name = email, password = password };
  369. string json = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
  370. client.Headers[HttpRequestHeader.ContentType] = "application/json";
  371. Uri baseUri = new Uri(config.GitConfig.Host);
  372. Uri finalUri = new Uri(baseUri, "api/v1/admin/users?token=" + config.GitConfig.AccessToken);
  373. string result = client.UploadString(finalUri, "POST", json);
  374. }
  375. }
  376. }
  377. catch (Exception ex)
  378. {
  379. throw new Exception("Unable to add git account.", ex);
  380. }
  381. }
  382. public static void EditUserGitPassword(Config config, User user, string password)
  383. {
  384. try
  385. {
  386. // If Git is enabled
  387. if (config.GitConfig.Enabled)
  388. {
  389. string email = string.Format("{0}@{1}", user.Username, config.EmailConfig.Domain);
  390. using (var client = new WebClient())
  391. {
  392. var obj = new { source_id = config.GitConfig.SourceId, email = email, password = password };
  393. string json = Newtonsoft.Json.JsonConvert.SerializeObject(obj);
  394. client.Headers[HttpRequestHeader.ContentType] = "application/json";
  395. Uri baseUri = new Uri(config.GitConfig.Host);
  396. Uri finalUri = new Uri(baseUri, "api/v1/admin/users/" + user.Username + "?token=" + config.GitConfig.AccessToken);
  397. string result = client.UploadString(finalUri, "PATCH", json);
  398. }
  399. }
  400. }
  401. catch (Exception ex)
  402. {
  403. throw new Exception("Unable to edit git account password.", ex);
  404. }
  405. }
  406. public static void DeleteUserGit(Config config, User user)
  407. {
  408. try
  409. {
  410. // If Git is enabled
  411. if (config.GitConfig.Enabled)
  412. {
  413. try
  414. {
  415. Uri baseUri = new Uri(config.GitConfig.Host);
  416. Uri finalUri = new Uri(baseUri, "api/v1/admin/users/" + user.Username + "?token=" + config.GitConfig.AccessToken);
  417. WebRequest request = WebRequest.Create(finalUri);
  418. request.Method = "DELETE";
  419. HttpWebResponse response = (HttpWebResponse)request.GetResponse();
  420. if (response.StatusCode != HttpStatusCode.NotFound && response.StatusCode != HttpStatusCode.OK)
  421. {
  422. throw new Exception("Unable to delete git account. Response Code: " + response.StatusCode);
  423. }
  424. }
  425. catch (HttpException htex)
  426. {
  427. if (htex.GetHttpCode() != 404)
  428. throw new Exception("Unable to delete git account. Http Exception: " + htex.Message);
  429. }
  430. catch (Exception ex)
  431. {
  432. // This error signifies the user doesn't exist, so we can continue deleting
  433. if (ex.Message != "The remote server returned an error: (404) Not Found.")
  434. {
  435. throw new Exception("Unable to delete git account. Exception: " + ex.Message);
  436. }
  437. }
  438. }
  439. }
  440. catch (Exception ex)
  441. {
  442. throw new Exception("Unable to delete git account.", ex);
  443. }
  444. }
  445. #endregion
  446. public static HttpCookie CreateAuthCookie(string username, bool remember, string domain, bool local)
  447. {
  448. Config config = Config.Load();
  449. HttpCookie authcookie = FormsAuthentication.GetAuthCookie(username, remember);
  450. authcookie.Name = "TeknikAuth";
  451. authcookie.HttpOnly = true;
  452. authcookie.Secure = true;
  453. // Set domain dependent on where it's being ran from
  454. if (local) // localhost
  455. {
  456. authcookie.Domain = null;
  457. }
  458. else if (config.DevEnvironment) // dev.example.com
  459. {
  460. authcookie.Domain = string.Format("dev.{0}", domain);
  461. }
  462. else // A production instance
  463. {
  464. authcookie.Domain = string.Format(".{0}", domain);
  465. }
  466. return authcookie;
  467. }
  468. }
  469. }