/jSLCore/jSLCore/jSLCore.Service/Security/jDatabaseSecurityManager.cs
C# | 305 lines | 240 code | 44 blank | 21 comment | 23 complexity | 40191a7f4c03233bb52bc35e968e5c0a MD5 | raw file
- using System;
- using System.Collections.Generic;
- using System.Data.Linq;
- using System.Linq;
- using jSLCore.Service.Workflow;
- using jSLCore.Service.Workflow.Linq;
-
- namespace jSLCore.Service.Security
- {
- /// <summary>
- /// Security based on jDatabase sql database
- /// </summary>
- // ReSharper disable InconsistentNaming
- public class jDatabaseSecurityManager : ISecurityManager
- // ReSharper restore InconsistentNaming
- , IPermissionDescriptionProvider
- , IEnumDescriptionProvider
- , ISuperVisorManager
- , IPasswordManager
- {
- private readonly string _connectionString;
-
- public jDatabaseSecurityManager(string connectionString)
- {
- _connectionString = connectionString;
- }
-
- #region IEnumDescriptionProvider Members
-
- public EnumDescription[] GetAllEnumDescriptions()
- {
- using (var db = new SecurityDatabaseDataContext(_connectionString))
- {
- return db.EnumDescriptions.ToArray();
- }
- }
-
- #endregion
-
- #region IPasswordManager Members
-
- public void ChangeCurrentUserPassword(string userName, string oldPwd, string newPwd)
- {
- using (var db = new SecurityDatabaseDataContext(_connectionString))
- {
- var user = db.Users.GetUserByLoginAndPwdOrNull(userName, oldPwd);
- if (user == null)
- {
- jWorkflowException.ThrowNew(
- "Пользователь с указанным именем и паролем не найден. Возможно пароль введен не правильно");
- throw new InvalidProgramException();
- }
- user.Password = new Binary(jSLAuthorizationServiceBase.GetPasswordHash(newPwd));
- db.SubmitChanges();
- }
- }
-
- #endregion
-
- #region IPermissionDescriptionProvider Members
-
- public PermissionDescription[] GetAllPermissionDescriptions()
- {
- using (var db = new SecurityDatabaseDataContext(_connectionString))
- {
- return db.PermissionDescriptions.ToArray();
- }
- }
-
- #endregion
-
- #region ISecurityManager Members
-
- public User Authorize(string login, string password)
- {
- using (var db = new SecurityDatabaseDataContext(_connectionString))
- {
- User user = null;
- try
- {
- user = db.Users.GetUserByLoginAndPwdOrNull(login, password);
-
- if (user == null) throw new InvalidOperationException();
- //user = new User(){IsEnabled = true,Login = loginName,Password = pwdHash};//создаем пользователя
- }
- catch (InvalidOperationException)
- {
- jWorkflowException.ThrowNew("Имя пользователя или пароль введены неправильно");
- }
-
- //db.Users.InsertOnSubmit(user);
- //db.SubmitChanges();
-
- // ReSharper disable PossibleNullReferenceException
- if (!user.IsEnabled)
- jWorkflowException.ThrowNew("Ваш аккаунт заблокирован. Обратитесь к администратору.");
- // ReSharper restore PossibleNullReferenceException
-
- Guid remeberCode = Guid.NewGuid(); //everytime user auth by login/pwd.. the remebercode will be reseted
- user.RemeberCode = remeberCode;
- db.SubmitChanges();
- db.Refresh(RefreshMode.OverwriteCurrentValues, user);
- return user;
- }
- }
-
- public User AuthorizeByCode(Guid code)
- {
- using (var db = new SecurityDatabaseDataContext(_connectionString))
- {
- User user;
- try
- {
- user = db.Users.SingleOrDefault(u => u.RemeberCode == code);
-
- if (user == null) throw new InvalidOperationException();
- //user = new User(){IsEnabled = true,Login = loginName,Password = pwdHash};//создаем пользователя
- }
- catch (InvalidOperationException)
- {
- //jWorkflowException.ThrowNew("Невозможно авторизоваться"); do nothing... user is out of login silently
- return null;
- }
-
- //db.Users.InsertOnSubmit(user);
- //db.SubmitChanges();
- if (!user.IsEnabled)
- {
- //jWorkflowException.ThrowNew("Ваш аккаунт заблокирован. Обратитесь к администратору."); check upper comment
- return null;
- }
- return user;
- }
- }
-
- public int[] GetPermissionSet(string userName)
- {
- using (var db = new SecurityDatabaseDataContext(_connectionString))
- {
- User user = db.Users.GetOneOrNull(userName, "Login");
- if (user == null) return new int[0];
- return user.GetPermissionSet();
- }
- }
-
- public User GetUser(string login)
- {
- using (var db = new SecurityDatabaseDataContext(_connectionString))
- {
- User user = db.Users.GetOneOrjWorkflowException(login, "Пользователь", login, "Login");
- return user;
- }
- }
-
- public bool IsUserHasPermission(string userName, int permission)
- {
- using (var db = new SecurityDatabaseDataContext(_connectionString))
- {
- User user = db.Users.SingleOrDefault(u => u.Login == userName);
- return IsUserHasPermission(user, permission);
- }
- }
-
- #endregion
-
- #region ISuperVisorManager Members
-
- public PermissionDescription[] GetInheritedPermissions(Guid roleId)
- {
- using (var db = new SecurityDatabaseDataContext(_connectionString))
- {
- Role role = db.Roles.GetOneOrjWorkflowException(roleId, "Роль", "");
-
- IEnumerable<Permission> permissions = role
- .GetAllRoles()
- .SelectMany(r => r.Permissions)
- .Distinct();
-
- return permissions
- // ReSharper disable AccessToDisposedClosure
- .Select(p => db.PermissionDescriptions.GetOne(p.PermissionNumber, "Permission"))
- // ReSharper restore AccessToDisposedClosure
- .ToArray();
- }
- }
-
- public Role GetRole(Guid id)
- {
- using (var db = new SecurityDatabaseDataContext(_connectionString))
- {
- Role role = db.Roles.GetOneOrjWorkflowException(id, "Роль", "");
- role.BeforeSending(db);
- return role;
- }
- }
-
- public Role[] SearchRoles(string searchText)
- {
- using (var db = new SecurityDatabaseDataContext(_connectionString))
- {
- Role[] res = db.Roles.Where(r => r.Name.Contains(searchText)).ToArray();
- foreach (Role role in res)
- {
- role.BeforeSending(db);
- }
- return res;
- }
- }
-
- public void CreateRole(string name)
- {
- using (var db = new SecurityDatabaseDataContext(_connectionString))
- {
- var role = new Role {Name = name};
- db.Roles.InsertOnSubmit(role);
- db.SubmitChanges();
- }
- }
-
- public void DeleteRole(Guid id)
- {
- using (var db = new SecurityDatabaseDataContext(_connectionString))
- {
- Role role = db.Roles.GetOneOrjWorkflowException(id, "Роль", "");
- db.Roles.DeleteOnSubmit(role);
- db.SubmitChanges();
- }
- }
-
- public void SaveRole(Role role)
- {
- using (var db = new SecurityDatabaseDataContext(_connectionString))
- {
- var one = role.id == Guid.Empty ? new Role() : db.Roles.GetOneOrjWorkflowException(role.id, "Роль", role.Name);
-
- one.Name = role.Name;
-
- //Проверка циркуляции
- foreach (Role baseRole in role.BaseRoles)
- {
- Role currentRole = db.Roles.GetOneOrjWorkflowException(baseRole.id, "Роль", baseRole.Name);
-
- if (currentRole.GetAllRoles().Any(r => r.id == role.id))
- jWorkflowException.ThrowNew(
- "Невозможно сохранить роль, так как найдена циркулирующая ссылка. Для устранения конфликта необходимо исключить роль: " +
- baseRole.Name);
- }
-
- SynchronizePermissions(role, db, one);
- SynchronizeBaseRoles(role, db, one);
-
- db.SubmitChanges();
- }
- }
-
- #endregion
-
- public static void InitializejSLAuthorizationServiceBase(string connectionString)
- {
- jSLAuthorizationServiceBase.InitializeSecurity(new jDatabaseSecurityManager(connectionString));
- }
-
- internal static bool IsUserHasPermission(User user, int permission)
- {
- if (user == null) return false;
- return user.HasPermission(permission);
- }
-
- private void SynchronizeBaseRoles(Role source, SecurityDatabaseDataContext db, Role target)
- {
- //Удаляем несуществующее наследие
- IEnumerable<RoleInherit> toDel =
- target.RoleInherits1.Where(r => !source.BaseRoles.Any(br => br.id == r.ParentRoleId));
- if (toDel.Any())
- db.RoleInherits.DeleteAllOnSubmit(toDel);
- //Добавляем новое наследие
- IEnumerable<Role> toAdd =
- source.BaseRoles.Where(br => !target.RoleInherits1.Any(t => t.ParentRoleId == br.id));
-
- foreach (Role role in toAdd)
- {
- var roleInherit = new RoleInherit();
- roleInherit.ChildRole = target;
- roleInherit.ParentRole = db.Roles.GetOneOrjWorkflowException(role.id, "Роль", role.Name);
- db.RoleInherits.InsertOnSubmit(roleInherit);
- }
- }
-
- private static void SynchronizePermissions(Role source, SecurityDatabaseDataContext db, Role target)
- {
- IEnumerable<Permission> forDel =
- target.Permissions.Where(p => !source.PermissionCash.Any(c => c.Permission == p.PermissionNumber));
- if (forDel.Any())
- db.Permissions.DeleteAllOnSubmit(forDel);
- //добавляем те, которые не перечислены в цели
- IEnumerable<PermissionDescription> toAdd =
- source.PermissionCash.Where(pc => !target.Permissions.Any(p => p.PermissionNumber == pc.Permission));
- foreach (PermissionDescription description in toAdd)
- {
- var permission = new Permission {PermissionNumber = description.Permission, Role = target};
- db.Permissions.InsertOnSubmit(permission);
- }
- }
- }
- }