コード例 #1
0
        public static TokenParser ProcessThemes(Tenant tenant, ProvisioningTenant provisioningTenant, TokenParser parser, PnPMonitoredScope scope, ProvisioningMessagesDelegate messagesDelegate)
        {
            if (provisioningTenant.Themes != null && provisioningTenant.Themes.Any())
            {
                var themes = tenant.GetAllTenantThemes();
                tenant.Context.Load(themes);
                tenant.Context.ExecuteQueryRetry();

                foreach (var theme in provisioningTenant.Themes)
                {
                    var parsedName = parser.ParseString(theme.Name);
                    if (themes.FirstOrDefault(t => t.Name == parsedName) != null)
                    {
                        if (theme.Overwrite)
                        {
                            var parsedPalette = parser.ParseString(theme.Palette);

                            messagesDelegate?.Invoke($"Overwriting existing theme {parsedName}", ProvisioningMessageType.Progress);

                            var palette     = JsonConvert.DeserializeObject <Dictionary <string, string> >(parsedPalette);
                            var tenantTheme = new TenantTheme()
                            {
                                Name = parsedName, Palette = palette, IsInverted = theme.IsInverted
                            };
                            tenant.UpdateTenantTheme(parsedName, JsonConvert.SerializeObject(tenantTheme));
                            tenant.Context.ExecuteQueryRetry();
                        }
                        else
                        {
                            messagesDelegate?.Invoke($"Skipped processing theme {parsedName} as it already exists and Overwrite is set to false", ProvisioningMessageType.Progress);
                        }
                    }
                    else
                    {
                        var parsedPalette = parser.ParseString(theme.Palette);

                        messagesDelegate?.Invoke($"Processing theme {parsedName}", ProvisioningMessageType.Progress);

                        var palette     = JsonConvert.DeserializeObject <Dictionary <string, string> >(parsedPalette);
                        var tenantTheme = new TenantTheme()
                        {
                            Name = parsedName, Palette = palette, IsInverted = theme.IsInverted
                        };
                        tenant.AddTenantTheme(parsedName, JsonConvert.SerializeObject(tenantTheme));
                        tenant.Context.ExecuteQueryRetry();
                    }
                }
            }
            return(parser);
        }
コード例 #2
0
        internal static TokenParser ProcessSiteScripts(Tenant tenant, ProvisioningTenant provisioningTenant, FileConnectorBase connector, TokenParser parser, PnPMonitoredScope scope, ProvisioningMessagesDelegate messagesDelegate)
        {
            if (provisioningTenant.SiteScripts != null && provisioningTenant.SiteScripts.Any())
            {
                var existingScripts = tenant.GetSiteScripts();
                tenant.Context.Load(existingScripts);
                tenant.Context.ExecuteQueryRetry();

                foreach (var siteScript in provisioningTenant.SiteScripts)
                {
                    var parsedTitle       = parser.ParseString(siteScript.Title);
                    var parsedDescription = parser.ParseString(siteScript.Description);
                    var parsedContent     = parser.ParseString(System.Text.Encoding.UTF8.GetString(ConnectorFileHelper.GetFileBytes(connector, parser.ParseString(siteScript.JsonFilePath))));
                    var existingScript    = existingScripts.FirstOrDefault(s => s.Title == parsedTitle);

                    messagesDelegate?.Invoke($"Processing site script {parsedTitle}", ProvisioningMessageType.Progress);

                    if (existingScript == null)
                    {
                        TenantSiteScriptCreationInfo siteScriptCreationInfo = new TenantSiteScriptCreationInfo
                        {
                            Title       = parsedTitle,
                            Description = parsedDescription,
                            Content     = parsedContent
                        };
                        var script = tenant.CreateSiteScript(siteScriptCreationInfo);
                        tenant.Context.Load(script);
                        tenant.Context.ExecuteQueryRetry();
                        parser.AddToken(new SiteScriptIdToken(null, parsedTitle, script.Id));
                    }
                    else
                    {
                        if (siteScript.Overwrite)
                        {
                            var existingId = existingScript.Id;
                            existingScript = Tenant.GetSiteScript(tenant.Context, existingId);
                            tenant.Context.ExecuteQueryRetry();

                            existingScript.Content     = parsedContent;
                            existingScript.Title       = parsedTitle;
                            existingScript.Description = parsedDescription;
                            tenant.UpdateSiteScript(existingScript);
                            tenant.Context.ExecuteQueryRetry();
                            var existingToken = parser.Tokens.OfType <SiteScriptIdToken>().FirstOrDefault(t => t.GetReplaceValue() == existingId.ToString());
                            if (existingToken != null)
                            {
                                parser.Tokens.Remove(existingToken);
                            }
                            parser.AddToken(new SiteScriptIdToken(null, parsedTitle, existingId));
                        }
                    }
                }
            }
            return(parser);
        }
コード例 #3
0
        public static TokenParser ProcessWebApiPermissions(Tenant tenant, ProvisioningTenant provisioningTenant, TokenParser parser, PnPMonitoredScope scope, ProvisioningMessagesDelegate messagesDelegate)
        {
            if (provisioningTenant.WebApiPermissions != null && provisioningTenant.WebApiPermissions.Any())
            {
                messagesDelegate?.Invoke("Processing WebApiPermissions", ProvisioningMessageType.Progress);
                var servicePrincipal = new SPOWebAppServicePrincipal(tenant.Context);
                //var requests = servicePrincipal.PermissionRequests;
                var requestsEnumerable = tenant.Context.LoadQuery(servicePrincipal.PermissionRequests);
                var grantsEnumerable   = tenant.Context.LoadQuery(servicePrincipal.PermissionGrants);
                tenant.Context.ExecuteQueryRetry();

                var requests = requestsEnumerable.ToList();

                foreach (var permission in provisioningTenant.WebApiPermissions)
                {
                    var parsedScope    = parser.ParseString(permission.Scope);
                    var parsedResource = parser.ParseString(permission.Resource);
                    var request        = requests.FirstOrDefault(r => r.Scope.Equals(parsedScope, StringComparison.InvariantCultureIgnoreCase) && r.Resource.Equals(parsedResource, StringComparison.InvariantCultureIgnoreCase));
                    while (request != null)
                    {
                        if (grantsEnumerable.FirstOrDefault(g => g.Resource.Equals(parsedResource, StringComparison.InvariantCultureIgnoreCase) && g.Scope.ToLower().Contains(parsedScope.ToLower())) == null)
                        {
                            var requestToApprove = servicePrincipal.PermissionRequests.GetById(request.Id);
                            tenant.Context.Load(requestToApprove);
                            tenant.Context.ExecuteQueryRetry();
                            try
                            {
                                requestToApprove.Approve();
                                tenant.Context.ExecuteQueryRetry();
                            }
                            catch (Exception ex)
                            {
                                messagesDelegate?.Invoke(ex.Message, ProvisioningMessageType.Warning);
                            }
                        }
                        requests.Remove(request);
                        request = requests.FirstOrDefault(r => r.Scope.Equals(parsedScope, StringComparison.InvariantCultureIgnoreCase) && r.Resource.Equals(parsedResource, StringComparison.InvariantCultureIgnoreCase));
                    }
                }
            }
            return(parser);
        }
コード例 #4
0
        public static TokenParser ProcessThemes(Tenant tenant, ProvisioningTenant provisioningTenant, TokenParser parser, PnPMonitoredScope scope, ProvisioningMessagesDelegate messagesDelegate)
        {
            if (provisioningTenant.Themes != null && provisioningTenant.Themes.Any())
            {
                foreach (var theme in provisioningTenant.Themes)
                {
                    var parsedName    = parser.ParseString(theme.Name);
                    var parsedPalette = parser.ParseString(theme.Palette);

                    messagesDelegate?.Invoke($"Processing theme {parsedName}", ProvisioningMessageType.Progress);

                    var palette     = JsonConvert.DeserializeObject <Dictionary <string, string> >(parsedPalette);
                    var tenantTheme = new TenantTheme()
                    {
                        Name = parsedName, Palette = palette, IsInverted = theme.IsInverted
                    };
                    tenant.UpdateTenantTheme(parsedName, JsonConvert.SerializeObject(tenantTheme));
                    tenant.Context.ExecuteQueryRetry();
                }
            }
            return(parser);
        }
コード例 #5
0
ファイル: TenantHelper.cs プロジェクト: wspelt/PnP-Sites-Core
        public static TokenParser ProcessUserProfiles(Tenant tenant, ProvisioningTenant provisioningTenant, TokenParser parser, PnPMonitoredScope scope, ProvisioningMessagesDelegate messagesDelegate)
        {
            if (provisioningTenant.SPUsersProfiles != null && provisioningTenant.SPUsersProfiles.Any())
            {
                messagesDelegate?.Invoke("Processing User Profiles", ProvisioningMessageType.Progress);

                foreach (var profile in provisioningTenant.SPUsersProfiles)
                {
                    string parsedUser;
                    if (!string.IsNullOrEmpty(profile.TargetUser))
                    {
                        parsedUser = parser.ParseString(profile.TargetUser);
                    }
                    else
                    {
                        parsedUser = parser.ParseString(profile.TargetGroup);
                    }

                    PeopleManager peopleManager = new PeopleManager(tenant.Context);
                    try
                    {
                        // Currently only supports setting Single Valued property
                        // We don't have a way at the moment to set Multi-valued property
                        foreach (var props in profile.Properties)
                        {
                            peopleManager.SetSingleValueProfileProperty($"i:0#.f|membership|{parsedUser}", props.Key, parser.ParseString(props.Value));
                        }
                        tenant.Context.ExecuteQueryRetry();
                    }
                    catch (Exception ex)
                    {
                        scope.LogError($"Error processing user profile for {parsedUser}. Skipped due to error: ${ex.Message}");
                    }
                }
            }
            return(parser);
        }
コード例 #6
0
        public static TokenParser ProcessApps(Tenant tenant, ProvisioningTenant provisioningTenant, FileConnectorBase connector, TokenParser parser, PnPMonitoredScope scope, ProvisioningTemplateApplyingInformation applyingInformation, ProvisioningMessagesDelegate messagesDelegate)
        {
            if (provisioningTenant.AppCatalog != null && provisioningTenant.AppCatalog.Packages.Count > 0)
            {
                var rootSiteUrl = tenant.GetRootSiteUrl();
                tenant.Context.ExecuteQueryRetry();
                using (var context = ((ClientContext)tenant.Context).Clone(rootSiteUrl.Value, applyingInformation.AccessTokens))
                {
                    var web = context.Web;

                    Uri appCatalogUri = null;

                    try
                    {
                        appCatalogUri = web.GetAppCatalog();
                    }
                    catch (System.Net.WebException ex)
                    {
                        if (ex.Response != null)
                        {
                            var httpResponse = ex.Response as System.Net.HttpWebResponse;
                            if (httpResponse != null && httpResponse.StatusCode == HttpStatusCode.Unauthorized)
                            {
                                // Ignore any security exception and simply keep
                                // the AppCatalog URI null
                            }
                            else
                            {
                                throw ex;
                            }
                        }
                        else
                        {
                            throw ex;
                        }
                    }

                    if (appCatalogUri != null)
                    {
                        var manager = new AppManager(context);

                        foreach (var app in provisioningTenant.AppCatalog.Packages)
                        {
                            AppMetadata appMetadata = null;

                            if (app.Action == PackageAction.Upload || app.Action == PackageAction.UploadAndPublish)
                            {
                                var appSrc   = parser.ParseString(app.Src);
                                var appBytes = ConnectorFileHelper.GetFileBytes(connector, appSrc);

                                var hash = string.Empty;
                                using (var memoryStream = new MemoryStream(appBytes))
                                {
                                    hash = CalculateHash(memoryStream);
                                }

                                var exists = false;
                                var appId  = Guid.Empty;

                                using (var appCatalogContext = ((ClientContext)tenant.Context).Clone(appCatalogUri, applyingInformation.AccessTokens))
                                {
                                    // check if the app already is present
                                    var appList   = appCatalogContext.Web.GetListByUrl("AppCatalog");
                                    var camlQuery = new CamlQuery
                                    {
                                        ViewXml = string.Format(appExistsQuery, hash)
                                    };
                                    var items = appList.GetItems(camlQuery);
                                    appCatalogContext.Load(items, i => i.IncludeWithDefaultProperties());
                                    appCatalogContext.ExecuteQueryRetry();
                                    if (items.Count > 0)
                                    {
                                        exists = true;
                                        appId  = Guid.Parse(items[0].FieldValues["UniqueId"].ToString());
                                    }
                                }
                                var appFilename = appSrc.Substring(appSrc.LastIndexOf('\\') + 1);

                                if (!exists)
                                {
                                    messagesDelegate?.Invoke($"Processing solution {app.Src}", ProvisioningMessageType.Progress);
                                    appMetadata = manager.Add(appBytes, appFilename, app.Overwrite, timeoutSeconds: 500);
                                }
                                else
                                {
                                    messagesDelegate?.Invoke($"Skipping existing solution {app.Src}", ProvisioningMessageType.Progress);
                                    appMetadata = manager.GetAvailable().FirstOrDefault(a => a.Id == appId);
                                }
                                if (appMetadata != null)
                                {
                                    parser.AddToken(new AppPackageIdToken(web, appFilename, appMetadata.Id));
                                    parser.AddToken(new AppPackageIdToken(web, appMetadata.Title, appMetadata.Id));
                                }
                            }

                            if (app.Action == PackageAction.Publish || app.Action == PackageAction.UploadAndPublish)
                            {
                                if (appMetadata == null)
                                {
                                    appMetadata = manager.GetAvailable()
                                                  .FirstOrDefault(a => a.Id == Guid.Parse(parser.ParseString(app.PackageId)));
                                }
                                if (appMetadata != null)
                                {
                                    manager.Deploy(appMetadata, app.SkipFeatureDeployment);
                                }
                                else
                                {
                                    scope.LogError("Referenced App Package {0} not available", app.PackageId);
                                    throw new Exception($"Referenced App Package {app.PackageId} not available");
                                }
                            }

                            if (app.Action == PackageAction.Remove)
                            {
                                var appId = Guid.Parse(parser.ParseString(app.PackageId));

                                // Get the apps already installed in the site
                                var appExists = manager.GetAvailable()?.Any(a => a.Id == appId);

                                if (appExists.HasValue && appExists.Value)
                                {
                                    manager.Remove(appId);
                                }
                                else
                                {
                                    messagesDelegate?.Invoke($"App Package with ID {appId} does not exist in the AppCatalog and cannot be removed!", ProvisioningMessageType.Warning);
                                }
                            }
                        }
                    }
                    else
                    {
                        messagesDelegate?.Invoke($"Tenant app catalog doesn't exist. ALM step will be skipped!", ProvisioningMessageType.Warning);
                    }
                }
            }
            return(parser);
        }
コード例 #7
0
        public static TokenParser ProcessSiteDesigns(Tenant tenant, ProvisioningTenant provisioningTenant, TokenParser parser, PnPMonitoredScope scope, ProvisioningMessagesDelegate messagesDelegate)
        {
            if (provisioningTenant.SiteDesigns != null && provisioningTenant.SiteDesigns.Any())
            {
                var existingDesigns = tenant.GetSiteDesigns();
                tenant.Context.Load(existingDesigns);
                tenant.Context.ExecuteQueryRetry();
                foreach (var siteDesign in provisioningTenant.SiteDesigns)
                {
                    var parsedTitle               = parser.ParseString(siteDesign.Title);
                    var parsedDescription         = parser.ParseString(siteDesign.Description);
                    var parsedPreviewImageUrl     = parser.ParseString(siteDesign.PreviewImageUrl);
                    var parsedPreviewImageAltText = parser.ParseString(siteDesign.PreviewImageAltText);
                    messagesDelegate?.Invoke($"Processing site design {parsedTitle}", ProvisioningMessageType.Progress);

                    var existingSiteDesign = existingDesigns.FirstOrDefault(d => d.Title == parsedTitle);
                    if (existingSiteDesign == null)
                    {
                        TenantSiteDesignCreationInfo siteDesignCreationInfo = new TenantSiteDesignCreationInfo()
                        {
                            Title               = parsedTitle,
                            Description         = parsedDescription,
                            PreviewImageUrl     = parsedPreviewImageUrl,
                            PreviewImageAltText = parsedPreviewImageAltText,
                            IsDefault           = siteDesign.IsDefault,
                        };
                        switch ((int)siteDesign.WebTemplate)
                        {
                        case 0:
                        {
                            siteDesignCreationInfo.WebTemplate = "64";
                            break;
                        }

                        case 1:
                        {
                            siteDesignCreationInfo.WebTemplate = "68";
                            break;
                        }
                        }
                        if (siteDesign.SiteScripts != null && siteDesign.SiteScripts.Any())
                        {
                            List <Guid> ids = new List <Guid>();
                            foreach (var siteScriptRef in siteDesign.SiteScripts)
                            {
                                ids.Add(Guid.Parse(parser.ParseString(siteScriptRef)));
                            }
                            siteDesignCreationInfo.SiteScriptIds = ids.ToArray();
                        }
                        var design = tenant.CreateSiteDesign(siteDesignCreationInfo);
                        tenant.Context.Load(design);
                        tenant.Context.ExecuteQueryRetry();

                        if (siteDesign.Grants != null && siteDesign.Grants.Any())
                        {
                            foreach (var grant in siteDesign.Grants)
                            {
                                var rights = (TenantSiteDesignPrincipalRights)Enum.Parse(typeof(TenantSiteDesignPrincipalRights), grant.Right.ToString());
                                tenant.GrantSiteDesignRights(design.Id, new[] { grant.Principal }, rights);
                            }
                            tenant.Context.ExecuteQueryRetry();
                        }
                        parser.AddToken(new SiteDesignIdToken(null, design.Title, design.Id));
                    }
                    else
                    {
                        if (siteDesign.Overwrite)
                        {
                            var existingId = existingSiteDesign.Id;
                            existingSiteDesign = Tenant.GetSiteDesign(tenant.Context, existingId);
                            tenant.Context.ExecuteQueryRetry();

                            existingSiteDesign.Title               = parsedTitle;
                            existingSiteDesign.Description         = parsedDescription;
                            existingSiteDesign.PreviewImageUrl     = parsedPreviewImageUrl;
                            existingSiteDesign.PreviewImageAltText = parsedPreviewImageAltText;
                            existingSiteDesign.IsDefault           = siteDesign.IsDefault;
                            switch ((int)siteDesign.WebTemplate)
                            {
                            case 0:
                            {
                                existingSiteDesign.WebTemplate = "64";
                                break;
                            }

                            case 1:
                            {
                                existingSiteDesign.WebTemplate = "68";
                                break;
                            }
                            }

                            tenant.UpdateSiteDesign(existingSiteDesign);
                            tenant.Context.ExecuteQueryRetry();

                            var existingToken = parser.Tokens.OfType <SiteDesignIdToken>().FirstOrDefault(t => t.GetReplaceValue() == existingId.ToString());
                            if (existingToken != null)
                            {
                                parser.Tokens.Remove(existingToken);
                            }
                            parser.AddToken(new SiteScriptIdToken(null, parsedTitle, existingId));

                            if (siteDesign.Grants != null && siteDesign.Grants.Any())
                            {
                                var existingRights = Tenant.GetSiteDesignRights(tenant.Context, existingId);
                                tenant.Context.Load(existingRights);
                                tenant.Context.ExecuteQueryRetry();
                                foreach (var existingRight in existingRights)
                                {
                                    Tenant.RevokeSiteDesignRights(tenant.Context, existingId, new[] { existingRight.PrincipalName });
                                }
                                foreach (var grant in siteDesign.Grants)
                                {
                                    var rights = (TenantSiteDesignPrincipalRights)Enum.Parse(typeof(TenantSiteDesignPrincipalRights), grant.Right.ToString());
                                    tenant.GrantSiteDesignRights(existingId, new[] { parser.ParseString(grant.Principal) }, rights);
                                }
                                tenant.Context.ExecuteQueryRetry();
                            }
                        }
                    }
                }
            }
            return(parser);
        }
コード例 #8
0
        internal static TokenParser ProcessStorageEntities(Tenant tenant, ProvisioningTenant provisioningTenant, TokenParser parser, PnPMonitoredScope scope, ProvisioningTemplateApplyingInformation applyingInformation, ProvisioningMessagesDelegate messagesDelegate)
        {
            if (provisioningTenant.StorageEntities != null && provisioningTenant.StorageEntities.Any())
            {
                var rootSiteUrl = tenant.GetRootSiteUrl();
                tenant.Context.ExecuteQueryRetry();

                using (var context = ((ClientContext)tenant.Context).Clone(rootSiteUrl.Value, applyingInformation.AccessTokens))
                {
                    var web = context.Web;

                    Uri appCatalogUri = null;

                    try
                    {
                        appCatalogUri = web.GetAppCatalog();
                    }
                    catch (System.Net.WebException ex)
                    {
                        if (ex.Response != null)
                        {
                            var httpResponse = ex.Response as System.Net.HttpWebResponse;
                            if (httpResponse != null && httpResponse.StatusCode == HttpStatusCode.Unauthorized)
                            {
                                // Ignore any security exception and simply keep
                                // the AppCatalog URI null
                            }
                            else
                            {
                                throw ex;
                            }
                        }
                        else
                        {
                            throw ex;
                        }
                    }

                    if (appCatalogUri != null)
                    {
                        using (var appCatalogContext = context.Clone(appCatalogUri, applyingInformation.AccessTokens))
                        {
                            foreach (var entity in provisioningTenant.StorageEntities)
                            {
                                var key         = parser.ParseString(entity.Key);
                                var value       = parser.ParseString(entity.Value);
                                var description = parser.ParseString(entity.Description);
                                var comment     = parser.ParseString(entity.Comment);
                                appCatalogContext.Web.SetStorageEntity(key, value, description, comment);
                            }
                            appCatalogContext.Web.Update();
                            appCatalogContext.ExecuteQueryRetry();
                        }
                    }
                    else
                    {
                        messagesDelegate?.Invoke($"Tenant app catalog doesn't exist. Provisioning of storage entities will be skipped!", ProvisioningMessageType.Warning);
                    }
                }
            }
            return(parser);
        }
コード例 #9
0
ファイル: TenantHelper.cs プロジェクト: wspelt/PnP-Sites-Core
        public static TokenParser ProcessO365GroupSettings(Tenant tenant, ProvisioningTenant provisioningTenant, TokenParser parser, PnPMonitoredScope scope, ProvisioningMessagesDelegate messagesDelegate)
        {
            if (provisioningTenant.Office365GroupsSettings != null && provisioningTenant.Office365GroupsSettings.Properties.Any())
            {
                messagesDelegate?.Invoke("Processing Office 365 Group Settings", ProvisioningMessageType.Progress);
                bool siteClassificationSettingsExists = false;
                if (PnPProvisioningContext.Current != null)
                {
                    string accessToken = string.Empty;
                    try
                    {
                        // Get a fresh Access Token for every request
                        accessToken = PnPProvisioningContext.Current.AcquireToken(GraphHelper.MicrosoftGraphBaseURI, "Directory.ReadWrite.All");

                        if (accessToken != null)
                        {
                            try
                            {
                                var siteClassificationSettings = tenant.GetSiteClassificationsSettings(accessToken);
                                siteClassificationSettingsExists = true;
                            }
                            catch (Exception ex)
                            {
                                // Tenant classification doesn't exist, just swallow the exception.
                            }

                            if (siteClassificationSettingsExists)
                            {
                                // Tenant classification exists, update the necessary values for Group Settings.
                                try
                                {
                                    string directorySettingTemplatesUrl  = $"{GraphHttpClient.MicrosoftGraphV1BaseUri}groupSettings";
                                    var    directorySettingTemplatesJson = GraphHttpClient.MakeGetRequestForString(directorySettingTemplatesUrl, accessToken);
                                    var    directorySettingTemplates     = JsonConvert.DeserializeObject <DirectorySettingTemplates>(directorySettingTemplatesJson);

                                    // Retrieve the setinngs for "Group.Unified"
                                    var unifiedGroupSetting = directorySettingTemplates.Templates.FirstOrDefault(t => t.DisplayName == "Group.Unified");

                                    if (unifiedGroupSetting != null)
                                    {
                                        var props = provisioningTenant.Office365GroupsSettings.Properties;
                                        foreach (var v in unifiedGroupSetting.SettingValues)
                                        {
                                            var item = props.Where(p => p.Key == v.Name).FirstOrDefault();
                                            if (!string.IsNullOrEmpty(item.Key))
                                            {
                                                v.Value = parser.ParseString(item.Value);
                                            }
                                        }

                                        string updateDirectorySettingUrl    = $"{GraphHttpClient.MicrosoftGraphV1BaseUri}groupSettings/{unifiedGroupSetting.Id}";
                                        var    updateDirectorySettingResult = GraphHttpClient.MakePatchRequestForString(
                                            updateDirectorySettingUrl,
                                            content: new
                                        {
                                            templateId = unifiedGroupSetting.Id,
                                            values     = from v in unifiedGroupSetting.SettingValues select new { name = v.Name, value = v.Value },
                                        },
                                            contentType: "application/json",
                                            accessToken: accessToken);
                                    }
                                    else
                                    {
                                        throw new ApplicationException("Missing DirectorySettingTemplate for \"Group.Unified\"");
                                    }
                                }
                                catch (Exception ex)
                                {
                                    scope.LogError($"Error occurred processing O365 Group settings ${ex.Message}");
                                }
                            }
                            else
                            {
                                // Tenant classification doesn't exist, create the necessary template for Group Settings.

                                try
                                {
                                    string directorySettingTemplatesUrl  = $"{GraphHttpClient.MicrosoftGraphV1BaseUri}groupSettingTemplates";
                                    var    directorySettingTemplatesJson = GraphHttpClient.MakeGetRequestForString(directorySettingTemplatesUrl, accessToken);
                                    var    directorySettingTemplates     = JsonConvert.DeserializeObject <DirectorySettingTemplates>(directorySettingTemplatesJson);

                                    // Retrieve the setinngs for "Group.Unified"
                                    var unifiedGroupSetting = directorySettingTemplates.Templates.FirstOrDefault(t => t.DisplayName == "Group.Unified");

                                    if (unifiedGroupSetting != null)
                                    {
                                        var props = provisioningTenant.Office365GroupsSettings.Properties;
                                        foreach (var v in unifiedGroupSetting.SettingValues)
                                        {
                                            var item = props.Where(p => p.Key == v.Name).FirstOrDefault();
                                            if (!string.IsNullOrEmpty(item.Key))
                                            {
                                                v.Value = parser.ParseString(item.Value);
                                            }
                                            else
                                            {
                                                // Set default value because null is not supported
                                                // It only accepts entire collection and not individual properties
                                                v.Value = v.DefaultValue;
                                            }
                                        }

                                        string updateDirectorySettingUrl    = $"{GraphHttpClient.MicrosoftGraphV1BaseUri}groupSettings";
                                        var    updateDirectorySettingResult = GraphHttpClient.MakePostRequestForString(
                                            updateDirectorySettingUrl,
                                            content: new
                                        {
                                            templateId = unifiedGroupSetting.Id,
                                            values     = from v in unifiedGroupSetting.SettingValues select new { name = v.Name, value = v.Value },
                                        },
                                            contentType: "application/json",
                                            accessToken: accessToken);
                                    }
                                    else
                                    {
                                        throw new ApplicationException("Missing DirectorySettingTemplate for \"Group.Unified\"");
                                    }
                                }
                                catch (Exception ex)
                                {
                                    scope.LogError($"Error occurred processing O365 Group settings ${ex.Message}");
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        scope.LogError($"Error occurred processing O365 Group settings ${ex.Message}");
                    }
                }
            }
            return(parser);
        }
コード例 #10
0
        /// <summary>
        /// Actual implementation of the apply templates
        /// </summary>
        /// <param name="web"></param>
        /// <param name="template"></param>
        /// <param name="provisioningInfo"></param>
        /// <param name="calledFromHierarchy"></param>
        /// <param name="tokenParser"></param>
        internal void ApplyRemoteTemplate(Web web, ProvisioningTemplate template, ProvisioningTemplateApplyingInformation provisioningInfo, bool calledFromHierarchy = false, TokenParser tokenParser = null)
        {
            using (var scope = new PnPMonitoredScope(CoreResources.Provisioning_ObjectHandlers_Provisioning))
            {
#if !ONPREMISES || SP2016 || SP2019
                web.Context.DisableReturnValueCache = true;
#endif

                ProvisioningProgressDelegate        progressDelegate        = null;
                ProvisioningMessagesDelegate        messagesDelegate        = null;
                ProvisioningSiteProvisionedDelegate siteProvisionedDelegate = null;
                if (provisioningInfo != null)
                {
                    if (provisioningInfo.OverwriteSystemPropertyBagValues == true)
                    {
                        scope.LogInfo(CoreResources.SiteToTemplateConversion_ApplyRemoteTemplate_OverwriteSystemPropertyBagValues_is_to_true);
                    }
                    progressDelegate = provisioningInfo.ProgressDelegate;
                    if (provisioningInfo.ProgressDelegate != null)
                    {
                        scope.LogInfo(CoreResources.SiteToTemplateConversion_ProgressDelegate_registered);
                    }
                    messagesDelegate = provisioningInfo.MessagesDelegate;
                    if (provisioningInfo.MessagesDelegate != null)
                    {
                        scope.LogInfo(CoreResources.SiteToTemplateConversion_MessagesDelegate_registered);
                    }
                    siteProvisionedDelegate = provisioningInfo.SiteProvisionedDelegate;
                }
                else
                {
                    // When no provisioning info was passed then we want to execute all handlers
                    provisioningInfo = new ProvisioningTemplateApplyingInformation();
                    provisioningInfo.HandlersToProcess = Handlers.All;
                }

                // Check if scope is present and if so, matches the current site. When scope was not set the returned value will be ProvisioningTemplateScope.Undefined
                if (template.Scope == ProvisioningTemplateScope.RootSite)
                {
                    if (web.IsSubSite())
                    {
                        scope.LogError(CoreResources.SiteToTemplateConversion_ScopeOfTemplateDoesNotMatchTarget);
                        throw new Exception(CoreResources.SiteToTemplateConversion_ScopeOfTemplateDoesNotMatchTarget);
                    }
                }
                var currentCultureInfoValue = System.Threading.Thread.CurrentThread.CurrentCulture.LCID;
                if (!string.IsNullOrEmpty(template.TemplateCultureInfo))
                {
                    int cultureInfoValue = System.Threading.Thread.CurrentThread.CurrentCulture.LCID;
                    if (int.TryParse(template.TemplateCultureInfo, out cultureInfoValue))
                    {
                        System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(cultureInfoValue);
                    }
                    else
                    {
                        System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(template.TemplateCultureInfo);
                    }
                }

                // Check if the target site shares the same base template with the template's source site
                var targetSiteTemplateId = web.GetBaseTemplateId();
                if (!String.IsNullOrEmpty(targetSiteTemplateId) && !String.IsNullOrEmpty(template.BaseSiteTemplate))
                {
                    if (!targetSiteTemplateId.Equals(template.BaseSiteTemplate, StringComparison.InvariantCultureIgnoreCase))
                    {
                        var templatesNotMatchingWarning = String.Format(CoreResources.Provisioning_Asymmetric_Base_Templates, template.BaseSiteTemplate, targetSiteTemplateId);
                        scope.LogWarning(templatesNotMatchingWarning);
                        messagesDelegate?.Invoke(templatesNotMatchingWarning, ProvisioningMessageType.Warning);
                    }
                }

                // Always ensure the Url property is loaded. In the tokens we need this and we don't want to call ExecuteQuery as this can
                // impact delta scenarions (calling ExecuteQuery before the planned update is called)
                web.EnsureProperty(w => w.Url);


                List <ObjectHandlerBase> objectHandlers = new List <ObjectHandlerBase>();

                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.RegionalSettings))
                {
                    objectHandlers.Add(new ObjectRegionalSettings());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.SupportedUILanguages))
                {
                    objectHandlers.Add(new ObjectSupportedUILanguages());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.AuditSettings))
                {
                    objectHandlers.Add(new ObjectAuditSettings());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.SitePolicy))
                {
                    objectHandlers.Add(new ObjectSitePolicy());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.SiteSecurity))
                {
                    objectHandlers.Add(new ObjectSiteSecurity());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Features))
                {
                    objectHandlers.Add(new ObjectFeatures());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.TermGroups))
                {
                    objectHandlers.Add(new ObjectTermGroups());
                }

                // Process 3 times these providers to handle proper ordering of artefact creation when dealing with lookup fields

                // 1st. create fields, content and list without lookup fields
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Fields) || provisioningInfo.HandlersToProcess.HasFlag(Handlers.Lists))
                {
                    objectHandlers.Add(new ObjectField(FieldAndListProvisioningStepHelper.Step.ListAndStandardFields));
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.ContentTypes))
                {
                    objectHandlers.Add(new ObjectContentType(FieldAndListProvisioningStepHelper.Step.ListAndStandardFields));
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Lists))
                {
                    objectHandlers.Add(new ObjectListInstance(FieldAndListProvisioningStepHelper.Step.ListAndStandardFields));
                }

                // 2nd. create lookup fields (which requires lists to be present
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Fields) || provisioningInfo.HandlersToProcess.HasFlag(Handlers.Lists))
                {
                    objectHandlers.Add(new ObjectField(FieldAndListProvisioningStepHelper.Step.LookupFields));
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.ContentTypes))
                {
                    objectHandlers.Add(new ObjectContentType(FieldAndListProvisioningStepHelper.Step.LookupFields));
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Lists))
                {
                    objectHandlers.Add(new ObjectListInstance(FieldAndListProvisioningStepHelper.Step.LookupFields));
                }

                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Files))
                {
                    objectHandlers.Add(new ObjectFiles());
                }

                // 3rd. Create remaining objects in lists (views, user custom actions, ...)
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Lists))
                {
                    objectHandlers.Add(new ObjectListInstance(FieldAndListProvisioningStepHelper.Step.ListSettings));
                }

                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Fields) || provisioningInfo.HandlersToProcess.HasFlag(Handlers.Lists))
                {
                    objectHandlers.Add(new ObjectListInstanceDataRows());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Workflows))
                {
                    objectHandlers.Add(new ObjectWorkflows());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Pages))
                {
                    objectHandlers.Add(new ObjectPages());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.PageContents))
                {
                    objectHandlers.Add(new ObjectPageContents());
                }
#if !ONPREMISES
                if (!calledFromHierarchy && provisioningInfo.HandlersToProcess.HasFlag(Handlers.Tenant))
                {
                    objectHandlers.Add(new ObjectTenant());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.ApplicationLifecycleManagement))
                {
                    objectHandlers.Add(new ObjectApplicationLifecycleManagement());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Pages))
                {
                    objectHandlers.Add(new ObjectClientSidePages());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.SiteHeader))
                {
                    objectHandlers.Add(new ObjectSiteHeaderSettings());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.SiteFooter))
                {
                    objectHandlers.Add(new ObjectSiteFooterSettings());
                }
#endif
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.CustomActions))
                {
                    objectHandlers.Add(new ObjectCustomActions());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Publishing))
                {
                    objectHandlers.Add(new ObjectPublishing());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.ComposedLook))
                {
                    objectHandlers.Add(new ObjectComposedLook());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.SearchSettings))
                {
                    objectHandlers.Add(new ObjectSearchSettings());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.PropertyBagEntries))
                {
                    objectHandlers.Add(new ObjectPropertyBagEntry());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.WebSettings))
                {
                    objectHandlers.Add(new ObjectWebSettings());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Theme))
                {
                    objectHandlers.Add(new ObjectTheme());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.Navigation))
                {
                    objectHandlers.Add(new ObjectNavigation());
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.ImageRenditions))
                {
                    objectHandlers.Add(new ObjectImageRenditions());
                }
                objectHandlers.Add(new ObjectLocalization()); // Always add this one, check is done in the handler
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.ExtensibilityProviders))
                {
                    objectHandlers.Add(new ObjectExtensibilityHandlers());
                }

                // Only persist template information in case this flag is set: this will allow the engine to
                // work with lesser permissions
                if (provisioningInfo.PersistTemplateInfo)
                {
                    objectHandlers.Add(new ObjectPersistTemplateInfo());
                }
                var count = objectHandlers.Count(o => o.ReportProgress && o.WillProvision(web, template, provisioningInfo)) + 1;

                progressDelegate?.Invoke("Initializing engine", 1, count); // handlers + initializing message)
                if (tokenParser == null)
                {
                    tokenParser = new TokenParser(web, template);
                }
                if (provisioningInfo.HandlersToProcess.HasFlag(Handlers.ExtensibilityProviders))
                {
                    var extensibilityHandler = objectHandlers.OfType <ObjectExtensibilityHandlers>().First();
                    extensibilityHandler.AddExtendedTokens(web, template, tokenParser, provisioningInfo);
                }

                int step = 2;

                // Remove potentially unsupported artifacts

                var cleaner = new NoScriptTemplateCleaner(web);
                if (messagesDelegate != null)
                {
                    cleaner.MessagesDelegate = messagesDelegate;
                }
                template = cleaner.CleanUpBeforeProvisioning(template);

                CallWebHooks(template, tokenParser, ProvisioningTemplateWebhookKind.ProvisioningStarted);

                foreach (var handler in objectHandlers)
                {
                    if (handler.WillProvision(web, template, provisioningInfo))
                    {
                        if (messagesDelegate != null)
                        {
                            handler.MessagesDelegate = messagesDelegate;
                        }
                        if (handler.ReportProgress && progressDelegate != null)
                        {
                            progressDelegate(handler.Name, step, count);
                            step++;
                        }
                        CallWebHooks(template, tokenParser, ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningStarted, handler);
                        tokenParser = handler.ProvisionObjects(web, template, tokenParser, provisioningInfo);
                        CallWebHooks(template, tokenParser, ProvisioningTemplateWebhookKind.ObjectHandlerProvisioningCompleted, handler);
                    }
                }

                // Notify the completed provisioning of the site
                web.EnsureProperties(w => w.Title, w => w.Url);
                siteProvisionedDelegate?.Invoke(web.Title, web.Url);

                CallWebHooks(template, tokenParser, ProvisioningTemplateWebhookKind.ProvisioningCompleted);

                System.Threading.Thread.CurrentThread.CurrentCulture = new System.Globalization.CultureInfo(currentCultureInfoValue);
            }
        }