using System; using System.IO; using System.Linq; using System.Threading; using System.Web.UI.WebControls.WebParts; using System.Xml; using Microsoft.SharePoint; using Microsoft.SharePoint.Deployment; using Microsoft.SharePoint.Navigation; using Microsoft.SharePoint.Publishing; using Microsoft.SharePoint.Publishing.Navigation; using Microsoft.SharePoint.WebPartPages; using Taloyhtio.CondoUpdate.Common; using WebPart = System.Web.UI.WebControls.WebParts.WebPart; namespace CondoUpdate.AddDomusPage { public class UpdaterImpl : ICondoUpdater { public event EventHandler OnNotify; public void Update(object args) { string url = args as string; if (string.IsNullOrEmpty(url)) { this.warn("Url is empty"); return; } try { this.updateImpl(url); } catch(Exception x) { this.error("Error occured during updating of Condo '{0}':\n{1}\n{2}", url, x.Message, x.StackTrace); } } private void updateImpl(string url) { string sourceSiteUrl = "http://taloyhtio.mobimus.com/pirkanisannointikeskus/Kylmanojankatu4-8/"; string targetSiteUrl = url; string pageName = "Tilintarkastus.aspx"; string fileToImport = "ExportedPage.cmp"; if (!this.import(sourceSiteUrl, targetSiteUrl, pageName, fileToImport)) { this.warn("Import was not performed. Web site will be skipped"); return; } this.fixWebParts(url, pageName); this.changeGlobalNavigation(url, pageName); this.addPermissionsToPage(url, pageName); } private void changeGlobalNavigation(string url, string pageName) { using (var site = new SPSite(url)) { using (var web = site.OpenWeb()) { var pweb = PublishingWeb.GetPublishingWeb(web); var globalNavigation = pweb.Navigation.GlobalNavigationNodes; string title = pageName.Replace(".aspx", ""); var nodePage = globalNavigation.Cast().FirstOrDefault(n => n.Title == title); if (nodePage != null) { this.warn("Navigation node already exists for page '{0}'", pageName); return; } var page = pweb.GetPublishingPages().FirstOrDefault(p => string.Compare(p.Name, pageName, true) == 0); if (page != null) { page.IncludeInGlobalNavigation = false; page.IncludeInCurrentNavigation = false; } var node = createNode(title, page.Url, globalNavigation, ""); var nodeSite = globalNavigation.Cast().FirstOrDefault(n => n.Title == "Hallitukselle"); if (nodeSite != null) { node.Move(globalNavigation, nodeSite); } else { this.warn("Navigation node for Hallitukselle site not found for page '{0}'. Node position won't be changed", pageName); } } } } private SPNavigationNode createNode(string targetTitle, string targetUrl, SPNavigationNodeCollection globalNavigation, string target) { var node = SPNavigationSiteMapNode.CreateSPNavigationNode(targetTitle, targetUrl, NodeTypes.AuthoredLinkPlain, globalNavigation); var dt = DateTime.Now; node.Properties["CreatedDate"] = dt; node.Properties["LastModifiedDate"] = dt; node.Properties["Description"] = ""; node.Properties["Target"] = target; node.Update(); return node; } private void addPermissionsToPage(string url, string pageName) { using (var site = new SPSite(url)) { using (var web = site.OpenWeb()) { var pweb = PublishingWeb.GetPublishingWeb(web); var item = pweb.PagesList.Items.Cast().FirstOrDefault( i => { return (i.File != null && string.Compare(i.File.Name, pageName, true) == 0); }); if (item == null) { return; } string pmcGroupName = string.Format("{0} - Isännöitsijät", web.Site.RootWeb.Title); if (SecurityHelper.IsGroupExist(web, pmcGroupName)) { var group = SecurityHelper.GetSiteGroup(web, pmcGroupName); var pmcRoleDefinition = web.RoleDefinitions.Cast().FirstOrDefault(r => r.Name == "Isännöitsijä"); if (pmcRoleDefinition == null) { return; } var pmcRoleAssignment = new SPRoleAssignment(group); SecurityHelper.AssignRoleToSecurableObject(web, item, pmcRoleDefinition, pmcRoleAssignment, false); } string hallitusGroupName = string.Format("{0} - Hallitus", web.Title); if (SecurityHelper.IsGroupExist(web, hallitusGroupName)) { var group = SecurityHelper.GetSiteGroup(web, hallitusGroupName); SecurityHelper.AssignGroupRoleToSecurableObject(web, item, SPRoleType.Reader, group); } } } } private bool import(string sourceSiteUrl, string targetSiteUrl, string pageName, string fileToImport) { using (var targetSite = new SPSite(targetSiteUrl)) { using (var targetWeb = targetSite.OpenWeb()) { var targetList = targetWeb.Lists.Cast().FirstOrDefault(l => l.Title == "Sivut"); var item = targetList.Items.Cast().FirstOrDefault( i => { return (i.File != null && string.Compare(i.File.Name, pageName, true) == 0); }); if (item != null) { this.warn("Page '{0}' already exists on web '{1}'", pageName, targetWeb.Url); return false; } using (var sourceSite = new SPSite(sourceSiteUrl)) { using (var sourceWeb = sourceSite.OpenWeb()) { var sourcePweb = PublishingWeb.GetPublishingWeb(sourceWeb); var targetPweb = PublishingWeb.GetPublishingWeb(targetWeb); return importImpl(targetWeb.Url, sourcePweb.PagesList.RootFolder.ServerRelativeUrl, targetPweb.PagesList.RootFolder.ServerRelativeUrl, pageName, fileToImport); } } } } } private bool importImpl(string fullTargetWebURL, string sourceItemParentUrl, string destinationItemParentUrl, string pageName, string fileToImport) { if (!File.Exists(fileToImport)) { this.error("File '{0}' not found", fileToImport); return false; } var importSettings = new SPImportSettings(); importSettings.BaseFileName = fileToImport; importSettings.FileLocation = Directory.GetCurrentDirectory(); importSettings.SiteUrl = fullTargetWebURL; importSettings.RetainObjectIdentity = false; importSettings.IncludeSecurity = SPIncludeSecurity.None; importSettings.UpdateVersions = SPUpdateVersions.Append; importSettings.UserInfoDateTime = SPImportUserInfoDateTimeOption.ImportAll; importSettings.FileCompression = true; importSettings.CommandLineVerbose = true; importSettings.Validate(); var import = new SPImport(importSettings); bool importCompeted = false; string importErrorMessage = ""; import.Started += (s, e) => { if (e.RootObjects == null) return; var rootObjects = e.RootObjects; foreach (SPImportObject item in rootObjects) { this.info(" Check import object: SourceUrl = {0}, TargetParentUrl = {1}", item.SourceUrl, item.TargetParentUrl); if (string.Compare(item.TargetParentUrl, sourceItemParentUrl + "/", true) == 0 || (item.SourceUrl.Contains("/" + pageName) && (item.Type == SPDeploymentObjectType.ListItem || item.Type == SPDeploymentObjectType.File))) { this.info(" Retarget item TargetParentUrl url from '{0}' to '{1}'", item.TargetParentUrl, destinationItemParentUrl + "/"); item.TargetParentUrl = destinationItemParentUrl + "/"; } } }; import.Error += (s, e) => { importErrorMessage = e.ErrorMessage; importCompeted = true; }; import.Completed += (s, e) => { importCompeted = true; }; //Log.Comment("Starting import to URL {0}", siteURL); importCompeted = false;//not thread safe but we dont need to be thread safe importErrorMessage = null; import.Run(); while (!importCompeted) { Thread.Sleep(1000); } if (importErrorMessage != null) { this.info("Problem occured during importing of " + sourceItemParentUrl + " and export file " + fileToImport + " " + importErrorMessage); return false; } return true; } private void fixWebParts(string url, string pageName) { using (var site = new SPSite(url)) { using (var web = site.OpenWeb()) { var pweb = PublishingWeb.GetPublishingWeb(web); SPLimitedWebPartManager webPartManager = null; try { //this.info("Get start page"); var item = pweb.PagesList.Items.Cast().FirstOrDefault( i => { return (i.File != null && string.Compare(i.File.Name, pageName, true) == 0); }); if (item == null) { this.error("Page '{0}' not found on web '{1}'", pageName, pweb.Url); return; } var file = item.File; if (file == null) { this.error("Page is null. Site won't be updated"); return; } if (file.CheckOutStatus == SPFile.SPCheckOutStatus.None) { //this.info("Checkout start page"); file.CheckOut(); } else { // if file was checked out by another user, need undo check out and check in again in order to avoid errors // when add web part //this.info("Start page is already checked out. Undo previous check out and check out it again"); file.UndoCheckOut(); file.CheckOut(); } //this.info("Get web part manager"); webPartManager = file.GetLimitedWebPartManager(PersonalizationScope.Shared); if (webPartManager == null) { this.error("Web part manager is null. Site won't be updated"); file.UndoCheckOut(); return; } //this.info("Search for DataFormWebPart with title '{0}' on the start page", webPartTitle); ContentEditorWebPart contentEditorWebPart = null; PageViewerWebPart pageViewerWebPart = null; var webParts = webPartManager.WebParts; if (webParts != null) { foreach (WebPart wp in webParts) { if (wp.GetType().FullName == "Microsoft.SharePoint.WebPartPages.ContentEditorWebPart") { contentEditorWebPart = wp as ContentEditorWebPart; } else if (wp.GetType().FullName == "Microsoft.SharePoint.WebPartPages.PageViewerWebPart") { pageViewerWebPart = wp as PageViewerWebPart; } } } string oldPart = "/Kylmanojankatu4-8/"; string newPart = pweb.Url.Substring(pweb.Url.LastIndexOf("/")) + "/"; if (contentEditorWebPart != null) { var doc = new XmlDocument(); var el = doc.CreateElement("root"); el.InnerText = contentEditorWebPart.Content.InnerText.Replace(oldPart, newPart); contentEditorWebPart.Content = el; webPartManager.SaveChanges(contentEditorWebPart); } if (pageViewerWebPart != null) { pageViewerWebPart.ContentLink = pageViewerWebPart.ContentLink.Replace(oldPart, newPart); webPartManager.SaveChanges(pageViewerWebPart); } //this.info("Checkin file"); file.Update(); file.CheckIn("Update web parts"); if (file.Item.ParentList.EnableMinorVersions) { file.Publish("Update web parts"); } //this.info("Web part was sucessfully updated"); } catch (Exception x) { this.error("Error occured when update web part on '{0}' site:\n{1}\n{2}", pweb.Web.Url, x.Message, x.StackTrace); var file = pweb.DefaultPage; if (file.CheckOutStatus != SPFile.SPCheckOutStatus.None) { file.UndoCheckOut(); } } finally { if (webPartManager != null) { if (webPartManager.Web != null) { webPartManager.Web.Dispose(); } webPartManager.Dispose(); } } } } } private void info(string msg, params object[] args) { this.notify(LogLevel.Info, msg, args); } private void warn(string msg, params object[] args) { this.notify(LogLevel.Warn, msg, args); } private void error(string msg, params object[] args) { this.notify(LogLevel.Error, msg, args); } private void notify(LogLevel level, string msg, params object[] args) { this.notify(level, string.Format(msg, args)); } private void notify(LogLevel level, string msg) { if (this.OnNotify != null) { this.OnNotify(this, new LogEventArgs { LogLevel = level, Message = msg }); } } } public static class SecurityHelper { public static void AddUserToGroup(SPWeb web, string loginName, string email, string name, string groupName) { // don't need to add user in group second time if (IsUserInGroup(web, loginName, groupName)) { return; } if (!containsUser(web, loginName)) { web.EnsureUser(loginName); } var group = web.SiteGroups[groupName]; group.AddUser(loginName, email, name, string.Empty); } public static void AddUserToGroup(SPWeb web, SPUser user, SPGroup group) { // don't need to add user in group second time if (IsUserInGroup(web, user.LoginName, group.Name)) { return; } group.AddUser(user); } public static bool IsUserInGroup(SPWeb web, string loginName, string groupName) { var group = web.SiteGroups[groupName]; return group.Users.Cast().Any(u => string.Compare(u.LoginName, loginName, true) == 0); } public static void CreateUser(SPWeb web, string loginName, string email, string name) { if (!containsUser(web, loginName)) { try { var user = web.EnsureUser(loginName); user.Email = email; user.Update(); } catch (SPException) { // EnsureUser can fail on one of WFEs because of some reason. // To avoid this error add user manually //string name = getUserName(loginName); if (!string.IsNullOrEmpty(name)) { web.AllUsers.Add(loginName, email, name, ""); } } } } public static bool containsUser(SPWeb web, string loginName) { return web.AllUsers.Cast().Any(u => string.Compare(u.LoginName, loginName, true) == 0); } // private static string getUserName(string loginName) // { // if (string.IsNullOrEmpty(loginName)) // { // return string.Empty; // } // if (loginName.Contains("\\")) // { // return string.Empty; // } // string name = loginName.Substring(loginName.LastIndexOf("\\")); // return name; // } public static SPGroup EnsureSiteGroup(SPWeb web, string groupName) { if (!IsGroupExist(web, groupName)) { web.SiteGroups.Add(groupName, web.SiteAdministrators[0], null, string.Empty); } return web.SiteGroups[groupName]; } public static SPGroup GetSiteGroup(SPWeb web, string groupName) { return web.SiteGroups[groupName]; } public static bool IsGroupExist(SPWeb web, string groupName) { return web.SiteGroups.Cast().Any(g => string.Compare(g.Name, groupName, true) == 0); } public static void AssignGroupRoleToSecurableObject(SPWeb web, ISecurableObject securableObject, SPRoleType roleType, SPGroup group) { SPRoleDefinition roleDefinition = web.RoleDefinitions.GetByType(roleType); AssignGroupRoleToSecurableObject(web, securableObject, roleDefinition, group, false); } public static void AssignGroupRoleToSecurableObject(SPWeb web, ISecurableObject securableObject, SPRoleType roleType, SPGroup group, bool copyRoleAssignment) { SPRoleDefinition roleDefinition = web.RoleDefinitions.GetByType(roleType); AssignGroupRoleToSecurableObject(web, securableObject, roleDefinition, group, copyRoleAssignment); } public static void AssignGroupRoleToSecurableObject(SPWeb web, ISecurableObject securableObject, SPRoleDefinition roleDefinition, SPGroup group, bool copyRoleAssignment) { SPRoleAssignment roleAssignment = new SPRoleAssignment(group); AssignRoleToSecurableObject(web, securableObject, roleDefinition, roleAssignment, copyRoleAssignment); } public static void AssignGroupRoleToSecurableObject(SPWeb web, ISecurableObject securableObject, SPRoleDefinition roleDefinition, SPGroup group) { SPRoleAssignment roleAssignment = new SPRoleAssignment(group); AssignRoleToSecurableObject(web, securableObject, roleDefinition, roleAssignment, true); } public static void AssignUserRoleToSecurableObject(SPWeb web, ISecurableObject securableObject, SPRoleType roleType, SPUser user) { SPRoleAssignment roleAssignment = new SPRoleAssignment(user); SPRoleDefinition roleDefinition = web.RoleDefinitions.GetByType(roleType); AssignRoleToSecurableObject(web, securableObject, roleDefinition, roleAssignment, true); } public static void AssignRoleToSecurableObject(SPWeb web, ISecurableObject securableObject, SPRoleDefinition roleDefinition, SPRoleAssignment roleAssignment, bool copyRoleAssignment) { roleAssignment.RoleDefinitionBindings.Add(roleDefinition); if (!securableObject.HasUniqueRoleAssignments) { securableObject.BreakRoleInheritance(copyRoleAssignment); // 2013-01-22 apetuhov: BreakRoleInheritance causes reset of AllowUnsafeUpdates to false. // See http://hristopavlov.wordpress.com/2008/05/16/what-you-need-to-know-about-allowunsafeupdates/ if (web != null && !web.AllowUnsafeUpdates) { web.AllowUnsafeUpdates = true; } if (securableObject is SPWeb) { var secureWeb = securableObject as SPWeb; if (!secureWeb.AllowUnsafeUpdates) { secureWeb.AllowUnsafeUpdates = true; } } } securableObject.RoleAssignments.Add(roleAssignment); } } }