def POST_wiki_edit(self, pageandprevious, content, page_name, reason): page, previous = pageandprevious if not page: error = c.errors.get(('WIKI_CREATE_ERROR', 'page')) if error: self.handle_error(403, **(error.msg_params or {})) if not c.user._spam: page = WikiPage.create(c.site, page_name) if c.user._spam: error = _("You are doing that too much, please try again later.") self.handle_error(415, 'SPECIAL_ERRORS', special_errors=[error]) renderer = RENDERERS_BY_PAGE.get(page.name, 'wiki') if renderer in ('wiki', 'reddit'): content = VMarkdown(('content'), renderer=renderer).run(content) # Use the raw POST value as we need to tell the difference between # None/Undefined and an empty string. The validators use a default # value with both of those cases and would need to be changed. # In order to avoid breaking functionality, this was done instead. previous = previous._id if previous else request.post.get('previous') try: if page.name == 'config/stylesheet': report, parsed = c.site.parse_css(content, verify=False) if report is None: # g.css_killswitch self.handle_error(403, 'STYLESHEET_EDIT_DENIED') if report.errors: error_items = [x.message for x in sorted(report.errors)] self.handle_error(415, 'SPECIAL_ERRORS', special_errors=error_items) c.site.change_css(content, parsed, previous, reason=reason) else: try: page.revise(content, previous, c.user._id36, reason=reason) except ContentLengthError as e: self.handle_error(403, 'CONTENT_LENGTH_ERROR', max_length=e.max_length) # continue storing the special pages as data attributes on the subreddit # object. TODO: change this to minimize subreddit get sizes. if page.special: setattr(c.site, ATTRIBUTE_BY_PAGE[page.name], content) setattr(c.site, "prev_" + ATTRIBUTE_BY_PAGE[page.name] + "_id", str(page.revision)) c.site._commit() if page.special or c.is_wiki_mod: description = modactions.get(page.name, 'Page %s edited' % page.name) ModAction.create(c.site, c.user, 'wikirevise', details=description) except ConflictException as e: self.handle_error(409, 'EDIT_CONFLICT', newcontent=e.new, newrevision=page.revision, diffcontent=e.htmldiff) return json.dumps({})
def POST_wiki_edit(self, pageandprevious, content, page_name, reason): """Edit a wiki `page`""" page, previous = pageandprevious if c.user._spam: error = _("You are doing that too much, please try again later.") self.handle_error(415, 'SPECIAL_ERRORS', special_errors=[error]) if not page: error = c.errors.get(('WIKI_CREATE_ERROR', 'page')) if error: self.handle_error(403, **(error.msg_params or {})) VNotInTimeout().run(action_name="wikirevise", details_text="create") page = WikiPage.create(c.site, page_name) else: VNotInTimeout().run(action_name="wikirevise", details_text="edit", target=page) error = c.errors.get(('MAY_NOT_REVISE', 'page')) if error: self.handle_error(403, **(error.msg_params or {})) renderer = RENDERERS_BY_PAGE.get(page.name, 'wiki') if renderer in ('wiki', 'reddit'): content = VMarkdown(('content'), renderer=renderer).run(content) # Use the raw POST value as we need to tell the difference between # None/Undefined and an empty string. The validators use a default # value with both of those cases and would need to be changed. # In order to avoid breaking functionality, this was done instead. previous = previous._id if previous else request.POST.get('previous') try: # special validation methods if page.name == 'config/stylesheet': css_errors, parsed = c.site.parse_css(content, verify=False) if g.css_killswitch: self.handle_error(403, 'STYLESHEET_EDIT_DENIED') if css_errors: error_items = [CssError(x).message for x in css_errors] self.handle_error(415, 'SPECIAL_ERRORS', special_errors=error_items) elif page.name == "config/automoderator": try: rules = Ruleset(content) except ValueError as e: error_items = [e.message] self.handle_error(415, "SPECIAL_ERRORS", special_errors=error_items) # special saving methods if page.name == "config/stylesheet": c.site.change_css(content, parsed, previous, reason=reason) else: try: page.revise(content, previous, c.user._id36, reason=reason) except ContentLengthError as e: self.handle_error(403, 'CONTENT_LENGTH_ERROR', max_length=e.max_length) # continue storing the special pages as data attributes on the subreddit # object. TODO: change this to minimize subreddit get sizes. if page.special and page.name in ATTRIBUTE_BY_PAGE: setattr(c.site, ATTRIBUTE_BY_PAGE[page.name], content) c.site._commit() if page.special or c.is_wiki_mod: description = modactions.get(page.name, 'Page %s edited' % page.name) ModAction.create(c.site, c.user, "wikirevise", details=description, description=reason) except ConflictException as e: self.handle_error(409, 'EDIT_CONFLICT', newcontent=e.new, newrevision=page.revision, diffcontent=e.htmldiff) return json.dumps({})
multi_sr_data_json_spec = VValidatedJSON.Object({ 'name': VSubredditName('name', allow_language_srs=True), }) multi_json_spec = VValidatedJSON.Object({ 'visibility': VOneOf('visibility', ('private', 'public')), 'subreddits': VValidatedJSON.ArrayOf(multi_sr_data_json_spec), }) multi_description_json_spec = VValidatedJSON.Object({ 'body_md': VMarkdown('body_md', empty_error=None), }) class MultiApiController(RedditController, OAuth2ResourceController): def pre(self): set_extension(request.environ, "json") self.check_for_bearer_token() RedditController.pre(self) def on_validation_error(self, error): if not error.code: raise ValueError('Error %r missing status code' % error) abort( reddit_http_error(
class WikiApiController(WikiController): @validate(VModhash(), pageandprevious=VWikiPageRevise(('page', 'previous'), restricted=True), content=VMarkdown(('content'), renderer='wiki'), page_name=VWikiPageName('page'), reason=VPrintable('reason', 256)) @api_doc(api_section.wiki, uri='/api/wiki/edit') def POST_wiki_edit(self, pageandprevious, content, page_name, reason): page, previous = pageandprevious if not page: error = c.errors.get(('WIKI_CREATE_ERROR', 'page')) if error: self.handle_error(403, **(error.msg_params or {})) if not c.user._spam: page = WikiPage.create(c.site, page_name) if c.user._spam: error = _("You are doing that too much, please try again later.") self.handle_error(415, 'SPECIAL_ERRORS', special_errors=[error]) # Use the raw POST value as we need to tell the difference between # None/Undefined and an empty string. The validators use a default # value with both of those cases and would need to be changed. # In order to avoid breaking functionality, this was done instead. previous = previous._id if previous else request.post.get('previous') try: if page.name == 'config/stylesheet': report, parsed = c.site.parse_css(content, verify=False) if report is None: # g.css_killswitch self.handle_error(403, 'STYLESHEET_EDIT_DENIED') if report.errors: error_items = [x.message for x in sorted(report.errors)] self.handle_error(415, 'SPECIAL_ERRORS', special_errors=error_items) c.site.change_css(content, parsed, previous, reason=reason) else: try: page.revise(content, previous, c.user._id36, reason=reason) except ContentLengthError as e: self.handle_error(403, 'CONTENT_LENGTH_ERROR', max_length=e.max_length) # continue storing the special pages as data attributes on the subreddit # object. TODO: change this to minimize subreddit get sizes. if page.special: setattr(c.site, ATTRIBUTE_BY_PAGE[page.name], content) setattr(c.site, "prev_" + ATTRIBUTE_BY_PAGE[page.name] + "_id", str(page.revision)) c.site._commit() if page.special or c.is_wiki_mod: description = modactions.get(page.name, 'Page %s edited' % page.name) ModAction.create(c.site, c.user, 'wikirevise', details=description) except ConflictException as e: self.handle_error(409, 'EDIT_CONFLICT', newcontent=e.new, newrevision=page.revision, diffcontent=e.htmldiff) return json.dumps({}) @validate(VModhash(), VWikiModerator(), page=VWikiPage('page'), act=VOneOf('act', ('del', 'add')), user=VExistingUname('username')) @api_doc(api_section.wiki, uri='/api/wiki/alloweditor/:act') def POST_wiki_allow_editor(self, act, page, user): if not user: self.handle_error(404, 'UNKNOWN_USER') elif act == 'del': page.remove_editor(user._id36) elif act == 'add': page.add_editor(user._id36) else: self.handle_error(400, 'INVALID_ACTION') return json.dumps({}) @validate(VModhash(), VWikiModerator(), pv=VWikiPageAndVersion(('page', 'revision'))) @api_doc(api_section.wiki, uri='/api/wiki/hide') def POST_wiki_revision_hide(self, pv): page, revision = pv if not revision: self.handle_error(400, 'INVALID_REVISION') return json.dumps({'status': revision.toggle_hide()}) @validate(VModhash(), VWikiModerator(), pv=VWikiPageAndVersion(('page', 'revision'))) @api_doc(api_section.wiki, uri='/api/wiki/revert') def POST_wiki_revision_revert(self, pv): page, revision = pv if not revision: self.handle_error(400, 'INVALID_REVISION') content = revision.content reason = 'reverted back %s' % timesince(revision.date) if page.name == 'config/stylesheet': report, parsed = c.site.parse_css(content) if report.errors: self.handle_error(403, 'INVALID_CSS') c.site.change_css(content, parsed, prev=None, reason=reason, force=True) else: try: page.revise(content, author=c.user._id36, reason=reason, force=True) # continue storing the special pages as data attributes on the subreddit # object. TODO: change this to minimize subreddit get sizes. if page.special: setattr(c.site, ATTRIBUTE_BY_PAGE[page.name], content) setattr(c.site, "prev_" + ATTRIBUTE_BY_PAGE[page.name] + "_id", page.revision) c.site._commit() except ContentLengthError as e: self.handle_error(403, 'CONTENT_LENGTH_ERROR', max_length=e.max_length) return json.dumps({}) def pre(self): WikiController.pre(self) c.render_style = 'api' set_extension(request.environ, 'json')