コード例 #1
0
        public static CommentBE PostNewComment(PageBE page, DreamMessage request, DreamContext context) {
            ValidateCommentText(request.ContentType, request.AsText());

            CommentBE comment = new CommentBE();
            comment.Title = context.GetParam("title", string.Empty);
            comment.PageId = page.ID;
            comment.Content = request.AsText();
            comment.ContentMimeType = request.ContentType.ToString();
            comment.PosterUserId = DekiContext.Current.User.ID;
            comment.CreateDate = DateTime.UtcNow;

            //Note (MaxM): Replytoid/replies not yet exposed
            //ulong replyToId = context.GetParam<ulong>("replyto", 0);
            //if (replyToId == 0)
            //    newComment.ReplyToId = null;
            //else
            //    newComment.ReplyToId = replyToId;

            ushort commentNumber;
            uint commentId = DbUtils.CurrentSession.Comments_Insert(comment, out commentNumber);
            if (commentId == 0) {
                return null;
            } else {
                comment.Id = commentId;
                comment.Number = commentNumber;
                PageBL.Touch(page, comment.CreateDate);
                RecentChangeBL.AddCommentCreateRecentChange(comment.CreateDate, page, DekiContext.Current.User, string.Format(DekiResources.COMMENT_ADDED, comment.Number.ToString()), comment);
                return comment;
            } 
        }
コード例 #2
0
        public Yield PutPasswordChange(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
            
            UserBE targetUser = GetUserFromUrlMustExist();

            string password = request.AsText();

            if (string.IsNullOrEmpty(password)) {
                response.Return(DreamMessage.BadRequest(DekiResources.NEW_PASSWORD_NOT_PROVIDED));
                yield break;
            }

            if( password.Length < 4)
                throw new DreamAbortException(DreamMessage.BadRequest(DekiResources.NEW_PASSWORD_TOO_SHORT));

            //Ensure that the password is being set only on local accounts
            ServiceBE s = ServiceBL.GetServiceById(targetUser.ServiceId);
            if( s != null && !ServiceBL.IsLocalAuthService(s)){
                throw new DreamAbortException(DreamMessage.BadRequest(DekiResources.PASSWORD_CHANGE_LOCAL_ONLY));
            }

            if (UserBL.IsAnonymous(targetUser))
                throw new DreamBadRequestException(DekiResources.CANNOT_CHANGE_ANON_PASSWORD);

            //Admins can always change anyones password.
            if (PermissionsBL.IsUserAllowed(DekiContext.Current.User, Permissions.ADMIN)) {

                //For admins a currentpassword is option but if given then it should be validated
                string currentPwd = context.GetParam("currentpassword", string.Empty);

                if (!string.IsNullOrEmpty(currentPwd)) {
                    if (!AuthBL.IsValidAuthenticationForLocalUser(targetUser, currentPwd)) {
                        throw new DreamAbortException(DreamMessage.Forbidden(DekiResources.CURRENTPASSWORD_DOES_NOT_MATCH));
                    }
                }
            }else if (DekiContext.Current.User.ID == targetUser.ID){

                if (context.GetParam<bool>("altpassword", false)) {
                    throw new DreamBadRequestException(DekiResources.CANNOT_CHANGE_OWN_ALT_PASSWORD);
                }

                //User changing their own password requires knowledge of their current password
                string currentPwd = context.GetParam("currentpassword");
                if (!AuthBL.IsValidAuthenticationForLocalUser(DekiContext.Current.User, currentPwd)) {
                    throw new DreamAbortException(DreamMessage.Forbidden(DekiResources.CURRENTPASSWORD_DOES_NOT_MATCH));
                }
            } else {
                response.Return(DreamMessage.Forbidden(DekiResources.MUST_BE_TARGET_USER_OR_ADMIN));
                yield break;
            }
            bool altPassword = context.GetParam<bool>("altpassword", false);
            targetUser = UserBL.SetPassword(targetUser, password, altPassword);
            if(DekiContext.Current.User.ID == targetUser.ID) {
                response.Return(BuildSetAuthTokenResponse(AuthBL.CreateAuthTokenForUser(targetUser)));
            } else {
                response.Return(DreamMessage.Ok());
            }
            yield break;
        }
コード例 #3
0
 // TODO (brigettek): this feature currently always fails.  Commenting out until we need/fix it.
 //  [DreamFeature("POST:site/notifyadmin", "Notifies the site admin")]/
 //  [DreamFeatureParam("subject", "string", "Subject of the notice")]
 //  [DreamFeatureStatus(DreamStatus.Ok, "The request completed successfully")]
 //  [DreamFeatureStatus(DreamStatus.BadRequest, "Invalid input parameter or request body")]
 //  [DreamFeatureStatus(DreamStatus.Forbidden, "User must be logged in")]
 public Yield PostSiteNotifyAdmin(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
     if((DekiContext.CurrentOrNull == null) || UserBL.IsAnonymous(DekiContext.Current.User)) {
         response.Return(DreamMessage.Forbidden(DekiResources.MUST_BE_LOGGED_IN));
         yield break;
     }
     SiteBL.SendNoticeToAdmin(context.GetParam("subject"), request.AsText(), request.ContentType);
     response.Return(DreamMessage.Ok());
     yield break;
 }
コード例 #4
0
        public static CommentBE EditExistingComment(PageBE page, CommentBE comment, DreamMessage request, DreamContext context) {
            if (comment.PosterUserId != DekiContext.Current.User.ID) {
                PermissionsBL.CheckUserAllowed(DekiContext.Current.User, Permissions.ADMIN);
            }
            ValidateCommentText(request.ContentType, request.AsText());
            comment.LastEditDate = DateTime.UtcNow;
            comment.LastEditUserId = DekiContext.Current.User.ID;
            comment.Content = request.AsText();
            comment.ContentMimeType = request.ContentType.ToString();

            DbUtils.CurrentSession.Comments_Update(comment);
            PageBL.Touch(page, comment.LastEditDate.Value);
            RecentChangeBL.AddCommentUpdateRecentChange(comment.LastEditDate.Value, page, DekiContext.Current.User, string.Format(DekiResources.COMMENT_EDITED, comment.Number.ToString()), comment);
            return comment;
        }
コード例 #5
0
ファイル: DekiWiki-Pages.cs プロジェクト: heran/DekiWiki
        public Yield PostPageContents(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
            PageBE cur = PageBL_GetPageFromUrl(context, false);

            // load page contents based on mime type
            string contents;
            MimeType mimeType = request.ContentType;
            if(mimeType.IsXml) {
                XDoc contentsDoc = request.ToDocument();
                if(contentsDoc == null || contentsDoc.IsEmpty || !contentsDoc.HasName("content")) {
                    throw new PostedDocumentInvalidArgumentException("content");
                }
                contents = contentsDoc["body"].ToInnerXHtml();
            } else if(MimeType.TEXT.Match(mimeType) || MimeType.FORM_URLENCODED.Match(mimeType)) {
                contents = request.AsText();
            } else {
                throw new UnsupportedContentTypeInvalidArgumentException(mimeType);
            }

            bool isExistingPage = cur.ID != 0 && !cur.IsRedirect;
            string abort = context.GetParam("abort", "never").ToLowerInvariant();
            if(isExistingPage && "exists" == abort) {
                throw new PageExistsConflictException();
            }

            // Retrieve the title used for path normalization (if any)
            Title relToTitle = Utils.GetRelToTitleFromUrl(context);
            string editTimeStr = context.GetParam("edittime", null);
            DateTime editTime = DateTime.MinValue;
            if(!string.IsNullOrEmpty(editTimeStr)) {
                editTime = editTimeStr.EqualsInvariantIgnoreCase("now") ? DateTime.UtcNow : DbUtils.ToDateTime(editTimeStr);
            }
            string comment = context.GetParam("comment", String.Empty);
            string language = context.GetParam("language", null);
            string displayName = context.GetParam("title", null);
            int section = context.GetParam<int>("section", -1);
            if((section < -1) || ((!isExistingPage) && (0 < section))) {
                throw new SectionParamInvalidArgumentException();
            }

            // determin how unsafe/invalid content should be handled
            bool removeIllegalElements = StringUtil.EqualsInvariantIgnoreCase(context.GetParam("tidy", "convert"), "remove");

            // a new revision is created when no changes are detected when overwrite is enabled
            bool overwrite = context.GetParam<bool>("overwrite", false);

            // check whether the page exists and is not a redirect
            DateTime pageLastEditTime = cur.TimeStamp;
            OldBE baseOld = null;
            OldBE overwrittenOld = null;
            if(isExistingPage) {
                PageBL.AuthorizePage(DekiContext.Current.User, Permissions.UPDATE, cur, false);

                // ensure that 'edittime' is set
                if(DateTime.MinValue == editTime) {
                    throw new PageEditTimeInvalidArgumentException();
                }

                // check if page was modified since since the specified time
                if(pageLastEditTime > editTime) {

                    // ensure we're allowed to save a modified page
                    if("modified" == abort) {
                        throw new PageModifiedConflictException();
                    }

                    // if an edit has occurred since the specified edit time, retrieve the revision upon which it is based
                    // NOTE: this can be null if someone created the page after the specified edit time (ie. no common base revision)
                    baseOld = DbUtils.CurrentSession.Old_GetOldByTimestamp(cur.ID, editTime);

                    // if editing a particular section, use the page upon which the section edits were based.
                    if(0 < section && null == baseOld) {
                        throw new PageHeadingInvalidArgumentException();
                    }
                }
            }

            // save page
            bool conflict;
            try {
                overwrittenOld = PageBL.Save(cur, baseOld, comment, contents, DekiMimeType.DEKI_TEXT, displayName, language, section, context.GetParam("xpath", null), DateTime.UtcNow, 0, true, removeIllegalElements, relToTitle, overwrite, out conflict);
            } catch(DekiScriptDocumentTooLargeException e) {
                response.Return(DreamMessage.Forbidden(string.Format(e.Message)));
                yield break;
            }

            // check if this post is part of an import action
            var importTimeStr = context.GetParam("importtime", null);
            if(!string.IsNullOrEmpty(importTimeStr)) {
                var dateModified = DbUtils.ToDateTime(importTimeStr);
                var lastImport = PropertyBL.Instance.GetPageProperty((uint)cur.ID, SiteImportBuilder.LAST_IMPORT);
                var lastImportDoc = new XDoc("last-import").Elem("etag", cur.Etag).Elem("date.modified", dateModified);
                var content = new ResourceContentBE(lastImportDoc);
                if(lastImport == null) {
                    PropertyBL.Instance.CreateProperty((uint)cur.ID, PageBL.GetUri(cur), ResourceBE.ParentType.PAGE, SiteImportBuilder.LAST_IMPORT, content, string.Format("import at revision {0}", cur.Revision), content.ComputeHashString(), AbortEnum.Never);
                } else {
                    PropertyBL.Instance.UpdatePropertyContent(lastImport, content, string.Format("updated import at revision {0}", cur.Revision), content.ComputeHashString(), AbortEnum.Never, PageBL.GetUri(cur), ResourceBE.ParentType.PAGE);
                }
            }

            // generate xml output
            XDoc editXml = new XDoc("edit") { PageBL.GetPageXml(cur, String.Empty) };

            // if a non-redirect was overwritten, report it
            if((overwrittenOld != null) && (pageLastEditTime != editTime) && isExistingPage && conflict) {
                editXml.Attr("status", "conflict");
                editXml.Add(baseOld == null ? new XDoc("page.base") : PageBL.GetOldXml(cur, baseOld, "base"));
                editXml.Add(PageBL.GetOldXml(cur, overwrittenOld, "overwritten"));
            } else {
                editXml.Attr("status", "success");
            }

            response.Return(DreamMessage.Ok(editXml));
            yield break;
        }
コード例 #6
0
ファイル: DekiWiki-Pages.cs プロジェクト: heran/DekiWiki
 public Yield PostPageMessage(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
     if(UserBL.IsAnonymous(DekiContext.Current.User)) {
         response.Return(DreamMessage.Forbidden("A logged-in user is required"));
         yield break;
     }
     if(request.ContentLength > 128 * 1024) {
         response.Return(DreamMessage.BadRequest("Content-length cannot exceed 128KB)"));
         yield break;
     }
     PageBE page = PageBL_AuthorizePage(context, null, Permissions.READ, false);
     XDoc body = new XDoc("body");
     switch(request.ContentType.FullType) {
     case "text/plain":
         body.Attr("content-type", request.ContentType.ToString())
             .Value(request.AsText());
         break;
     default:
         body.Attr("content-type", request.ContentType.ToString())
             .Add(request.ToDocument());
         break;
     }
     string[] path = context.GetSuffixes(UriPathFormat.Original);
     path = ArrayUtil.SubArray(path, 1);
     DekiContext.Current.Instance.EventSink.PageMessage(DekiContext.Current.Now, page, DekiContext.Current.User, body, path);
     response.Return(DreamMessage.Ok());
     yield break;
 }
コード例 #7
0
        public Yield PutFileDescription(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
            PageBE parentPage;
            AttachmentBE file = GetAttachment(request, Permissions.UPDATE, false, false, out parentPage);

            // determine if description needs to be set or cleared
            string description = StringUtil.EqualsInvariant(context.Verb, "PUT") ? request.AsText() : string.Empty;
            file = AttachmentBL.Instance.SetDescription(file, description);
            response.Return(DreamMessage.Ok(AttachmentBL.Instance.GetFileXml(file, true, null, null)));
            yield break;
        }
コード例 #8
0
ファイル: DekiWiki-Site.cs プロジェクト: heran/DekiWiki
 // TODO (brigettek): this feature currently always fails.  Commenting out until we need/fix it.
 //  [DreamFeature("POST:site/notifyadmin", "Notifies the site admin")]/
 //  [DreamFeatureParam("subject", "string", "Subject of the notice")]
 //  [DreamFeatureStatus(DreamStatus.Ok, "The request completed successfully")]
 //  [DreamFeatureStatus(DreamStatus.BadRequest, "Invalid input parameter or request body")]
 //  [DreamFeatureStatus(DreamStatus.Forbidden, "User must be logged in")]
 public Yield PostSiteNotifyAdmin(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
     if((DekiContext.CurrentOrNull == null) || UserBL.IsAnonymous(DekiContext.Current.User)) {
         throw new SiteMustBeLoggedInForbiddenException();
     }
     var siteBL = new SiteBL();
     siteBL.SendNoticeToAdmin(context.GetParam("subject"), request.AsText(), request.ContentType);
     response.Return(DreamMessage.Ok());
     yield break;
 }
コード例 #9
0
ファイル: DekiWiki-Users.cs プロジェクト: heran/DekiWiki
        public Yield PutPasswordChange(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
            UserBE targetUser = GetUserFromUrlMustExist();
            string password = request.AsText();
            if(string.IsNullOrEmpty(password)) {
                throw new UserNewPasswordNotProvidedInvalidArgumentException();
            }
            if(password.Length < 4) {
                throw new UserNewPasswordTooShortInvalidArgumentException();
            }

            // Ensure that the password is being set only on local accounts
            ServiceBE s = ServiceBL.GetServiceById(targetUser.ServiceId);
            if(s != null && !ServiceBL.IsLocalAuthService(s)) {
                throw new UserCanOnlyChangeLocalUserPasswordInvalidOperationException();
            }
            if(UserBL.IsAnonymous(targetUser)) {
                throw new UserCannotChangeAnonPasswordInvalidOperationException();
            }

            // Admins can always change anyones password.
            if(PermissionsBL.IsUserAllowed(DekiContext.Current.User, Permissions.ADMIN)) {

                //For admins a currentpassword is option but if given then it should be validated
                string currentPwd = context.GetParam("currentpassword", string.Empty);
                if(!string.IsNullOrEmpty(currentPwd)) {
                    if(!AuthBL.IsValidAuthenticationForLocalUser(targetUser, currentPwd)) {
                        throw new UserCurrentPasswordIncorrectForbiddenException();
                    }
                }
            } else if(DekiContext.Current.User.ID == targetUser.ID) {
                if(context.GetParam("altpassword", false)) {
                    throw new UserCannotChangeOwnAltPasswordInvalidOperationException();
                }

                // User changing their own password requires knowledge of their current password
                string currentPwd = context.GetParam("currentpassword");
                if(!AuthBL.IsValidAuthenticationForLocalUser(DekiContext.Current.User, currentPwd)) {
                    throw new UserCurrentPasswordIncorrectForbiddenException();
                }
            } else {
                throw new UserMustBeTargetOrAdminForbiddenException();
            }
            bool altPassword = context.GetParam<bool>("altpassword", false);
            targetUser = UserBL.SetPassword(targetUser, password, altPassword);
            if(DekiContext.Current.User.ID == targetUser.ID) {
                response.Return(BuildSetAuthTokenResponse(AuthBL.CreateAuthTokenForUser(targetUser), null));
            } else {
                response.Return(DreamMessage.Ok());
            }
            yield break;
        }