private static XDoc BuildXmlSiteMap(PageBE current, XDoc doc, Dictionary <ulong, PageBE> allowedPagesById) { doc.Add(PageBL.GetPageXml(current, null)); XDoc y = doc[doc.AsXmlNode.LastChild].Start("subpages"); if (!ArrayUtil.IsNullOrEmpty(current.ChildPages)) { PageBE[] visibleChildren = Array.FindAll(current.ChildPages, delegate(PageBE child) { return(allowedPagesById.ContainsKey(child.ID)); }); foreach (PageBE child in visibleChildren) { BuildXmlSiteMap(child, y, allowedPagesById); } } y.End(); return(doc); }
private XDoc AppendFileXml(XDoc doc, ResourceBE file, string fileSuffix, bool?explicitRevisionInfo, UserBE updatedByUser, PageBE parentPage) { bool requiresEnd = false; string fileElement = string.IsNullOrEmpty(fileSuffix) ? "file" : "file." + fileSuffix; if (doc == null || doc.IsEmpty) { doc = new XDoc(fileElement); } else { doc.Start(fileElement); requiresEnd = true; } doc.Attr("id", file.MetaXml.FileId ?? 0); doc.Attr("revision", file.Revision); doc.Attr("res-id", file.ResourceId); if (file.IsHidden) { doc.Attr("hidden", true); } doc.Attr("href", GetUriInfo(file, explicitRevisionInfo)); doc.Start("filename").Value(file.Name).End(); //Description comes from a property string description = string.Empty; if (!ArrayUtil.IsNullOrEmpty(file.ChildResources)) { ResourceBE descProp = Array.Find(file.ChildResources, p => p != null && p.ResourceType == ResourceBE.Type.PROPERTY && p.Name.EqualsInvariantIgnoreCase(PropertyBL.PROP_DESC)); if (descProp != null) { description = descProp.Content.ToText(); } } doc.Start("description").Value(description).End(); doc.Start("contents") .Attr("type", file.MimeType == null ? null : file.MimeType.ToString()) .Attr("size", file.Size); if ((file.MetaXml.ImageHeight ?? 0) > 0 && (file.MetaXml.ImageWidth ?? 0) > 0) { doc.Attr("width", file.MetaXml.ImageWidth.Value); doc.Attr("height", file.MetaXml.ImageHeight.Value); } doc.Attr("href", GetUriContent(file, explicitRevisionInfo)); doc.End(); //contents if ((file.MetaXml.ImageWidth ?? 0) > 0 && (file.MetaXml.ImageHeight ?? 0) > 0) { string previewMime = AttachmentPreviewBL.ResolvePreviewMime(file.MimeType).ToString(); doc.Start("contents.preview") .Attr("rel", "thumb") .Attr("type", previewMime) .Attr("maxwidth", _dekiContext.Instance.ImageThumbPixels) .Attr("maxheight", _dekiContext.Instance.ImageThumbPixels) .Attr("href", GetUriContent(file, explicitRevisionInfo).With("size", "thumb")); if (!file.IsHeadRevision() || (explicitRevisionInfo ?? false)) { doc.Attr("revision", file.Revision); } doc.End(); //contents.preview: thumb doc.Start("contents.preview") .Attr("rel", "webview") .Attr("type", previewMime) .Attr("maxwidth", _dekiContext.Instance.ImageWebviewPixels) .Attr("maxheight", _dekiContext.Instance.ImageWebviewPixels) .Attr("href", GetUriContent(file, explicitRevisionInfo).With("size", "webview")); if (!file.IsHeadRevision() || (explicitRevisionInfo ?? false)) { doc.Attr("revision", file.Revision); } doc.End(); //contents.preview: webview } doc.Start("date.created").Value(file.Timestamp).End(); if (updatedByUser != null) { doc.Add(UserBL.GetUserXml(updatedByUser, "createdby", Utils.ShowPrivateUserInfo(updatedByUser))); } if (file.ResourceIsDeleted && ((file.ChangeMask & ResourceBE.ChangeOperations.DELETEFLAG) == ResourceBE.ChangeOperations.DELETEFLAG)) { if (updatedByUser != null) { doc.Add(UserBL.GetUserXml(updatedByUser, "deletedby", Utils.ShowPrivateUserInfo(updatedByUser))); } doc.Start("date.deleted").Value(file.Timestamp).End(); } if (file.IsHeadRevision() && !(explicitRevisionInfo ?? false) && !file.ResourceIsDeleted) { uint filteredCount = _session.Resources_GetRevisionCount(file.ResourceId, DEFAULT_REVISION_FILTER); doc.Start("revisions"); doc.Attr("count", filteredCount); doc.Attr("totalcount", file.Revision); doc.Attr("href", GetUri(file).At("revisions")); doc.End(); } else { if (file.ChangeMask != ResourceBE.ChangeOperations.UNDEFINED) { doc.Start("user-action").Attr("type", file.ChangeMask.ToString().ToLowerInvariant()).End(); } } //parent page is passed in for verbose output only if (parentPage != null) { doc.Add(PageBL.GetPageXml(parentPage, "parent")); } if (file.ChildResources != null) { List <ResourceBE> properties = new List <ResourceBE>(); foreach (ResourceBE p in file.ChildResources) { properties.Add(p); } doc = PropertyBL.Instance.GetPropertyXml(properties.ToArray(), GetUri(file), null, null, doc); } if (file.IsHidden) { uint?userIdHiddenBy = file.MetaXml.RevisionHiddenUserId; if (userIdHiddenBy != null) { UserBE userHiddenBy = UserBL.GetUserById(userIdHiddenBy.Value); if (userHiddenBy != null) { doc.Add(UserBL.GetUserXml(userHiddenBy, "hiddenby", Utils.ShowPrivateUserInfo(userHiddenBy))); } } doc.Elem("date.hidden", file.MetaXml.RevisionHiddenTimestamp ?? DateTime.MinValue); doc.Elem("description.hidden", file.MetaXml.RevisionHiddenComment ?? string.Empty); } if (requiresEnd) { doc.End(); //file } return(doc); }
private static XDoc AppendCommentXml(XDoc doc, CommentBE comment, string suffix, bool?includeParentInfo) { bool requiresEnd = false; string commentElement = string.IsNullOrEmpty(suffix) ? "comment" : "comment." + suffix; if (doc == null || doc.IsEmpty) { doc = new XDoc(commentElement); } else { doc.Start(commentElement); requiresEnd = true; } doc.Attr("id", comment.Id).Attr("href", CommentBL.GetUri(comment)); //include parentinfo by default if the parent page is populated PageBE page = PageBL.GetPageById(comment.PageId); if (page != null && (includeParentInfo ?? true)) { doc.Add(PageBL.GetPageXml(page, "parent")); } UserBE posterUser = UserBL.GetUserById(comment.PosterUserId); if (posterUser != null) { doc.Add(UserBL.GetUserXml(posterUser, "createdby", Utils.ShowPrivateUserInfo(posterUser))); } doc.Start("date.posted").Value(comment.CreateDate).End(); doc.Start("title").Value(comment.Title).End(); doc.Start("number").Value(comment.Number).End(); //Note (MaxM): Replytoid/replies not yet exposed //if (ReplyToId.HasValue) { // doc.Start("comment.replyto") // .Attr("number", ReplyToId.Value.ToString()) // .Attr("href", DekiContext.Current.ApiUri.At("pages", PageId.ToString(), "comments", ReplyToId.Value.ToString())).End(); //} bool displayContent = true; //Only display content for nondeleted comments or for admins if (comment.IsCommentMarkedAsDeleted) { displayContent = PermissionsBL.IsUserAllowed(DekiContext.Current.User, Permissions.ADMIN); } if (displayContent) { doc.Start("content") .Attr("type", comment.ContentMimeType) .Attr("href", CommentBL.GetUri(comment).At("content")) .Value(comment.Content).End(); } if (comment.LastEditUserId.HasValue) { UserBE lastEditUser = UserBL.GetUserById(comment.LastEditUserId.Value); if (null != lastEditUser) { doc.Add(UserBL.GetUserXml(lastEditUser, "editedby", Utils.ShowPrivateUserInfo(lastEditUser))); doc.Start("date.edited").Value(comment.LastEditDate).End(); } } if (comment.IsCommentMarkedAsDeleted && comment.DeleterUserId.HasValue) { UserBE deleteUser = UserBL.GetUserById(comment.DeleterUserId.Value); if (null != deleteUser) { doc.Add(UserBL.GetUserXml(deleteUser, "deletedby", Utils.ShowPrivateUserInfo(deleteUser))); doc.Start("date.deleted").Value(comment.DeleteDate).End(); } } if (requiresEnd) { doc.End(); //comment } return(doc); }
public Yield PostUsersAllowed(DreamContext context, DreamMessage request, Result <DreamMessage> response) { var permissionMask = context.GetParam <ulong>("mask", 0); var operationList = context.GetParam("operations", ""); var user = GetUserFromUrlMustExist(); var verbose = context.GetParam("verbose", true); var invert = context.GetParam("invert", false); // Use comma separated permission list or permissionmask from request. var permissions = Permissions.NONE; if (permissionMask != 0) { permissions = (Permissions)permissionMask; } // Convert operation list to mask combined with provided mask if (!string.IsNullOrEmpty(operationList)) { try { permissions |= (Permissions)PermissionsBL.MaskFromPermissionList(PermissionsBL.PermissionListFromString(operationList)); } catch { throw new UserOperationListInvalidArgumentException(); } } IEnumerable <ulong> pageIds; var textOutput = false; if (request.HasDocument) { if (!request.ToDocument().HasName("pages")) { throw new UserExpectedRootNodePagesInvalidDocumentException(); } pageIds = from pageIdXml in request.ToDocument()["page/@id"] let pageId = pageIdXml.AsULong where pageId.HasValue select pageId.Value; } else if (verbose) { throw new UserPageFilterVerboseNotAllowedException(); } else if (!request.ContentType.Match(MimeType.TEXT)) { throw new UserPageFilterInvalidInputException(); } else { textOutput = true; pageIds = request.ToText().CommaDelimitedToULong(); } IEnumerable <ulong> filtered; var allowedPages = PermissionsBL.FilterDisallowed(user, pageIds, false, out filtered, permissions); if (textOutput) { var output = invert ? filtered.ToCommaDelimitedString() : allowedPages.ToCommaDelimitedString(); response.Return(DreamMessage.Ok(MimeType.TEXT, output ?? string.Empty)); } else { var responseDoc = new XDoc("pages"); if (invert) { foreach (var pageId in filtered) { responseDoc.Start("page").Attr("id", pageId).End(); } } else if (allowedPages.Any()) { if (verbose) { foreach (var page in PageBL.GetPagesByIdsPreserveOrder(allowedPages)) { responseDoc.Add(PageBL.GetPageXml(page, null)); } } else { foreach (var pageId in allowedPages) { responseDoc.Start("page").Attr("id", pageId).End(); } } } response.Return(DreamMessage.Ok(responseDoc)); } yield break; }
public static XDoc RestoreDeletedPage(uint pageid, Title newRootPath, string revertReason) { //Retrieve initial revisions of pages to restore //First item in the list is the page that initiated the transaction. //Talk pages are included. uint initialDeleteTranId = 0; IList <ArchiveBE> pagesToRestore = DbUtils.CurrentSession.Archive_GetPagesInTransaction(pageid, out initialDeleteTranId); TransactionBE initialDeleteTrans = DbUtils.CurrentSession.Transactions_GetById(initialDeleteTranId); //Validate deleted page + transaction if (pagesToRestore.Count == 0) { throw new PageArchiveLogicNotFoundException(pageid); } if (initialDeleteTrans == null) { throw new PageArchiveBadTransactionFatalException(initialDeleteTranId, pageid); } //TODO MaxM: move the above gathering of what pages to restore to another method. Make this private. //Look for title conflicts List <Title> titles = new List <Title>(); List <ulong> pageidsToRestore = new List <ulong>(); Dictionary <ulong, PageBE> restoredPagesById = null; DateTime utcTimestamp = DateTime.UtcNow; foreach (ArchiveBE p in pagesToRestore) { Title t = p.Title; if (newRootPath != null) { t = BuildNewTitlesForMovedPage(pagesToRestore[0].Title, p.Title, newRootPath); } titles.Add(t); pageidsToRestore.Add(p.LastPageId); } IList <PageBE> currentPages = DbUtils.CurrentSession.Pages_GetByTitles(titles.ToArray()); if (currentPages.Count > 0) { //Remove all conflicting redirect pages from target of restore if all conflicting pages are redirects List <PageBE> conflictingRedirects = new List <PageBE>(); foreach (PageBE p in currentPages) { if (p.IsRedirect) { conflictingRedirects.Add(p); } } if (currentPages.Count == conflictingRedirects.Count && conflictingRedirects.Count > 0) { //Remove existing redirects and refresh the conflicting pages list PageBL.DeletePages(conflictingRedirects.ToArray(), utcTimestamp, 0, false); currentPages = DbUtils.CurrentSession.Pages_GetByTitles(titles.ToArray()); } } if (currentPages.Count > 0) { //return the name(s) of the conflicting page title(s) StringBuilder conflictTitles = new StringBuilder(); foreach (PageBE p in currentPages) { if (conflictTitles.Length > 0) { conflictTitles.Append(", "); } conflictTitles.Append(p.Title.AsPrefixedUserFriendlyPath()); } throw new PageArchiveRestoreNamedPageConflictException(conflictTitles.ToString()); } //Gather revisions for all pages to be restored. //Revisions are sorted by timestamp: oldest first. Dictionary <ulong, IList <ArchiveBE> > revisionsByPageId = DbUtils.CurrentSession.Archive_GetRevisionsByPageIds(pageidsToRestore); uint restoredPageTranId = 0; try { TransactionBE newTrans = new TransactionBE(); newTrans.UserId = DekiContext.Current.User.ID; newTrans.PageId = pageid; newTrans.Title = pagesToRestore[0].Title; newTrans.Type = RC.PAGERESTORED; newTrans.TimeStamp = DateTime.UtcNow; restoredPageTranId = DbUtils.CurrentSession.Transactions_Insert(newTrans); //Pages must be restored in correct order (alphabetical ensures parent pages are restored before children). //pagesToRestore must be in alphabetical title order bool minorChange = false; foreach (ArchiveBE pageToRestore in pagesToRestore) { IList <ArchiveBE> revisions = null; if (revisionsByPageId.TryGetValue(pageToRestore.LastPageId, out revisions)) { //Optionally restore page to different title Title restoreToTitle = pageToRestore.Title; if (newRootPath != null) { restoreToTitle = BuildNewTitlesForMovedPage(pagesToRestore[0].Title, pageToRestore.Title, newRootPath); } RestorePageRevisionsForPage(revisions.ToArray(), restoreToTitle, restoredPageTranId, minorChange, utcTimestamp); DbUtils.CurrentSession.Archive_Delete(revisions.Select(e => e.Id).ToList()); } minorChange = true; } //Retrieve the restored pages restoredPagesById = PageBL.GetPagesByIdsPreserveOrder(pageidsToRestore).AsHash(e => e.ID); // Restore attachments IList <ResourceBE> attachmentsToRestore = ResourceBL.Instance.GetResourcesByChangeSet(initialDeleteTrans.Id, ResourceBE.Type.FILE); foreach (ResourceBE at in attachmentsToRestore) { PageBE restoredPage; if (restoredPagesById.TryGetValue(at.ParentPageId.Value, out restoredPage)) { AttachmentBL.Instance.RestoreAttachment(at, restoredPage, utcTimestamp, restoredPageTranId); } } //Update the old transaction as reverted initialDeleteTrans.Reverted = true; initialDeleteTrans.RevertTimeStamp = utcTimestamp; initialDeleteTrans.RevertUserId = DekiContext.Current.User.ID; initialDeleteTrans.RevertReason = revertReason; DbUtils.CurrentSession.Transactions_Update(initialDeleteTrans); } catch (Exception) { DbUtils.CurrentSession.Transactions_Delete(restoredPageTranId); throw; } //Build restore summary XDoc ret = new XDoc("pages.restored"); foreach (ulong restoredPageId in pageidsToRestore) { PageBE restoredPage = null; if (restoredPagesById.TryGetValue((uint)restoredPageId, out restoredPage)) { ret.Add(PageBL.GetPageXml(restoredPage, string.Empty)); } } return(ret); }
public static XDoc GetUserXmlVerbose(UserBE user, string relationAttr, bool showPrivateInfo, bool showGroups, bool showProperties) { XDoc userXml = GetUserXml(user, relationAttr, showPrivateInfo); userXml.Elem("date.created", user.CreateTimestamp); if (!IsAnonymous(user)) { PageBE homePage = GetHomePage(user); if (homePage != null && homePage.ID != 0) { userXml.Add(PageBL.GetPageXml(homePage, "home")); } } userXml.Start("status").Value(user.UserActive ? "active" : "inactive").End(); userXml.Start("date.lastlogin").Value(user.Touched).End(); userXml.Start("language").Value(user.Language).End(); userXml.Start("timezone").Value(user.Timezone).End(); ServiceBE authService = ServiceBL.GetServiceById(user.ServiceId); if (authService != null) { userXml.Add(ServiceBL.GetServiceXml(authService, "authentication")); } //Permissions for the user from user role userXml.Add(PermissionsBL.GetRoleXml(PermissionsBL.GetRoleById(user.RoleId), "user")); ulong effectivePermissions = PermissionsBL.CalculateEffectiveUserRights(user); //Effective permissions for the user from the role + group roles. userXml.Add(PermissionsBL.GetPermissionXml(effectivePermissions, "effective")); // Set of permissions revoked from the user userXml.Add(PermissionsBL.GetPermissionsRevokedXml(user)); // check if groups should be included if (showGroups) { userXml.Start("groups"); IList <GroupBE> groups = DbUtils.CurrentSession.Groups_GetByUser(user.ID); if (null != groups) { foreach (GroupBE g in groups) { userXml.Add(GroupBL.GetGroupXmlVerbose(g, null)); } } userXml.End(); } // retrieve properties for current user while providing an href for other users. if (showProperties && (DekiContext.Current != null && DekiContext.Current.User != null && DekiContext.Current.User.ID == user.ID)) { IList <ResourceBE> props = PropertyBL.Instance.GetUserProperties(user.ID); userXml = PropertyBL.Instance.GetPropertyXml(props, GetUri(user), null, null, userXml); } else { userXml.Start("properties").Attr("href", GetUri(user).At("properties")).End(); } // TODO Max: get <subscriptions> (watchlist) not implemented return(userXml); }