вторник, 17 июля 2012 г.

LinqToSharePoint & RunWithElevatedPriveledges

Итак проблема

SPSecurity.RunWithElevatedPriveledges игнорируется при использовании команд LinqToSharePoint, так как для выполнения команд в любом случае берется текущий контекст, SPContext.Current, если он не пуст. И только если мы выполняем команды вне веб-контекста, он сформирует контекст из наших данных.

Проблема решается, путем  «подсовывания» текущему контексту, того Web данных, который мы используем внутри RunWithoutPriveledges.

Делается это так:

1)      Запоминаем текущий веб-контекст
2)      Выполняем RunWithoutPriveledges
3)      Внутри открываем Site и Web
4)      Ассоциируем текущий контекст с новым Web
5)      Открываем DataContext LinqToSharePoint
6)      Выполняем все команды с повышенными правами
7)      Закрываем Web и Site
8)      Восстанавливаем веб-контекст из п.1


Техническая реализация описана в этой ссылке:




Вот класс-обертки для вызова
public class LinqToSPSecurity
{
  public static void RunWithElevatedPriveledges(SPWeb web, Action<SPWeb> action) 
  {
    Guid webId = web.ID;
    Guid siteId = web.Site.ID;

    HttpContext backupCtxt = HttpContext.Current;
    try
    {
      if (SPContext.Current != null)
        HttpContext.Current = null;
      SPSecurity.RunWithElevatedPrivileges(() =>
      {
        using (SPSite elevatedSite = new SPSite(siteId))
        {
          using (SPWeb elevatedWeb = elevatedSite.OpenWeb(webId))
          {
            HttpRequest httpRequest = new HttpRequest("", elevatedWeb.Url, "");
            HttpContext.Current = new HttpContext(httpRequest, new HttpResponse(new System.IO.StringWriter()));
            SPControl.SetContextWeb(HttpContext.Current, elevatedWeb);
            action(elevatedWeb);
          }
        }
      });
    }
    finally
    {
      if (SPContext.Current != null)
        HttpContext.Current = backupCtxt;
    }

  }

  public static void RunWithElevatedPriveledges(Action<SPWeb> action) 
  {
    RunWithElevatedPriveledges(SPContext.Current.Web, action);
  }
}

вторник, 3 июля 2012 г.

Yet Another Shitty Code (Говнокод 2)


/// <summary>
        /// Сохранение орг. звена
        /// </summary>
        /// <param name="orgUnit">Орг. звено</param>
        /// <param name="newchildren">Список идентификаторов добавляемых дочерних орг. единиц</param>
        /// <param name="deletechildren">Список идентификаторов удаляемых дочерних орг. единиц</param>
        /// <param name="newcustomers">Список идентификаторов добавляемых заказчиков</param>
        /// <param name="deletecustomers">Список идентификаторов удаляемых заказчиков</param>
        /// <param name="newemployees">Список идентификаторов добавляемых сотрудников</param>
        /// <param name="deleteemployees">Список идентификаторов удаляемых сотрудников</param>
            public void Save(OrgUnit orgUnit,
                  List<int> newchildren, List<int> deletechildren,
                  List<int> newcustomers, List<int> deletecustomers,
                  List<int> newemployees, List<int> deleteemployees)
            {
                  if (newchildren == null) newchildren = new List<int>();
                  if (newcustomers == null) newcustomers = new List<int>();
                  if (newemployees == null) newemployees = new List<int>();
                  if (deletechildren == null) deletechildren = new List<int>();
                  if (deletecustomers == null) deletecustomers = new List<int>();
                  if (deleteemployees == null) deleteemployees = new List<int>();

                  if (orgUnit.OrgUnitID == 0) // новая - создать
                  {
                L_UserActivityController.Write("Орг.звено", "Создание", orgUnit.Title);
                        DataContext.OrgUnits.InsertOnSubmit(orgUnit);
                  }

                  foreach (int id in newemployees)
                  {
                OUBind oldbins = App.DataContext.OUBinds.FirstOrDefault(b => b.EmployeeID == id &&
                    b.EndDate == null && b.BindType == 'M');
                if (oldbins != null)
                    oldbins.EndDate = DateTime.Now;

                oldbins = App.DataContext.OUBinds.FirstOrDefault(b => b.EmployeeID == id &&
                    b.EndDate == null && b.BindType == 'E');
                if (oldbins != null)
                    oldbins.EndDate = DateTime.Now;


                        OUBind eou = new OUBind();
                        eou.OrgUnit = orgUnit;
                        eou.EmployeeID = id;
                        eou.BeginDate = DateTime.Now;
                eou.BindType = 'M';
                        App.DataContext.OUBinds.InsertOnSubmit(eou);
                if (App.DataContext.EmployeeRoles.Count(r => r.EmployeeID == id && r.RoleCode == RoleEnum.Employee.ToString()) == 0)
                {
                    EmployeeRole er = new EmployeeRole { EmployeeID = id, RoleCode = RoleEnum.Employee.ToString() };
                    App.DataContext.EmployeeRoles.InsertOnSubmit(er);
                }
                  }

                  if (deleteemployees.Count > 0)
                  {
                        List<OUBind> eoudel = DataContext.OUBinds.Where(
                             eou => deleteemployees.Contains(eou.EmployeeID) &&
                                   eou.OrgUnitID == orgUnit.OrgUnitID).ToList();
                foreach (var b in eoudel)
                    b.EndDate = DateTime.Now;
                  }

                  if (orgUnit.BranchID == null) // сохранение филиалов
                  {
                        foreach (int id in newchildren)
                        {
                             OrgUnit o = new OrgUnit();
                             o.Affiliation = orgUnit.Affiliation;
                             o.BranchID = id;
                             o.IsActive = true;
                    L_UserActivityController.Write("Орг.звено", "Создание", orgUnit.Title + " / " + GetAdminUnit(id).Title);
                             DataContext.OrgUnits.InsertOnSubmit(o);
                        }

                        if (deletechildren.Count > 0)
                        {
                             List<OrgUnit> oudel = DataContext.OrgUnits.Where(ou =>
                                   ou.AffiliationID == orgUnit.AffiliationID &&
                                   ou.BranchID.HasValue &&
                                   !ou.FuncDirectionID.HasValue &&
                                   !ou.ActivityCategoryID.HasValue &&
                                   !ou.RegionID.HasValue &&
                                   !ou.DepartmentID.HasValue &&
                                   !ou.GroupID.HasValue &&
                                   deletechildren.Contains(ou.BranchID ?? 0)
                                   ).ToList();
                    foreach (var ou in oudel)
                    {
                        L_UserActivityController.Write("Орг.звено", "Удаление", ou.Title);
                        ou.IsActive = false;
                        DeleteChild(ou);
                    }
                        }
                  }
                  else if (orgUnit.FuncDirectionID == null) // сохранение функциональных направлений
                  {
                        foreach (int id in newchildren)
                        {
                             OrgUnit o = new OrgUnit();
                             o.Affiliation = orgUnit.Affiliation;
                             o.Branch = orgUnit.Branch;
                             o.FuncDirectionID = id;
                             o.IsActive = true;
                    L_UserActivityController.Write("Орг.звено", "Создание", orgUnit.Title + " / " + GetAdminUnit(id).Title);
                             DataContext.OrgUnits.InsertOnSubmit(o);
                        }

                        if (deletechildren.Count > 0)
                        {
                             List<OrgUnit> oudel = DataContext.OrgUnits.Where(ou =>
                                   ou.AffiliationID == orgUnit.AffiliationID &&
                                   ou.BranchID == orgUnit.BranchID &&
                                   ou.FuncDirectionID.HasValue &&
                                   !ou.ActivityCategoryID.HasValue &&
                                   !ou.RegionID.HasValue &&
                                   !ou.DepartmentID.HasValue &&
                                   !ou.GroupID.HasValue &&
                                   deletechildren.Contains(ou.FuncDirectionID ?? 0)
                                   ).ToList();
                    foreach (var ou in oudel)
                    {
                        L_UserActivityController.Write("Орг.звено", "Удаление", ou.Title);
                        ou.IsActive = false;
                        DeleteChild(ou);
                    }
                        }
                  }
                  else if (orgUnit.ActivityCategoryID == null) // сохранение видов деятельности
                  {
                        foreach (int id in newchildren)
                        {
                             OrgUnit o = new OrgUnit();
                             o.Affiliation = orgUnit.Affiliation;
                             o.Branch = orgUnit.Branch;
                             o.FuncDirection = orgUnit.FuncDirection;
                             o.ActivityCategoryID = id;
                             o.IsActive = true;
                    L_UserActivityController.Write("Орг.звено", "Создание", orgUnit.Title + " / " + GetAdminUnit(id).Title);
                             DataContext.OrgUnits.InsertOnSubmit(o);
                        }

                        if (deletechildren.Count > 0)
                        {
                             List<OrgUnit> oudel = DataContext.OrgUnits.Where(ou =>
                                   ou.AffiliationID == orgUnit.AffiliationID &&
                                   ou.BranchID == orgUnit.BranchID &&
                                   ou.FuncDirectionID == orgUnit.FuncDirectionID &&
                                   ou.ActivityCategoryID.HasValue &&
                                   !ou.RegionID.HasValue &&
                                   !ou.DepartmentID.HasValue &&
                                   !ou.GroupID.HasValue &&
                                   deletechildren.Contains(ou.ActivityCategoryID ?? 0)
                                   ).ToList();
                    foreach (var ou in oudel)
                    {
                        L_UserActivityController.Write("Орг.звено", "Удаление", ou.Title);
                        ou.IsActive = false;
                        DeleteChild(ou);
                    }
                        }
                  }
                  else if (orgUnit.RegionID == null) // сохранение регионов
                  {
                        foreach (int id in newchildren)
                        {
                              OrgUnit o = new OrgUnit();
                             o.Affiliation = orgUnit.Affiliation;
                             o.Branch = orgUnit.Branch;
                             o.FuncDirection = orgUnit.FuncDirection;
                             o.ActivityCategory = orgUnit.ActivityCategory;
                             o.RegionID = id;
                             o.IsActive = true;
                    L_UserActivityController.Write("Орг.звено", "Создание", orgUnit.Title + " / " + GetAdminUnit(id).Title);
                             DataContext.OrgUnits.InsertOnSubmit(o);
                        }

                        if (deletechildren.Count > 0)
                        {
                             List<OrgUnit> oudel = DataContext.OrgUnits.Where(ou =>
                                   ou.AffiliationID == orgUnit.AffiliationID &&
                                   ou.BranchID == orgUnit.BranchID &&
                                   ou.FuncDirectionID == orgUnit.FuncDirectionID &&
                                   ou.ActivityCategoryID == orgUnit.ActivityCategoryID &&
                                   ou.RegionID.HasValue &&
                                   !ou.DepartmentID.HasValue &&
                                   !ou.GroupID.HasValue &&
                                   deletechildren.Contains(ou.RegionID ?? 0)
                                   ).ToList();
                    foreach (var ou in oudel)
                    {
                        L_UserActivityController.Write("Орг.звено", "Удаление", ou.Title);
                        ou.IsActive = false;
                        DeleteChild(ou);
                    }
                        }

                        foreach (int id in newcustomers)
                        {
                             CustomerOrgUnit cou = new CustomerOrgUnit();
                             cou.OrgUnitID = orgUnit.OrgUnitID;
                             cou.CustomerID = id;
                             DataContext.CustomerOrgUnits.InsertOnSubmit(cou);
                        }

                        if (deletecustomers.Count > 0)
                        {
                             List<CustomerOrgUnit> coudel = DataContext.CustomerOrgUnits.Where(
                                   cou => deletecustomers.Contains(cou.CustomerID) &&
                                         cou.OrgUnitID == orgUnit.OrgUnitID).ToList();
                             DataContext.CustomerOrgUnits.DeleteAllOnSubmit(coudel);
                        }

                  }
                  else if (orgUnit.DepartmentID == null) // сохранение отделов
                  {
                        foreach (int id in newchildren)
                        {
                             OrgUnit o = new OrgUnit();
                             o.Affiliation = orgUnit.Affiliation;
                             o.Branch = orgUnit.Branch;
                             o.FuncDirection = orgUnit.FuncDirection;
                             o.ActivityCategory = orgUnit.ActivityCategory;
                             o.Region = orgUnit.Region;
                              o.DepartmentID = id;
                             o.IsActive = true;
                    L_UserActivityController.Write("Орг.звено", "Создание", orgUnit.Title + " / " + GetAdminUnit(id).Title);
                             DataContext.OrgUnits.InsertOnSubmit(o);
                        }

                        if (deletechildren.Count > 0)
                        {
                             List<OrgUnit> oudel = DataContext.OrgUnits.Where(ou =>
                                   ou.AffiliationID == orgUnit.AffiliationID &&
                                   ou.BranchID == orgUnit.BranchID &&
                                   ou.FuncDirectionID == orgUnit.FuncDirectionID &&
                                   ou.ActivityCategoryID == orgUnit.ActivityCategoryID &&
                                   ou.RegionID == orgUnit.RegionID &&
                                   ou.DepartmentID.HasValue &&
                                   !ou.GroupID.HasValue &&
                                   deletechildren.Contains(ou.DepartmentID ?? 0)
                                   ).ToList();
                    foreach (var ou in oudel)
                    {
                        L_UserActivityController.Write("Орг.звено", "Удаление", ou.Title);
                        ou.IsActive = false;
                        DeleteChild(ou);
                    }
                        }
                  }
                  else if (orgUnit.GroupID == null) // сохранение групп
                  {
                        foreach (int id in newchildren)
                        {
                             OrgUnit o = new OrgUnit();
                             o.Affiliation = orgUnit.Affiliation;
                             o.Branch = orgUnit.Branch;
                             o.FuncDirection = orgUnit.FuncDirection;
                             o.ActivityCategory = orgUnit.ActivityCategory;
                             o.Region = orgUnit.Region;
                             o.Department = orgUnit.Department;
                             o.GroupID = id;
                             o.IsActive = true;
                    L_UserActivityController.Write("Орг.звено", "Создание", orgUnit.Title + " / " + GetAdminUnit(id).Title);
                             DataContext.OrgUnits.InsertOnSubmit(o);
                        }

                        if (deletechildren.Count > 0)
                        {
                             List<OrgUnit> oudel = DataContext.OrgUnits.Where(ou =>
                                   ou.AffiliationID == orgUnit.AffiliationID &&
                                   ou.BranchID == orgUnit.BranchID &&
                                   ou.FuncDirectionID == orgUnit.FuncDirectionID &&
                                   ou.ActivityCategoryID == orgUnit.ActivityCategoryID &&
                                   ou.RegionID == orgUnit.RegionID &&
                                   ou.DepartmentID == orgUnit.DepartmentID &&
                                   ou.GroupID.HasValue &&
                                   deletechildren.Contains(ou.GroupID ?? 0)
                                   ).ToList();
                    foreach(var ou in oudel)
                    {
                        L_UserActivityController.Write("Орг.звено", "Удаление", ou.Title);
                        ou.IsActive = false;
                        DeleteChild(ou);
                    }
                        }
                  }

                  DataContext.SubmitChanges();
                  RedirectTo<OrgUnitController>(c => c.Edit(orgUnit.OrgUnitID));
            }