PageRenderTime 165ms CodeModel.GetById 17ms RepoModel.GetById 1ms app.codeStats 0ms

/jSLCore/jSLCore/jSLCore.Service/Security/jDatabaseSecurityManager.cs

#
C# | 305 lines | 240 code | 44 blank | 21 comment | 23 complexity | 40191a7f4c03233bb52bc35e968e5c0a MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.Linq;
  4. using System.Linq;
  5. using jSLCore.Service.Workflow;
  6. using jSLCore.Service.Workflow.Linq;
  7. namespace jSLCore.Service.Security
  8. {
  9. /// <summary>
  10. /// Security based on jDatabase sql database
  11. /// </summary>
  12. // ReSharper disable InconsistentNaming
  13. public class jDatabaseSecurityManager : ISecurityManager
  14. // ReSharper restore InconsistentNaming
  15. , IPermissionDescriptionProvider
  16. , IEnumDescriptionProvider
  17. , ISuperVisorManager
  18. , IPasswordManager
  19. {
  20. private readonly string _connectionString;
  21. public jDatabaseSecurityManager(string connectionString)
  22. {
  23. _connectionString = connectionString;
  24. }
  25. #region IEnumDescriptionProvider Members
  26. public EnumDescription[] GetAllEnumDescriptions()
  27. {
  28. using (var db = new SecurityDatabaseDataContext(_connectionString))
  29. {
  30. return db.EnumDescriptions.ToArray();
  31. }
  32. }
  33. #endregion
  34. #region IPasswordManager Members
  35. public void ChangeCurrentUserPassword(string userName, string oldPwd, string newPwd)
  36. {
  37. using (var db = new SecurityDatabaseDataContext(_connectionString))
  38. {
  39. var user = db.Users.GetUserByLoginAndPwdOrNull(userName, oldPwd);
  40. if (user == null)
  41. {
  42. jWorkflowException.ThrowNew(
  43. "Пользователь с указанным именем и паролем не найден. Возможно пароль введен не правильно");
  44. throw new InvalidProgramException();
  45. }
  46. user.Password = new Binary(jSLAuthorizationServiceBase.GetPasswordHash(newPwd));
  47. db.SubmitChanges();
  48. }
  49. }
  50. #endregion
  51. #region IPermissionDescriptionProvider Members
  52. public PermissionDescription[] GetAllPermissionDescriptions()
  53. {
  54. using (var db = new SecurityDatabaseDataContext(_connectionString))
  55. {
  56. return db.PermissionDescriptions.ToArray();
  57. }
  58. }
  59. #endregion
  60. #region ISecurityManager Members
  61. public User Authorize(string login, string password)
  62. {
  63. using (var db = new SecurityDatabaseDataContext(_connectionString))
  64. {
  65. User user = null;
  66. try
  67. {
  68. user = db.Users.GetUserByLoginAndPwdOrNull(login, password);
  69. if (user == null) throw new InvalidOperationException();
  70. //user = new User(){IsEnabled = true,Login = loginName,Password = pwdHash};//создаем пользователя
  71. }
  72. catch (InvalidOperationException)
  73. {
  74. jWorkflowException.ThrowNew("Имя пользователя или пароль введены неправильно");
  75. }
  76. //db.Users.InsertOnSubmit(user);
  77. //db.SubmitChanges();
  78. // ReSharper disable PossibleNullReferenceException
  79. if (!user.IsEnabled)
  80. jWorkflowException.ThrowNew("Ваш аккаунт заблокирован. Обратитесь к администратору.");
  81. // ReSharper restore PossibleNullReferenceException
  82. Guid remeberCode = Guid.NewGuid(); //everytime user auth by login/pwd.. the remebercode will be reseted
  83. user.RemeberCode = remeberCode;
  84. db.SubmitChanges();
  85. db.Refresh(RefreshMode.OverwriteCurrentValues, user);
  86. return user;
  87. }
  88. }
  89. public User AuthorizeByCode(Guid code)
  90. {
  91. using (var db = new SecurityDatabaseDataContext(_connectionString))
  92. {
  93. User user;
  94. try
  95. {
  96. user = db.Users.SingleOrDefault(u => u.RemeberCode == code);
  97. if (user == null) throw new InvalidOperationException();
  98. //user = new User(){IsEnabled = true,Login = loginName,Password = pwdHash};//создаем пользователя
  99. }
  100. catch (InvalidOperationException)
  101. {
  102. //jWorkflowException.ThrowNew("Невозможно авторизоваться"); do nothing... user is out of login silently
  103. return null;
  104. }
  105. //db.Users.InsertOnSubmit(user);
  106. //db.SubmitChanges();
  107. if (!user.IsEnabled)
  108. {
  109. //jWorkflowException.ThrowNew("Ваш аккаунт заблокирован. Обратитесь к администратору."); check upper comment
  110. return null;
  111. }
  112. return user;
  113. }
  114. }
  115. public int[] GetPermissionSet(string userName)
  116. {
  117. using (var db = new SecurityDatabaseDataContext(_connectionString))
  118. {
  119. User user = db.Users.GetOneOrNull(userName, "Login");
  120. if (user == null) return new int[0];
  121. return user.GetPermissionSet();
  122. }
  123. }
  124. public User GetUser(string login)
  125. {
  126. using (var db = new SecurityDatabaseDataContext(_connectionString))
  127. {
  128. User user = db.Users.GetOneOrjWorkflowException(login, "Пользователь", login, "Login");
  129. return user;
  130. }
  131. }
  132. public bool IsUserHasPermission(string userName, int permission)
  133. {
  134. using (var db = new SecurityDatabaseDataContext(_connectionString))
  135. {
  136. User user = db.Users.SingleOrDefault(u => u.Login == userName);
  137. return IsUserHasPermission(user, permission);
  138. }
  139. }
  140. #endregion
  141. #region ISuperVisorManager Members
  142. public PermissionDescription[] GetInheritedPermissions(Guid roleId)
  143. {
  144. using (var db = new SecurityDatabaseDataContext(_connectionString))
  145. {
  146. Role role = db.Roles.GetOneOrjWorkflowException(roleId, "Роль", "");
  147. IEnumerable<Permission> permissions = role
  148. .GetAllRoles()
  149. .SelectMany(r => r.Permissions)
  150. .Distinct();
  151. return permissions
  152. // ReSharper disable AccessToDisposedClosure
  153. .Select(p => db.PermissionDescriptions.GetOne(p.PermissionNumber, "Permission"))
  154. // ReSharper restore AccessToDisposedClosure
  155. .ToArray();
  156. }
  157. }
  158. public Role GetRole(Guid id)
  159. {
  160. using (var db = new SecurityDatabaseDataContext(_connectionString))
  161. {
  162. Role role = db.Roles.GetOneOrjWorkflowException(id, "Роль", "");
  163. role.BeforeSending(db);
  164. return role;
  165. }
  166. }
  167. public Role[] SearchRoles(string searchText)
  168. {
  169. using (var db = new SecurityDatabaseDataContext(_connectionString))
  170. {
  171. Role[] res = db.Roles.Where(r => r.Name.Contains(searchText)).ToArray();
  172. foreach (Role role in res)
  173. {
  174. role.BeforeSending(db);
  175. }
  176. return res;
  177. }
  178. }
  179. public void CreateRole(string name)
  180. {
  181. using (var db = new SecurityDatabaseDataContext(_connectionString))
  182. {
  183. var role = new Role {Name = name};
  184. db.Roles.InsertOnSubmit(role);
  185. db.SubmitChanges();
  186. }
  187. }
  188. public void DeleteRole(Guid id)
  189. {
  190. using (var db = new SecurityDatabaseDataContext(_connectionString))
  191. {
  192. Role role = db.Roles.GetOneOrjWorkflowException(id, "Роль", "");
  193. db.Roles.DeleteOnSubmit(role);
  194. db.SubmitChanges();
  195. }
  196. }
  197. public void SaveRole(Role role)
  198. {
  199. using (var db = new SecurityDatabaseDataContext(_connectionString))
  200. {
  201. var one = role.id == Guid.Empty ? new Role() : db.Roles.GetOneOrjWorkflowException(role.id, "Роль", role.Name);
  202. one.Name = role.Name;
  203. //Проверка циркуляции
  204. foreach (Role baseRole in role.BaseRoles)
  205. {
  206. Role currentRole = db.Roles.GetOneOrjWorkflowException(baseRole.id, "Роль", baseRole.Name);
  207. if (currentRole.GetAllRoles().Any(r => r.id == role.id))
  208. jWorkflowException.ThrowNew(
  209. "Невозможно сохранить роль, так как найдена циркулирующая ссылка. Для устранения конфликта необходимо исключить роль: " +
  210. baseRole.Name);
  211. }
  212. SynchronizePermissions(role, db, one);
  213. SynchronizeBaseRoles(role, db, one);
  214. db.SubmitChanges();
  215. }
  216. }
  217. #endregion
  218. public static void InitializejSLAuthorizationServiceBase(string connectionString)
  219. {
  220. jSLAuthorizationServiceBase.InitializeSecurity(new jDatabaseSecurityManager(connectionString));
  221. }
  222. internal static bool IsUserHasPermission(User user, int permission)
  223. {
  224. if (user == null) return false;
  225. return user.HasPermission(permission);
  226. }
  227. private void SynchronizeBaseRoles(Role source, SecurityDatabaseDataContext db, Role target)
  228. {
  229. //Удаляем несуществующее наследие
  230. IEnumerable<RoleInherit> toDel =
  231. target.RoleInherits1.Where(r => !source.BaseRoles.Any(br => br.id == r.ParentRoleId));
  232. if (toDel.Any())
  233. db.RoleInherits.DeleteAllOnSubmit(toDel);
  234. //Добавляем новое наследие
  235. IEnumerable<Role> toAdd =
  236. source.BaseRoles.Where(br => !target.RoleInherits1.Any(t => t.ParentRoleId == br.id));
  237. foreach (Role role in toAdd)
  238. {
  239. var roleInherit = new RoleInherit();
  240. roleInherit.ChildRole = target;
  241. roleInherit.ParentRole = db.Roles.GetOneOrjWorkflowException(role.id, "Роль", role.Name);
  242. db.RoleInherits.InsertOnSubmit(roleInherit);
  243. }
  244. }
  245. private static void SynchronizePermissions(Role source, SecurityDatabaseDataContext db, Role target)
  246. {
  247. IEnumerable<Permission> forDel =
  248. target.Permissions.Where(p => !source.PermissionCash.Any(c => c.Permission == p.PermissionNumber));
  249. if (forDel.Any())
  250. db.Permissions.DeleteAllOnSubmit(forDel);
  251. //добавляем те, которые не перечислены в цели
  252. IEnumerable<PermissionDescription> toAdd =
  253. source.PermissionCash.Where(pc => !target.Permissions.Any(p => p.PermissionNumber == pc.Permission));
  254. foreach (PermissionDescription description in toAdd)
  255. {
  256. var permission = new Permission {PermissionNumber = description.Permission, Role = target};
  257. db.Permissions.InsertOnSubmit(permission);
  258. }
  259. }
  260. }
  261. }