private void ProcessFiles(string templateFileName, FileConnectorBase fileSystemConnector, FileConnectorBase connector) { var templateFile = ReadProvisioningTemplate.LoadProvisioningTemplateFromFile(templateFileName, null, (e) => { WriteError(new ErrorRecord(e, "TEMPLATENOTVALID", ErrorCategory.SyntaxError, null)); }); if (Template.Tenant?.AppCatalog != null) { foreach (var app in Template.Tenant.AppCatalog.Packages) { WriteObject($"Processing {app.Src}"); AddFile(app.Src, templateFile, fileSystemConnector, connector); } } if (Template.Tenant?.SiteScripts != null) { foreach (var siteScript in Template.Tenant.SiteScripts) { WriteObject($"Processing {siteScript.JsonFilePath}"); AddFile(siteScript.JsonFilePath, templateFile, fileSystemConnector, connector); } } if (Template.Localizations != null && Template.Localizations.Any()) { foreach (var location in Template.Localizations) { WriteObject($"Processing {location.ResourceFile}"); AddFile(location.ResourceFile, templateFile, fileSystemConnector, connector); } } if (Template.WebSettings != null && !String.IsNullOrEmpty(Template.WebSettings.SiteLogo)) { // is it a file? var isFile = false; using (var fileStream = fileSystemConnector.GetFileStream(Template.WebSettings.SiteLogo)) { isFile = fileStream != null; } if (isFile) { WriteObject($"Processing {Template.WebSettings.SiteLogo}"); AddFile(Template.WebSettings.SiteLogo, templateFile, fileSystemConnector, connector); } } if (Template.Files.Any()) { foreach (var file in Template.Files) { WriteObject($"Processing {file.Src}"); AddFile(file.Src, templateFile, fileSystemConnector, connector); } } if (templateFile.Connector is ICommitableFileConnector) { ((ICommitableFileConnector)templateFile.Connector).Commit(); } }
/// <summary> /// Constructor for ProvisioningTemplate class /// </summary> public ProvisioningTemplate() { this.connector = new FileSystemConnector(".", ""); this._localizations = new LocalizationCollection(this); this._siteFields = new FieldCollection(this); this._contentTypes = new ContentTypeCollection(this); this._propertyBags = new PropertyBagEntryCollection(this); this._lists = new ListInstanceCollection(this); this._siteSecurity = new SiteSecurity(); this._siteSecurity.ParentTemplate = this; this._composedLook = new ComposedLook(); this._composedLook.ParentTemplate = this; this._features = new Features(); this._features.ParentTemplate = this; this._customActions = new CustomActions(); this._customActions.ParentTemplate = this; this._files = new FileCollection(this); this._directories = new DirectoryCollection(this); this._providers = new ProviderCollection(this); // Deprecated this._extensibilityHandlers = new ExtensibilityHandlerCollection(this); this._pages = new PageCollection(this); this._termGroups = new TermGroupCollection(this); this._supportedUILanguages = new SupportedUILanguageCollection(this); this._addins = new AddInCollection(this); this._siteWebhooks = new SiteWebhookCollection(this); this._clientSidePages = new ClientSidePageCollection(this); }
/// <summary> /// Returns Connectors /// </summary> /// <returns></returns> private FileConnectorBase GetProvisioningConnector() { ReflectionHelper _helper = new ReflectionHelper(); FileConnectorBase _connectorInstance = _helper.GetProvisioningConnector(ModuleKeys.PROVISIONINGCONNECTORS_KEY); return(_connectorInstance); }
public XMLOpenXMLTemplateProvider(string packageFileName, FileConnectorBase persistenceConnector, String author = null, X509Certificate2 signingCertificate = null) : base(new OpenXMLConnector(packageFileName, persistenceConnector, author, signingCertificate)) { }
private static void SaveFileInPackage(String filePath, String container, FileConnectorBase connector) { using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { String fileName = filePath.Substring(filePath.LastIndexOf("\\") + 1); connector.SaveFileStream(fileName, container, fs); } }
private void ProcessFiles(string templateFileName, FileConnectorBase fileSystemConnector, FileConnectorBase connector) { var templateFile = ReadTenantTemplate.LoadProvisioningHierarchyFromFile(templateFileName, null); if (Template.Tenant?.AppCatalog != null) { foreach (var app in Template.Tenant.AppCatalog.Packages) { WriteObject($"Processing {app.Src}"); AddFile(app.Src, templateFile, fileSystemConnector, connector); } } if (Template.Tenant?.SiteScripts != null) { foreach (var siteScript in Template.Tenant.SiteScripts) { WriteObject($"Processing {siteScript.JsonFilePath}"); AddFile(siteScript.JsonFilePath, templateFile, fileSystemConnector, connector); } } if (Template.Localizations != null && Template.Localizations.Any()) { foreach (var location in Template.Localizations) { WriteObject($"Processing {location.ResourceFile}"); AddFile(location.ResourceFile, templateFile, fileSystemConnector, connector); } } foreach (var template in Template.Templates) { if (template.WebSettings != null && template.WebSettings.SiteLogo != null) { // is it a file? var isFile = false; using (var fileStream = fileSystemConnector.GetFileStream(template.WebSettings.SiteLogo)) { isFile = fileStream != null; } if (isFile) { WriteObject($"Processing {template.WebSettings.SiteLogo}"); AddFile(template.WebSettings.SiteLogo, templateFile, fileSystemConnector, connector); } } if (template.Files.Any()) { foreach (var file in template.Files) { WriteObject($"Processing {file.Src}"); AddFile(file.Src, templateFile, fileSystemConnector, connector); } } } if (templateFile.Connector is ICommitableFileConnector) { ((ICommitableFileConnector)templateFile.Connector).Commit(); } }
public static byte[] GetFileBytes(FileConnectorBase connector, string fileName) { var container = String.Empty; if (fileName.Contains(@"\") || fileName.Contains(@"/")) { var tempFileName = fileName.Replace(@"/", @"\"); container = fileName.Substring(0, tempFileName.LastIndexOf(@"\")); fileName = fileName.Substring(tempFileName.LastIndexOf(@"\") + 1); } // add the default provided container (if any) if (!String.IsNullOrEmpty(container)) { if (!String.IsNullOrEmpty(connector.GetContainer())) { if (container.StartsWith("/")) { container = container.TrimStart("/".ToCharArray()); } container = $@"{connector.GetContainer()}\{container}"; } } else { container = connector.GetContainer(); } var stream = connector.GetFileStream(fileName, container); if (stream == null) { //Decode the URL and try again fileName = WebUtility.UrlDecode(fileName); stream = connector.GetFileStream(fileName, container); } if (stream == null) { throw new ArgumentException($"The specified filename '{fileName}' cannot be found"); } byte[] returnData; using (var memStream = new MemoryStream()) { stream.CopyTo(memStream); memStream.Position = 0; returnData = memStream.ToArray(); } if (stream != null) { stream.Dispose(); } return(returnData); }
public string ReadWorkflowFile(string fileName, FileConnectorBase fileReader) { //FileSystemConnector connector = new FileSystemConnector(null,workflowFolderName); //string fileContents = connector.GetFile(fileName); string fileContents = fileReader.GetFile(fileName); return(fileContents); }
private void AddFile(string sourceName, ProvisioningHierarchy hierarchy, FileConnectorBase fileSystemConnector, FileConnectorBase connector) { using (var fs = fileSystemConnector.GetFileStream(sourceName)) { var fileName = sourceName.IndexOf("\\") > 0 ? sourceName.Substring(sourceName.LastIndexOf("\\") + 1) : sourceName; var folderName = sourceName.IndexOf("\\") > 0 ? sourceName.Substring(0, sourceName.LastIndexOf("\\")) : ""; hierarchy.Connector.SaveFileStream(fileName, folderName, fs); } }
protected XMLTemplateProvider(FileConnectorBase connector) : base(connector) { }
private void DownLoadFile(SharePointConnector reader, SharePointConnector readerRoot, FileConnectorBase writer, string webUrl, string asset) { // No file passed...leave if (String.IsNullOrEmpty(asset)) { return; } SharePointConnector readerToUse; Model.File f = GetComposedLookFile(asset); // Strip the /sites/root part from /sites/root/lib/folder structure Uri u = new Uri(webUrl); if (f.Folder.IndexOf(u.PathAndQuery, StringComparison.InvariantCultureIgnoreCase) > -1) { f.Folder = f.Folder.Replace(u.PathAndQuery, ""); } // in case of a theme catalog we need to use the root site reader as that list only exists on root site level if (f.Folder.IndexOf("/_catalogs/theme", StringComparison.InvariantCultureIgnoreCase) > -1) { readerToUse = readerRoot; } else { readerToUse = reader; } using (Stream s = readerToUse.GetFileStream(f.Src, f.Folder)) { if (s != null) { writer.SaveFileStream(f.Src, s); } } }
private void DownLoadFile(SharePointConnector reader, SharePointConnector readerRoot, FileConnectorBase writer, string webUrl, string asset, PnPMonitoredScope scope) { // No file passed...leave if (String.IsNullOrEmpty(asset)) { return; } scope.LogDebug(CoreResources.Provisioning_ObjectHandlers_ComposedLooks_DownLoadFile_Downloading_asset___0_, asset); ; SharePointConnector readerToUse; Model.File f = GetComposedLookFile(asset); // Strip the /sites/root part from /sites/root/lib/folder structure, special case for root site handling. Uri u = new Uri(webUrl); if (f.Folder.IndexOf(u.PathAndQuery, StringComparison.InvariantCultureIgnoreCase) > -1 && u.PathAndQuery.Length > 1) { f.Folder = f.Folder.Replace(u.PathAndQuery, ""); } // in case of a theme catalog we need to use the root site reader as that list only exists on root site level if (f.Folder.IndexOf("/_catalogs/theme", StringComparison.InvariantCultureIgnoreCase) > -1) { readerToUse = readerRoot; } else { readerToUse = reader; } using (Stream s = readerToUse.GetFileStream(f.Src, f.Folder)) { if (s != null) { writer.SaveFileStream(f.Src, s); } } }
/// <summary> /// Constructor for ProvisioningTemplate class /// </summary> /// <param name="connector">FileConnectorBase object</param> public ProvisioningTemplate(FileConnectorBase connector) : this() { this.connector = connector; }
private Microsoft.SharePoint.Client.ContentType CreateContentType( Web web, ProvisioningTemplate template, ContentType templateContentType, TokenParser parser, FileConnectorBase connector, PnPMonitoredScope scope, List <Microsoft.SharePoint.Client.ContentType> existingCTs = null, List <Microsoft.SharePoint.Client.Field> existingFields = null, bool isNoScriptSite = false) { var name = parser.ParseString(templateContentType.Name); var description = parser.ParseString(templateContentType.Description); var id = parser.ParseString(templateContentType.Id); var group = parser.ParseString(templateContentType.Group); var createdCT = web.CreateContentType(name, description, id, group); var fieldsRefsToProcess = templateContentType.FieldRefs.Select(fr => new { FieldRef = fr, TemplateField = template.SiteFields.FirstOrDefault(tf => (Guid)XElement.Parse(parser.ParseString(tf.SchemaXml)).Attribute("ID") == fr.Id) }).Where(frData => frData.TemplateField == null || // Process fields refs if the target is not defined in the current template frData.TemplateField.GetFieldProvisioningStep(parser) == _step // or process field ref only if the current step is matching ).Select(fr => fr.FieldRef).ToArray(); foreach (var fieldRef in fieldsRefsToProcess) { Microsoft.SharePoint.Client.Field field = null; try { field = web.AvailableFields.GetById(fieldRef.Id); } catch (ArgumentException) { if (!string.IsNullOrEmpty(fieldRef.Name)) { field = web.AvailableFields.GetByInternalNameOrTitle(fieldRef.Name); } } // Add it to the target content type // Notice that this code will fail if the field does not exist web.AddFieldToContentType(createdCT, field, fieldRef.Required, fieldRef.Hidden); } // Add new CTs parser.AddToken(new ContentTypeIdToken(web, name, id)); #if !ONPREMISES // Set resources if (templateContentType.Name.ContainsResourceToken()) { createdCT.NameResource.SetUserResourceValue(templateContentType.Name, parser); } if (templateContentType.Description.ContainsResourceToken()) { createdCT.DescriptionResource.SetUserResourceValue(templateContentType.Description, parser); } #endif //Reorder the elements so that the new created Content Type has the same order as defined in the //template. The order can be different if the new Content Type inherits from another Content Type. //In this case the new Content Type has all field of the original Content Type and missing fields //will be added at the end. To fix this issue we ordering the fields once more. createdCT.FieldLinks.Reorder(templateContentType.FieldRefs.Select(fld => parser.ParseString(fld.Name)).ToArray()); createdCT.ReadOnly = templateContentType.ReadOnly; createdCT.Hidden = templateContentType.Hidden; createdCT.Sealed = templateContentType.Sealed; if (templateContentType.DocumentSetTemplate == null) { // Only apply a document template when the contenttype is not a document set if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.DocumentTemplate))) { createdCT.DocumentTemplate = parser.ParseString(templateContentType.DocumentTemplate); } } // Skipping updates of forms as we can't upload forms to noscript sites if (!isNoScriptSite) { if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.NewFormUrl))) { createdCT.NewFormUrl = parser.ParseString(templateContentType.NewFormUrl); } if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.EditFormUrl))) { createdCT.EditFormUrl = parser.ParseString(templateContentType.EditFormUrl); } if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.DisplayFormUrl))) { createdCT.DisplayFormUrl = parser.ParseString(templateContentType.DisplayFormUrl); } } else { if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.DisplayFormUrl)) || !string.IsNullOrEmpty(parser.ParseString(templateContentType.EditFormUrl)) || !string.IsNullOrEmpty(parser.ParseString(templateContentType.NewFormUrl))) { // log message scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ContentTypes_SkipCustomFormUrls, name); } } createdCT.Update(true); web.Context.ExecuteQueryRetry(); // If the CT is a DocumentSet if (templateContentType.DocumentSetTemplate != null) { // Retrieve a reference to the DocumentSet Content Type Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate documentSetTemplate = Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate.GetDocumentSetTemplate(web.Context, createdCT); // Load the collections to allow for deletion scenarions web.Context.Load(documentSetTemplate, d => d.AllowedContentTypes, d => d.DefaultDocuments, d => d.SharedFields, d => d.WelcomePageFields); web.Context.ExecuteQueryRetry(); if (!String.IsNullOrEmpty(templateContentType.DocumentSetTemplate.WelcomePage)) { // TODO: Customize the WelcomePage of the DocumentSet } // Add additional content types to the set of allowed content types bool hasDefaultDocumentContentTypeInTemplate = false; foreach (String ctId in templateContentType.DocumentSetTemplate.AllowedContentTypes) { Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == ctId); if (ct != null) { if (ct.Id.StringValue.Equals("0x0101", StringComparison.InvariantCultureIgnoreCase)) { hasDefaultDocumentContentTypeInTemplate = true; } documentSetTemplate.AllowedContentTypes.Add(ct.Id); } } // If the default document content type (0x0101) is not in our definition then remove it if (!hasDefaultDocumentContentTypeInTemplate) { Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == "0x0101"); if (ct != null) { documentSetTemplate.AllowedContentTypes.Remove(ct.Id); } } if (!isNoScriptSite) { foreach (var doc in templateContentType.DocumentSetTemplate.DefaultDocuments) { Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == doc.ContentTypeId); if (ct != null) { using (Stream fileStream = connector.GetFileStream(doc.FileSourcePath)) { documentSetTemplate.DefaultDocuments.Add(doc.Name, ct.Id, ReadFullStream(fileStream)); } } } } else { if (templateContentType.DocumentSetTemplate.DefaultDocuments.Any()) { scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ContentTypes_SkipDocumentSetDefaultDocuments, name); } } foreach (var sharedField in templateContentType.DocumentSetTemplate.SharedFields) { Microsoft.SharePoint.Client.Field field = existingFields.FirstOrDefault(f => f.Id == sharedField); if (field != null) { documentSetTemplate.SharedFields.Add(field); } } foreach (var welcomePageField in templateContentType.DocumentSetTemplate.WelcomePageFields) { Microsoft.SharePoint.Client.Field field = existingFields.FirstOrDefault(f => f.Id == welcomePageField); if (field != null) { documentSetTemplate.WelcomePageFields.Add(field); } } documentSetTemplate.Update(true); web.Context.ExecuteQueryRetry(); } else if (templateContentType.Id.StartsWith(BuiltInContentTypeId.Workflow2013Task + "00")) { // If the Workflow Task (SP2013) contains more than one outcomeChoice, the Form UI will not show // the buttons associated each to choices, but fallback to classic Save and Cancel buttons. // +"00" is used to target only inherited content types and not alter OOB var outcomeFields = web.Context.LoadQuery( createdCT.Fields.Where(f => f.TypeAsString == "OutcomeChoice")); web.Context.ExecuteQueryRetry(); if (outcomeFields.Any()) { // 2 OutcomeChoice specified means the user has certainly push its own. // Let's remove the default outcome field var field = outcomeFields.FirstOrDefault(f => f.StaticName == "TaskOutcome"); if (field != null) { var fl = createdCT.FieldLinks.GetById(field.Id); fl.DeleteObject(); createdCT.Update(true); web.Context.ExecuteQueryRetry(); } } } web.Context.Load(createdCT); web.Context.ExecuteQueryRetry(); return(createdCT); }
/// <summary> /// Synchronizes Team's Photo /// </summary> /// <param name="scope">The PnP Provisioning Scope</param> /// <param name="parser">The PnP Token Parser</param> /// <param name="connector">The PnP File Connector</param> /// <param name="team">The Team settings, including security settings</param> /// <param name="teamId">The ID of the target Team</param> /// <param name="accessToken">The OAuth 2.0 Access Token</param> /// <returns>Whether the Apps have been provisioned or not</returns> private static bool SetTeamPhoto(PnPMonitoredScope scope, TokenParser parser, FileConnectorBase connector, Team team, string teamId, string accessToken) { if (!String.IsNullOrEmpty(team.Photo) && connector != null) { var photoPath = parser.ParseString(team.Photo); var photoBytes = ConnectorFileHelper.GetFileBytes(connector, team.Photo); using (var mem = new MemoryStream()) { mem.Write(photoBytes, 0, photoBytes.Length); mem.Position = 0; HttpHelper.MakePostRequest( $"{GraphHelper.MicrosoftGraphBaseURI}v1.0/groups/{teamId}/photo/$value", mem, "image/jpeg", accessToken); } } return(true); }
private void AddResourceTokens(Web web, LocalizationCollection localizations, FileConnectorBase connector) { if (localizations != null && localizations.Any()) { //https://github.com/SharePoint/PnP-Provisioning-Schema/issues/301 //fixing issue to allow multiple resx files in the template. i.e: //<pnp:Localization LCID="1033" Name="core" ResourceFile="core.en-us.resx" /> //<pnp:Localization LCID="3082" Name="core" ResourceFile="core.es-es.resx" /> //<pnp:Localization LCID="1033" Name="intranet" ResourceFile="intranet.en-us.resx" /> //<pnp:Localization LCID="3082" Name="intranet" ResourceFile="intranet.es-es.resx" /> var resourcesFilesCount = localizations.GroupBy(l => l.Name).Count(); // Read all resource keys in a list List <Tuple <string, uint, string> > resourceEntries = new List <Tuple <string, uint, string> >(); foreach (var localizationEntry in localizations) { var filePath = localizationEntry.ResourceFile; using (var stream = connector.GetFileStream(filePath)) { if (stream != null) { #if !NETSTANDARD2_0 using (ResXResourceReader resxReader = new ResXResourceReader(stream)) #else using (ResourceReader resxReader = new ResourceReader(stream)) #endif { foreach (DictionaryEntry entry in resxReader) { // One can have multiple resource files in a single file, by adding tokens with resource file name and without we allow both scenarios to resolve resourceEntries.Add(new Tuple <string, uint, string>($"{localizationEntry.Name}:{entry.Key}", (uint)localizationEntry.LCID, entry.Value.ToString().Replace("\"", """))); resourceEntries.Add(new Tuple <string, uint, string>(entry.Key.ToString(), (uint)localizationEntry.LCID, entry.Value.ToString().Replace("\"", """))); } } } } } var uniqueKeys = resourceEntries.Select(k => k.Item1).Distinct(); foreach (var key in uniqueKeys) { var matches = resourceEntries.Where(k => k.Item1 == key); var entries = matches.Select(k => new ResourceEntry() { LCID = k.Item2, Value = k.Item3 }).ToList(); LocalizationToken token = new LocalizationToken(web, key, entries); _tokens.Add(token); } } }
public TemplateProviderBase(FileConnectorBase connector) { this._connector = connector; }
private static Microsoft.SharePoint.Client.ContentType CreateContentType(Web web, ContentType templateContentType, TokenParser parser, FileConnectorBase connector, List <Microsoft.SharePoint.Client.ContentType> existingCTs = null, List <Microsoft.SharePoint.Client.Field> existingFields = null) { var name = parser.ParseString(templateContentType.Name); var description = parser.ParseString(templateContentType.Description); var id = parser.ParseString(templateContentType.Id); var group = parser.ParseString(templateContentType.Group); var createdCT = web.CreateContentType(name, description, id, group); foreach (var fieldRef in templateContentType.FieldRefs) { var field = web.Fields.GetById(fieldRef.Id); web.AddFieldToContentType(createdCT, field, fieldRef.Required, fieldRef.Hidden); } //Reorder the elements so that the new created Content Type has the same order as defined in the //template. The order can be different if the new Content Type inherits from another Content Type. //In this case the new Content Type has all field of the original Content Type and missing fields //will be added at the end. To fix this issue we ordering the fields once more. createdCT.FieldLinks.Reorder(templateContentType.FieldRefs.Select(fld => fld.Name).ToArray()); createdCT.Update(true); web.Context.ExecuteQueryRetry(); createdCT.ReadOnly = templateContentType.ReadOnly; createdCT.Hidden = templateContentType.Hidden; createdCT.Sealed = templateContentType.Sealed; if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.DocumentTemplate))) { createdCT.DocumentTemplate = parser.ParseString(templateContentType.DocumentTemplate); } if (!String.IsNullOrEmpty(templateContentType.NewFormUrl)) { createdCT.NewFormUrl = templateContentType.NewFormUrl; } if (!String.IsNullOrEmpty(templateContentType.EditFormUrl)) { createdCT.EditFormUrl = templateContentType.EditFormUrl; } if (!String.IsNullOrEmpty(templateContentType.DisplayFormUrl)) { createdCT.DisplayFormUrl = templateContentType.DisplayFormUrl; } // If the CT is a DocumentSet if (templateContentType.DocumentSetTemplate != null) { // Retrieve a reference to the DocumentSet Content Type Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate documentSetTemplate = Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate.GetDocumentSetTemplate(web.Context, createdCT); if (!String.IsNullOrEmpty(templateContentType.DocumentSetTemplate.WelcomePage)) { // TODO: Customize the WelcomePage of the DocumentSet } foreach (String ctId in templateContentType.DocumentSetTemplate.AllowedContentTypes) { Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == ctId); if (ct != null) { documentSetTemplate.AllowedContentTypes.Add(ct.Id); } } foreach (var doc in templateContentType.DocumentSetTemplate.DefaultDocuments) { Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == doc.ContentTypeId); if (ct != null) { using (Stream fileStream = connector.GetFileStream(doc.FileSourcePath)) { documentSetTemplate.DefaultDocuments.Add(doc.Name, ct.Id, ReadFullStream(fileStream)); } } } foreach (var sharedField in templateContentType.DocumentSetTemplate.SharedFields) { Microsoft.SharePoint.Client.Field field = existingFields.FirstOrDefault(f => f.Id == sharedField); if (field != null) { documentSetTemplate.SharedFields.Add(field); } } foreach (var welcomePageField in templateContentType.DocumentSetTemplate.WelcomePageFields) { Microsoft.SharePoint.Client.Field field = existingFields.FirstOrDefault(f => f.Id == welcomePageField); if (field != null) { documentSetTemplate.WelcomePageFields.Add(field); } } documentSetTemplate.Update(true); web.Context.ExecuteQueryRetry(); } web.Context.Load(createdCT); web.Context.ExecuteQueryRetry(); return(createdCT); }
public static byte[] GetFileBytes(FileConnectorBase connector, string fileName) { var container = String.Empty; if (fileName.Contains(@"\") || fileName.Contains(@"/")) { var tempFileName = fileName.Replace(@"/", @"\"); container = fileName.Substring(0, tempFileName.LastIndexOf(@"\")); fileName = fileName.Substring(tempFileName.LastIndexOf(@"\") + 1); } // add the default provided container (if any) if (!String.IsNullOrEmpty(container)) { if (!String.IsNullOrEmpty(connector.GetContainer())) { if (container.StartsWith("/")) { container = container.TrimStart("/".ToCharArray()); } #if !NETSTANDARD2_0 if (connector.GetType() == typeof(Connectors.AzureStorageConnector)) { if (connector.GetContainer().EndsWith("/")) { container = $@"{connector.GetContainer()}{container}"; } else { container = $@"{connector.GetContainer()}/{container}"; } } else { container = $@"{connector.GetContainer()}\{container}"; } #else container = $@"{connector.GetContainer()}\{container}"; #endif } } else { container = connector.GetContainer(); } var stream = connector.GetFileStream(fileName, container); if (stream == null) { //Decode the URL and try again fileName = WebUtility.UrlDecode(fileName); stream = connector.GetFileStream(fileName, container); } byte[] returnData; using (var memStream = new MemoryStream()) { stream.CopyTo(memStream); memStream.Position = 0; returnData = memStream.ToArray(); } if (stream != null) { stream.Dispose(); } return(returnData); }
private static Microsoft.SharePoint.Client.ContentType CreateContentType(Web web, ContentType templateContentType, TokenParser parser, FileConnectorBase connector, PnPMonitoredScope scope, List <Microsoft.SharePoint.Client.ContentType> existingCTs = null, List <Microsoft.SharePoint.Client.Field> existingFields = null, bool isNoScriptSite = false) { var name = parser.ParseString(templateContentType.Name); var description = parser.ParseString(templateContentType.Description); var id = parser.ParseString(templateContentType.Id); var group = parser.ParseString(templateContentType.Group); var createdCT = web.CreateContentType(name, description, id, group); foreach (var fieldRef in templateContentType.FieldRefs) { Microsoft.SharePoint.Client.Field field = null; try { field = web.AvailableFields.GetById(fieldRef.Id); } catch (ArgumentException) { if (!string.IsNullOrEmpty(fieldRef.Name)) { field = web.AvailableFields.GetByInternalNameOrTitle(fieldRef.Name); } } // Add it to the target content type // Notice that this code will fail if the field does not exist web.AddFieldToContentType(createdCT, field, fieldRef.Required, fieldRef.Hidden); } // Add new CTs parser.AddToken(new ContentTypeIdToken(web, name, id)); #if !ONPREMISES // Set resources if (templateContentType.Name.ContainsResourceToken()) { createdCT.NameResource.SetUserResourceValue(templateContentType.Name, parser); } if (templateContentType.Description.ContainsResourceToken()) { createdCT.DescriptionResource.SetUserResourceValue(templateContentType.Description, parser); } #endif //Reorder the elements so that the new created Content Type has the same order as defined in the //template. The order can be different if the new Content Type inherits from another Content Type. //In this case the new Content Type has all field of the original Content Type and missing fields //will be added at the end. To fix this issue we ordering the fields once more. createdCT.FieldLinks.Reorder(templateContentType.FieldRefs.Select(fld => parser.ParseString(fld.Name)).ToArray()); createdCT.ReadOnly = templateContentType.ReadOnly; createdCT.Hidden = templateContentType.Hidden; createdCT.Sealed = templateContentType.Sealed; if (templateContentType.DocumentSetTemplate == null) { // Only apply a document template when the contenttype is not a document set if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.DocumentTemplate))) { createdCT.DocumentTemplate = parser.ParseString(templateContentType.DocumentTemplate); } } // Skipping updates of forms as we can't upload forms to noscript sites if (!isNoScriptSite) { if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.NewFormUrl))) { createdCT.NewFormUrl = parser.ParseString(templateContentType.NewFormUrl); } if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.EditFormUrl))) { createdCT.EditFormUrl = parser.ParseString(templateContentType.EditFormUrl); } if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.DisplayFormUrl))) { createdCT.DisplayFormUrl = parser.ParseString(templateContentType.DisplayFormUrl); } } else { if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.DisplayFormUrl)) || !string.IsNullOrEmpty(parser.ParseString(templateContentType.EditFormUrl)) || !string.IsNullOrEmpty(parser.ParseString(templateContentType.NewFormUrl))) { // log message scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ContentTypes_SkipCustomFormUrls, name); } } createdCT.Update(true); web.Context.ExecuteQueryRetry(); // If the CT is a DocumentSet if (templateContentType.DocumentSetTemplate != null) { // Retrieve a reference to the DocumentSet Content Type Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate documentSetTemplate = Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate.GetDocumentSetTemplate(web.Context, createdCT); // Load the collections to allow for deletion scenarions web.Context.Load(documentSetTemplate, d => d.AllowedContentTypes, d => d.DefaultDocuments, d => d.SharedFields, d => d.WelcomePageFields); web.Context.ExecuteQueryRetry(); if (!String.IsNullOrEmpty(templateContentType.DocumentSetTemplate.WelcomePage)) { // TODO: Customize the WelcomePage of the DocumentSet } // Add additional content types to the set of allowed content types bool hasDefaultDocumentContentTypeInTemplate = false; foreach (String ctId in templateContentType.DocumentSetTemplate.AllowedContentTypes) { Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == ctId); if (ct != null) { if (ct.Id.StringValue.Equals("0x0101", StringComparison.InvariantCultureIgnoreCase)) { hasDefaultDocumentContentTypeInTemplate = true; } documentSetTemplate.AllowedContentTypes.Add(ct.Id); } } // If the default document content type (0x0101) is not in our definition then remove it if (!hasDefaultDocumentContentTypeInTemplate) { Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == "0x0101"); if (ct != null) { documentSetTemplate.AllowedContentTypes.Remove(ct.Id); } } if (!isNoScriptSite) { foreach (var doc in templateContentType.DocumentSetTemplate.DefaultDocuments) { Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == doc.ContentTypeId); if (ct != null) { using (Stream fileStream = connector.GetFileStream(doc.FileSourcePath)) { documentSetTemplate.DefaultDocuments.Add(doc.Name, ct.Id, ReadFullStream(fileStream)); } } } } else { if (templateContentType.DocumentSetTemplate.DefaultDocuments.Any()) { scope.LogWarning(CoreResources.Provisioning_ObjectHandlers_ContentTypes_SkipDocumentSetDefaultDocuments, name); } } foreach (var sharedField in templateContentType.DocumentSetTemplate.SharedFields) { Microsoft.SharePoint.Client.Field field = existingFields.FirstOrDefault(f => f.Id == sharedField); if (field != null) { documentSetTemplate.SharedFields.Add(field); } } foreach (var welcomePageField in templateContentType.DocumentSetTemplate.WelcomePageFields) { Microsoft.SharePoint.Client.Field field = existingFields.FirstOrDefault(f => f.Id == welcomePageField); if (field != null) { documentSetTemplate.WelcomePageFields.Add(field); } } documentSetTemplate.Update(true); web.Context.ExecuteQueryRetry(); } web.Context.Load(createdCT); web.Context.ExecuteQueryRetry(); return(createdCT); }
/// <summary> /// Creates a new Team from a PnP Provisioning Schema definition /// </summary> /// <param name="scope">The PnP Provisioning Scope</param> /// <param name="parser">The PnP Token Parser</param> /// <param name="connector">The PnP File connector</param> /// <param name="team">The Team to provision</param> /// <param name="accessToken">The OAuth 2.0 Access Token</param> /// <returns>The provisioned Team as a JSON object</returns> private static JToken CreateTeamFromProvisioningSchema(PnPMonitoredScope scope, TokenParser parser, FileConnectorBase connector, Team team, string accessToken) { String teamId = null; // If we have to Clone an existing Team if (!String.IsNullOrWhiteSpace(team.CloneFrom)) { teamId = CloneTeam(scope, team, parser, accessToken); } // If we start from an already existing Group else if (!String.IsNullOrEmpty(team.GroupId)) { // We need to parse the GroupId, if it is a token var parsedGroupId = parser.ParseString(team.GroupId); // Check if the Group exists if (GroupExistsById(scope, parsedGroupId, accessToken)) { // Then promote the Group into a Team or update it, if it already exists. Patching a team doesn't return an ID, so use the parsedGroupId directly (teamId and groupId are the same). teamId = CreateOrUpdateTeamFromGroup(scope, team, parser, parsedGroupId, accessToken) ?? parsedGroupId; } else { // Log the exception and return NULL (i.e. cancel) scope.LogError(CoreResources.Provisioning_ObjectHandlers_Teams_Team_GroupDoesNotExists, parsedGroupId); return(null); } } // Otherwise create a Team from scratch else { teamId = CreateOrUpdateTeam(scope, team, parser, accessToken); } if (!String.IsNullOrEmpty(teamId)) { // Wait to be sure that the Team is ready before configuring it WaitForTeamToBeReady(accessToken, teamId); // And now we configure security, channels, and apps if (!SetGroupSecurity(scope, team, teamId, accessToken)) { return(null); } if (!SetTeamChannels(scope, parser, team, teamId, accessToken)) { return(null); } if (!SetTeamApps(scope, team, teamId, accessToken)) { return(null); } // So far the Team's photo cannot be set if we don't have an already existing mailbox // if (!SetTeamPhoto(scope, parser, connector, team, teamId, accessToken)) return null; // Call Archive or Unarchive for the current Team ArchiveTeam(scope, teamId, team.Archived, accessToken); try { // Get the whole Team that we just created and return it back as the method result return(JToken.Parse(HttpHelper.MakeGetRequestForString($"{GraphHelper.MicrosoftGraphBaseURI}v1.0/teams/{teamId}", accessToken))); } catch (Exception ex) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_Teams_Team_FetchingError, ex.Message); } } return(null); }
public ProvisioningTemplate() { this.connector = new FileSystemConnector(".", ""); }
/// <summary> /// Synchronizes User's Photo /// </summary> /// <param name="scope">The PnP Provisioning Scope</param> /// <param name="parser">The PnP Token Parser</param> /// <param name="connector">The PnP file connector</param> /// <param name="user">The target User</param> /// <param name="userId">The ID of the target User</param> /// <param name="accessToken">The OAuth 2.0 Access Token</param> /// <returns>Whether the Photo has been updated or not</returns> private static bool SetUserPhoto(PnPMonitoredScope scope, TokenParser parser, FileConnectorBase connector, Model.AzureActiveDirectory.User user, string userId, string accessToken) { Boolean result = false; if (!String.IsNullOrEmpty(user.ProfilePhoto) && connector != null) { var photoPath = parser.ParseString(user.ProfilePhoto); var photoBytes = ConnectorFileHelper.GetFileBytes(connector, user.ProfilePhoto); using (var mem = new MemoryStream()) { mem.Write(photoBytes, 0, photoBytes.Length); mem.Position = 0; HttpHelper.MakePostRequest( $"{GraphHelper.MicrosoftGraphBaseURI}v1.0/users/{userId}/photo/$value", mem, "image/jpeg", accessToken); } } return(result); }
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); }
private void AddResourceTokens(Web web, LocalizationCollection localizations, FileConnectorBase connector) { if (localizations != null && localizations.Any()) { // Read all resource keys in a list List <Tuple <string, uint, string> > resourceEntries = new List <Tuple <string, uint, string> >(); foreach (var localizationEntry in localizations) { var filePath = localizationEntry.ResourceFile; using (var stream = connector.GetFileStream(filePath)) { if (stream != null) { #if !NETSTANDARD2_0 using (ResXResourceReader resxReader = new ResXResourceReader(stream)) #else using (ResourceReader resxReader = new ResourceReader(stream)) #endif { foreach (DictionaryEntry entry in resxReader) { resourceEntries.Add(new Tuple <string, uint, string>(entry.Key.ToString(), (uint)localizationEntry.LCID, entry.Value.ToString().Replace("\"", """))); } } } } } var uniqueKeys = resourceEntries.Select(k => k.Item1).Distinct(); foreach (var key in uniqueKeys) { var matches = resourceEntries.Where(k => k.Item1 == key); var entries = matches.Select(k => new ResourceEntry() { LCID = k.Item2, Value = k.Item3 }).ToList(); LocalizationToken token = new LocalizationToken(web, key, entries); _tokens.Add(token); } } }
private static Microsoft.SharePoint.Client.ContentType CreateContentType(Web web, ContentType templateContentType, TokenParser parser, FileConnectorBase connector, List <Microsoft.SharePoint.Client.ContentType> existingCTs = null, List <Microsoft.SharePoint.Client.Field> existingFields = null) { var name = parser.ParseString(templateContentType.Name); var description = parser.ParseString(templateContentType.Description); var id = parser.ParseString(templateContentType.Id); var group = parser.ParseString(templateContentType.Group); var createdCT = web.CreateContentType(name, description, id, group); foreach (var fieldRef in templateContentType.FieldRefs) { var field = web.Fields.GetById(fieldRef.Id); web.AddFieldToContentType(createdCT, field, fieldRef.Required, fieldRef.Hidden); } createdCT.ReadOnly = templateContentType.ReadOnly; createdCT.Hidden = templateContentType.Hidden; createdCT.Sealed = templateContentType.Sealed; if (!string.IsNullOrEmpty(parser.ParseString(templateContentType.DocumentTemplate))) { createdCT.DocumentTemplate = parser.ParseString(templateContentType.DocumentTemplate); } if (!String.IsNullOrEmpty(templateContentType.NewFormUrl)) { createdCT.NewFormUrl = templateContentType.NewFormUrl; } if (!String.IsNullOrEmpty(templateContentType.EditFormUrl)) { createdCT.EditFormUrl = templateContentType.EditFormUrl; } if (!String.IsNullOrEmpty(templateContentType.DisplayFormUrl)) { createdCT.DisplayFormUrl = templateContentType.DisplayFormUrl; } // If the CT is a DocumentSet if (templateContentType.DocumentSetTemplate != null) { // Retrieve a reference to the DocumentSet Content Type Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate documentSetTemplate = Microsoft.SharePoint.Client.DocumentSet.DocumentSetTemplate.GetDocumentSetTemplate(web.Context, createdCT); if (!String.IsNullOrEmpty(templateContentType.DocumentSetTemplate.WelcomePage)) { // TODO: Customize the WelcomePage of the DocumentSet } foreach (String ctId in templateContentType.DocumentSetTemplate.AllowedContentTypes) { Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == ctId); if (ct != null) { documentSetTemplate.AllowedContentTypes.Add(ct.Id); } } foreach (var doc in templateContentType.DocumentSetTemplate.DefaultDocuments) { Microsoft.SharePoint.Client.ContentType ct = existingCTs.FirstOrDefault(c => c.StringId == doc.ContentTypeId); if (ct != null) { using (Stream fileStream = connector.GetFileStream(doc.FileSourcePath)) { documentSetTemplate.DefaultDocuments.Add(doc.Name, ct.Id, ReadFullStream(fileStream)); } } } foreach (var sharedField in templateContentType.DocumentSetTemplate.SharedFields) { Microsoft.SharePoint.Client.Field field = existingFields.FirstOrDefault(f => f.Id == sharedField); if (field != null) { documentSetTemplate.SharedFields.Add(field); } } foreach (var welcomePageField in templateContentType.DocumentSetTemplate.WelcomePageFields) { Microsoft.SharePoint.Client.Field field = existingFields.FirstOrDefault(f => f.Id == welcomePageField); if (field != null) { documentSetTemplate.WelcomePageFields.Add(field); } } documentSetTemplate.Update(true); web.Context.ExecuteQueryRetry(); } web.Context.Load(createdCT); web.Context.ExecuteQueryRetry(); return(createdCT); }
internal static void ProcessFiles(ProvisioningHierarchy tenantTemplate, string templateFileName, FileConnectorBase fileSystemConnector, FileConnectorBase connector, Action <string> progress) { var templateFile = ReadTenantTemplate.LoadProvisioningHierarchyFromFile(templateFileName, null, null); if (tenantTemplate.Tenant?.AppCatalog != null) { foreach (var app in tenantTemplate.Tenant.AppCatalog.Packages) { progress($"Processing {app.Src}"); AddFile(app.Src, templateFile, fileSystemConnector, connector); } } if (tenantTemplate.Tenant?.SiteScripts != null) { foreach (var siteScript in tenantTemplate.Tenant.SiteScripts) { progress($"Processing {siteScript.JsonFilePath}"); AddFile(siteScript.JsonFilePath, templateFile, fileSystemConnector, connector); } } if (tenantTemplate.Localizations != null && tenantTemplate.Localizations.Any()) { foreach (var location in tenantTemplate.Localizations) { progress($"Processing {location.ResourceFile}"); AddFile(location.ResourceFile, templateFile, fileSystemConnector, connector); } } foreach (var template in tenantTemplate.Templates) { if (template.WebSettings != null && !String.IsNullOrEmpty(template.WebSettings.SiteLogo)) { // is it a file? var isFile = false; try { using (var fileStream = fileSystemConnector.GetFileStream(template.WebSettings.SiteLogo)) { isFile = fileStream != null; } } catch { } if (isFile) { progress($"Processing {template.WebSettings.SiteLogo}"); AddFile(template.WebSettings.SiteLogo, templateFile, fileSystemConnector, connector); } } if (template.Files.Any()) { foreach (var file in template.Files) { progress($"Processing {file.Src}"); AddFile(file.Src, templateFile, fileSystemConnector, connector); } } if (template.Lists.Any()) { foreach (var list in template.Lists) { if (list.DataRows.Any()) { foreach (var dataRow in list.DataRows) { if (dataRow.Attachments.Any()) { progress("List attachments"); foreach (var attachment in dataRow.Attachments) { AddFile(attachment.Src, templateFile, fileSystemConnector, connector); } } } } } } } if (templateFile.Connector is ICommitableFileConnector) { ((ICommitableFileConnector)templateFile.Connector).Commit(); } }
/// <summary> /// Creates a new Team from a PnP Provisioning Schema definition /// </summary> /// <param name="scope">The PnP Provisioning Scope</param> /// <param name="parser">The PnP Token Parser</param> /// <param name="connector">The PnP File connector</param> /// <param name="team">The Team to provision</param> /// <param name="accessToken">The OAuth 2.0 Access Token</param> /// <returns>The provisioned Team as a JSON object</returns> private static JToken CreateTeamFromProvisioningSchema(PnPMonitoredScope scope, TokenParser parser, FileConnectorBase connector, Team team, string accessToken) { String teamId = null; // If we have to Clone an existing Team if (!String.IsNullOrWhiteSpace(team.CloneFrom)) { teamId = CloneTeam(scope, team, parser, accessToken); } // If we start from an already existing Group else if (!String.IsNullOrEmpty(team.GroupId)) { // We need to parse the GroupId, if it is a token var parsedGroupId = parser.ParseString(team.GroupId); // Check if the Group exists if (GroupExistsById(scope, parsedGroupId, accessToken)) { // Then promote the Group into a Team or update it, if it already exists teamId = CreateOrUpdateTeamFromGroup(scope, team, parser, parsedGroupId, accessToken); } else { // Log the exception and return NULL (i.e. cancel) scope.LogError(CoreResources.Provisioning_ObjectHandlers_Teams_Team_GroupDoesNotExists, parsedGroupId); return(null); } } // Otherwise create a Team from scratch else { teamId = CreateOrUpdateTeam(scope, team, parser, accessToken); } if (!String.IsNullOrEmpty(teamId)) { // Wait for the Team to be ready Boolean wait = true; Int32 iterations = 0; while (wait) { iterations++; try { var jsonOwners = HttpHelper.MakeGetRequestForString($"{GraphHelper.MicrosoftGraphBaseURI}v1.0/groups/{teamId}/owners?$select=id", accessToken); if (!String.IsNullOrEmpty(jsonOwners)) { wait = false; } } catch (Exception) { // In case of exception wait for 5 secs System.Threading.Thread.Sleep(TimeSpan.FromSeconds(5)); } // Don't wait more than 1 minute if (iterations > 12) { wait = false; } } // And now we configure security, channels, and apps if (!SetGroupSecurity(scope, team, teamId, accessToken)) { return(null); } if (!SetTeamChannels(scope, parser, team, teamId, accessToken)) { return(null); } if (!SetTeamApps(scope, team, teamId, accessToken)) { return(null); } // So far the Team's photo cannot be set if we don't have an already existing mailbox // if (!SetTeamPhoto(scope, parser, connector, team, teamId, accessToken)) return null; // Call Archive or Unarchive for the current Team ArchiveTeam(scope, teamId, team.Archived, accessToken); try { // Get the whole Team that we just created and return it back as the method result return(JToken.Parse(HttpHelper.MakeGetRequestForString($"{GraphHelper.MicrosoftGraphBaseURI}v1.0/teams/{teamId}", accessToken))); } catch (Exception ex) { scope.LogError(CoreResources.Provisioning_ObjectHandlers_Teams_Team_FetchingError, ex.Message); } } return(null); }
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); }
public void DownloadWorkflowFile(string workflowID, FileConnectorBase writer, Stream fileStream, WorkflowLevel workflowLevel) { writer.SaveFileStream(workflowID + ".xml", workflowFolderName, fileStream); }