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); }
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); }