Project Server Online CSOM - GeneralSecurityAccessDenied при чтении назначений временных интервалов

Это мой первый вопрос, поэтому, пожалуйста, дайте мне знать, если этот вопрос не очень ясен или я что-то упускаю.

К вашему сведению, я не смог прикрепить ссылки, так что извините за все плохое форматирование.

обзор

Я пытаюсь прочитать (и написать) "Фактическую работу" для ресурса в Project Server Online с помощью библиотеки CSOM, доступной Microsoft. Чтение и запись заданий и фактическая работа работают отлично, пока я читаю задания для текущего аутентифицированного пользователя. Если я пытаюсь прочитать это для другого ресурса, я получаю ошибку GeneralSecurityAccessDenied.

Я делал это в прошлом, используя Impersonation, которая должна прозрачно вызываться в фоновом режиме, если у пользователя есть StatusBrokerPermission, но, похоже, он не работает для меня. Олицетворение было удалено в 2013+, так что это больше не вариант.

Краткое описание проблемы

Предполагается, что CSOM прозрачно разрешает расширения статусирования, чтобы можно было выполнять обновления статуса для ресурсов, отличных от аутентифицированного в данный момент пользователя (если пользователь имеет разрешение посредника статуса). Это прекрасно работает для добавления новых назначений, но не работает при попытке обновить фактические часы TimePhased через назначения TimePhased. Назначения не могут быть запрошены, и поэтому мы не можем вызвать SubmitAllStatusUpdates для отправки часов.

Исследование

  1. Сценарии использования для CSOM: https:// msdn.microsoft.com/en-us/library/office/jj163082(v=office.15).aspx#pj15_WhatTheCSOM_UsageScenarios

  2. Олицетворение устарело: https:// msdn.microsoft.com/en-us/library/office/ee767690(v=office.15).aspx#pj15_WhatsNew_Deprecated)

Картинка: Предполагается, что читать от имени другого пользователя...

  1. Люди с такой же проблемой # 1: https:// social.technet.microsoft.com/Forums/projectserver/en-US/dccdb543-18a1-4a0e-a948-5d861305516e/how-to-get-resource-assignments-summary- вид-данные проект-сервер онлайн-2013? форум =projectonline)

  2. Люди с такой же проблемой # 2: http:// uzzai.com/ZB43wp95/ps2013-app-how-to-read-and-update-timephased-data-with-jsom-javascript-csom.html

  3. Люди с такой же проблемой # 4: https:// social.technet.microsoft.com/Forums/Sharepoint/en-US/be27d497-e959-44b6-97cb-8f19fe0278fe/csom-how-to-set-timephase-data- на ан-задания? форум =project2010custprog

Другие вещи, которые я пробовал

  1. Использование CSOM с MsOnlineClaimsHelper для получения файлов cookie FedAuth для пользователя (и назначение их с помощью CookieContainer).
  2. Использование REST/OData API. a) https:// URL.sharepoint.com/sites/pwa/_api/ProjectServer/EnterpriseResources('c39ba8f1-00fe-e311-8894-00155da45f0e')/Assignments/GetTimePhaseByUrl(start='2014-12-09',end='2014-12-09')/ задания
  3. Включение "StatusBrokerPermission" для пользователя
  4. Снимите флажок "Разрешить обновления задач только через задачи и расписания". На экране настроек сервера (настройки и отображение задач).
  5. Создание приложения на базе SharePoint и использование кода JSOM, эквивалентного приведенному выше коду CSOM. а) Код, который мы написали, был JavaScript, выполняемый из приложения SharePoint, поэтому нам не нужно было обеспечивать аутентификацию. Пользователь, вошедший в систему, имел StatusBrokerPermission.
  6. Использование размещенного на провайдере приложения SharePoint и приведенного выше кода CSOM. Мы попытались использовать все методы аутентификации для CSOM, описанные выше, с дополнительным тестом: a) с помощью Fiddler для просмотра файлов cookie FedAuth, устанавливаемых аутентификацией приложения SharePoint, и переопределив веб-запрос для ручной вставки файлов cookie FedAuth/rtFA: webRequestEventArgs.WebRequestExecutor.WebRequest.CookieContainer = getStaticCookieContainer();
  7. Использование расписаний для подачи поэтапных данных. a) Мы можем создать расписание только для аутентифицированного в данный момент пользователя и не можем заполнять строки расписания не доступными ему проектами / назначениями (или генерируется ошибка GeneralItemDoesNotExist).
  8. Выполнение запроса CSOM "SubmitAllStatusUpdates" вручную с использованием fiddler от имени другого пользователя. а) Цель этого теста состояла в том, чтобы определить, можем ли мы записать данные с временной фазой, даже если мы не можем их прочитать.
  9. Убедиться, что проект был проверен для текущего пользователя.
  10. Использование административного делегирования для ресурса.
  11. Настройка всех доступных параметров в рамках разрешений проекта.
  12. Использование веб-интерфейса Project для ввода данных TimePhased для других ресурсов.
  13. Использование режима разрешений SharePoint вместо режима разрешений проекта.

Код

Смотрите скриншот с ошибкой кода здесь

    using System;
    using System.Security;
    using Microsoft.ProjectServer.Client;
    using Microsoft.SharePoint.Client;
    namespace ProjectOnlineActuals
    {
        static class Program
        {
            const string projectSite = "https://URL.sharepoint.com/sites/pwa/";
            private const string edward = "c39ba8f1-00fe-e311-8894-00155da45f0e";
            private const string admin = "8b1bcfa4-1b7f-e411-af75-00155da4630b";

            static void Main(string[] args)
            {
                TestActuals();
            }

            private static void TestActuals()
            {
                Console.WriteLine("Attempting test # 1 (login: admin, resource: admin)");
                TestActuals("admin@URL.onmicrosoft.com", "123", admin);

                Console.WriteLine("Attempting test # 2 (login: admin, resource: edward)");
                TestActuals("adminy@hmssoftware.onmicrosoft.com", "123", edward);
                Console.ReadLine();
            }

            private static void TestActuals(string username, string password, string resourceID)
            {
                try
                {
                    using (ProjectContext context = new ProjectContext(projectSite))
                    {
                        DateTime startDate = DateTime.Now.Date;
                        DateTime endDate = DateTime.Now.Date;
                        Login(context, username, password);
                        context.Load(context.Web); // Query for Web
                        context.ExecuteQuery(); // Execute

                        Guid gResourceId = new Guid(resourceID);
                        EnterpriseResource enterpriseResource = context.EnterpriseResources.GetByGuid(gResourceId);
                        context.Load(enterpriseResource, p => p.Name, p => p.Assignments, p => p.Email);
                        Console.Write("Loading resource...");
                        context.ExecuteQuery();
                        Console.WriteLine("done! {0}".FormatWith(enterpriseResource.Name));

                        Console.Write("Adding new resource assignment to collection...");
                        enterpriseResource.Assignments.Add(new StatusAssignmentCreationInformation
                        {
                            Comment = "testing comment - 2016-02-17",
                            ProjectId = new Guid("27bf182c-2339-e411-8e76-78e3b5af0525"),

                            Task = new StatusTaskCreationInformation
                            {
                                Start = DateTime.Now,
                                Finish = DateTime.Now.AddDays(2),
                                Name = "testing - 2016-02-17",
                            }
                        });
                        Console.WriteLine("done!");

                        Console.Write("Trying to save new resource assignment...");
                        enterpriseResource.Assignments.Update();
                        context.ExecuteQuery();
                        Console.WriteLine("done!");

                        Console.Write("Loading TimePhase...");
                        TimePhase timePhase = enterpriseResource.Assignments.GetTimePhase(startDate.Date, endDate.Date);
                        context.ExecuteQuery();
                        Console.WriteLine("done!");

                        Console.Write("Loading TimePhase assignments...");
                        context.Load(timePhase.Assignments);
                        context.ExecuteQuery();
                        Console.WriteLine("done! Found {0} assignments.".FormatWith(timePhase.Assignments.Count));

                        Console.WriteLine("Updating TimePhase assignments...");
                        foreach (var assignment in timePhase.Assignments)
                        {
                            Console.WriteLine("Updating assignment: {0}. ActualWork: {1}".FormatWith(assignment.Name, assignment.ActualWork));
                            assignment.ActualWork = "9h";
                            assignment.RegularWork = "3h";
                            assignment.RemainingWork = "0h";
                        }
                        timePhase.Assignments.SubmitAllStatusUpdates("Status update comment test 2016-02-17");
                        context.ExecuteQuery();
                        Console.WriteLine("done!");

                        Console.WriteLine("Success (retrieved & updated {0} time phase assignments)!".FormatWith(timePhase.Assignments.Count));
                    }
                }
                catch (Exception ex)
                {
                    if (ex.ToString().Contains("GeneralSecurityAccessDenied"))
                        Console.WriteLine("ERROR! - GeneralSecurityAccessDenied");
                    else
                        throw;
                }
                finally
                {
                    Console.WriteLine();
                    Console.WriteLine();
                }
            }

            private static void Login(ProjectContext projContext, string username, string password)
            {
                var securePassword = new SecureString();
                foreach (char c in password)
                    securePassword.AppendChar(c);

                projContext.Credentials = new SharePointOnlineCredentials(username, securePassword);
            }

            static string FormatWith(this string str, params object[] args)
            {
                return String.Format(str, args);
            }
        }
    }

Может кто-нибудь помочь??

0 ответов

Другие вопросы по тегам