From 3ea509d4c088bbcc63455ece472fa994f19bc0ce Mon Sep 17 00:00:00 2001 From: Keith Mitchell Date: Thu, 27 Mar 2014 13:23:10 -0700 Subject: [PATCH] Refactor /post/options for re-use * Create a var with the validators * Don't always grab langs out of request.POST * Refactor validation to a separate function --- r2/r2/controllers/post.py | 122 +++++++---------------------- r2/r2/lib/validator/preferences.py | 118 ++++++++++++++++++++++++++++ 2 files changed, 148 insertions(+), 92 deletions(-) create mode 100644 r2/r2/lib/validator/preferences.py diff --git a/r2/r2/controllers/post.py b/r2/r2/controllers/post.py index 3a51bb70a..f31534741 100644 --- a/r2/r2/controllers/post.py +++ b/r2/r2/controllers/post.py @@ -23,9 +23,16 @@ from r2.lib.pages import * from reddit_base import cross_domain from api import ApiController +from r2.lib.errors import BadRequestError, errors from r2.lib.utils import Storage, query_string, UrlParser from r2.lib.emailer import opt_in, opt_out from r2.lib.validator import * +from r2.lib.validator.preferences import ( + filter_prefs, + format_content_lang_pref, + PREFS_VALIDATORS, + set_prefs, +) from r2.models.recommend import ExploreSettings from pylons import request, c, g from pylons.controllers.util import redirect_to @@ -34,105 +41,36 @@ from r2.models import * import hashlib class PostController(ApiController): - def set_options(self, all_langs, pref_lang, **kw): - if c.errors.errors: - print "fucker" - return - - if all_langs == 'all': - langs = 'all' - elif all_langs == 'some': - langs = [] - for lang in g.all_languages: - if request.POST.get('lang-' + lang): - langs.append(str(lang)) #unicode - if langs: - langs.sort() - langs = tuple(langs) - else: - langs = 'all' - - for k, v in kw.iteritems(): - #startswith is important because kw has all sorts of - #request info in it - if k.startswith('pref_'): - setattr(c.user, k, v) - - c.user.pref_content_langs = langs - c.user.pref_lang = pref_lang - c.user._commit() + def _langs_from_post(self, all_or_some): + if all_or_some == 'all': + return 'all' + langs = [] + for lang in g.all_languages: + if request.POST.get('lang-' + lang): + langs.append(str(lang)) + return format_content_lang_pref(langs) @validate(pref_lang = VLang('lang'), all_langs = VOneOf('all-langs', ('all', 'some'), default='all')) def POST_unlogged_options(self, all_langs, pref_lang): - self.set_options( all_langs, pref_lang) + content_langs = self._langs_from_post(all_langs) + prefs = {"pref_content_lang": content_langs, "pref_lang": pref_lang} + set_prefs(c.user, prefs) + c.user._commit() return self.redirect(request.referer) - @validate(VUser(), - VModhash(), - pref_frame = VBoolean('frame'), - pref_clickgadget = VBoolean('clickgadget'), - pref_organic = VBoolean('organic'), - pref_newwindow = VBoolean('newwindow'), - pref_public_votes = VBoolean('public_votes'), - pref_hide_from_robots = VBoolean('hide_from_robots'), - pref_hide_ups = VBoolean('hide_ups'), - pref_hide_downs = VBoolean('hide_downs'), - pref_over_18 = VBoolean('over_18'), - pref_research = VBoolean('research'), - pref_numsites = VInt('numsites', 1, 100), - pref_lang = VLang('lang'), - pref_media = VOneOf('media', ('on', 'off', 'subreddit')), - pref_compress = VBoolean('compress'), - pref_domain_details = VBoolean('domain_details'), - pref_min_link_score = VInt('min_link_score', -100, 100), - pref_min_comment_score = VInt('min_comment_score', -100, 100), - pref_num_comments = VInt('num_comments', 1, g.max_comments, - default = g.num_comments), - pref_show_stylesheets = VBoolean('show_stylesheets'), - pref_show_flair = VBoolean('show_flair'), - pref_show_link_flair = VBoolean('show_link_flair'), - pref_no_profanity = VBoolean('no_profanity'), - pref_label_nsfw = VBoolean('label_nsfw'), - pref_show_promote = VBoolean('show_promote'), - pref_mark_messages_read = VBoolean("mark_messages_read"), - pref_threaded_messages = VBoolean("threaded_messages"), - pref_collapse_read_messages = VBoolean("collapse_read_messages"), - pref_private_feeds = VBoolean("private_feeds"), - pref_local_js = VBoolean('local_js'), - pref_store_visits = VBoolean('store_visits'), - pref_show_adbox = VBoolean("show_adbox"), - pref_show_sponsors = VBoolean("show_sponsors"), - pref_show_sponsorships = VBoolean("show_sponsorships"), - pref_highlight_new_comments = VBoolean("highlight_new_comments"), - pref_monitor_mentions=VBoolean("monitor_mentions"), - all_langs = VOneOf('all-langs', ('all', 'some'), default='all')) - def POST_options(self, all_langs, pref_lang, **kw): - #temporary. eventually we'll change pref_clickgadget to an - #integer preference - kw['pref_clickgadget'] = kw['pref_clickgadget'] and 5 or 0 - if c.user.pref_show_promote is None: - kw['pref_show_promote'] = None - elif not kw.get('pref_show_promote'): - kw['pref_show_promote'] = False - - if not kw.get("pref_over_18") or not c.user.pref_over_18: - kw['pref_no_profanity'] = True - - if kw.get("pref_no_profanity") or c.user.pref_no_profanity: - kw['pref_label_nsfw'] = True - - # default all the gold options to on if they don't have gold - if not c.user.gold: - for pref in ('pref_show_adbox', - 'pref_show_sponsors', - 'pref_show_sponsorships', - 'pref_highlight_new_comments', - 'pref_monitor_mentions'): - kw[pref] = True - - self.set_options(all_langs, pref_lang, **kw) + @validate(VUser(), VModhash(), + all_langs=VOneOf('all-langs', ('all', 'some'), default='all'), + **PREFS_VALIDATORS) + def POST_options(self, all_langs, **prefs): + pref_content_langs = self._langs_from_post(all_langs) + prefs['pref_content_langs'] = pref_content_langs + filter_prefs(prefs, c.user) + if c.errors.errors: + return abort(BadRequestError(errors.INVALID_PREF)) + set_prefs(c.user, prefs) + c.user._commit() u = UrlParser(c.site.path + "prefs") u.update_query(done = 'true') if c.cname: diff --git a/r2/r2/lib/validator/preferences.py b/r2/r2/lib/validator/preferences.py new file mode 100644 index 000000000..8826df434 --- /dev/null +++ b/r2/r2/lib/validator/preferences.py @@ -0,0 +1,118 @@ +# The contents of this file are subject to the Common Public Attribution +# License Version 1.0. (the "License"); you may not use this file except in +# compliance with the License. You may obtain a copy of the License at +# http://code.reddit.com/LICENSE. The License is based on the Mozilla Public +# License Version 1.1, but Sections 14 and 15 have been added to cover use of +# software over a computer network and provide for limited attribution for the +# Original Developer. In addition, Exhibit A has been modified to be consistent +# with Exhibit B. +# +# Software distributed under the License is distributed on an "AS IS" basis, +# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for +# the specific language governing rights and limitations under the License. +# +# The Original Code is reddit. +# +# The Original Developer is the Initial Developer. The Initial Developer of +# the Original Code is reddit Inc. +# +# All portions of the code written by reddit are Copyright (c) 2006-2013 reddit +# Inc. All Rights Reserved. +############################################################################### +from pylons import g +from r2.lib.validator.validator import ( + VBoolean, + VInt, + VLang, + VOneOf, +) + +# Validators that map directly to Account._preference_attrs +# The key MUST be the same string as the value in _preference_attrs +# Non-preference validators should be added to to the controller +# method directly (see PostController.POST_options) +PREFS_VALIDATORS = dict( + pref_frame=VBoolean('frame'), + pref_clickgadget=VBoolean('clickgadget'), + pref_organic=VBoolean('organic'), + pref_newwindow=VBoolean('newwindow'), + pref_public_votes=VBoolean('public_votes'), + pref_hide_from_robots=VBoolean('hide_from_robots'), + pref_hide_ups=VBoolean('hide_ups'), + pref_hide_downs=VBoolean('hide_downs'), + pref_over_18=VBoolean('over_18'), + pref_research=VBoolean('research'), + pref_numsites=VInt('numsites', 1, 100), + pref_lang=VLang('lang'), + pref_media=VOneOf('media', ('on', 'off', 'subreddit')), + pref_compress=VBoolean('compress'), + pref_domain_details=VBoolean('domain_details'), + pref_min_link_score=VInt('min_link_score', -100, 100), + pref_min_comment_score=VInt('min_comment_score', -100, 100), + pref_num_comments=VInt('num_comments', 1, g.max_comments, + default=g.num_comments), + pref_show_stylesheets=VBoolean('show_stylesheets'), + pref_show_flair=VBoolean('show_flair'), + pref_show_link_flair=VBoolean('show_link_flair'), + pref_no_profanity=VBoolean('no_profanity'), + pref_label_nsfw=VBoolean('label_nsfw'), + pref_show_promote=VBoolean('show_promote'), + pref_mark_messages_read=VBoolean("mark_messages_read"), + pref_threaded_messages=VBoolean("threaded_messages"), + pref_collapse_read_messages=VBoolean("collapse_read_messages"), + pref_private_feeds=VBoolean("private_feeds"), + pref_local_js=VBoolean('local_js'), + pref_store_visits=VBoolean('store_visits'), + pref_show_adbox=VBoolean("show_adbox"), + pref_show_sponsors=VBoolean("show_sponsors"), + pref_show_sponsorships=VBoolean("show_sponsorships"), + pref_highlight_new_comments=VBoolean("highlight_new_comments"), + pref_monitor_mentions=VBoolean("monitor_mentions"), +) + + +def format_content_lang_pref(content_langs): + pref_content_langs = [] + for lang in content_langs: + if lang in g.all_languages: + pref_content_langs.append(lang) + pref_content_langs = tuple(sorted(pref_content_langs)) + + if not pref_content_langs or "all" in pref_content_langs: + return "all" + else: + return pref_content_langs + + +def set_prefs(user, prefs): + for k, v in prefs.iteritems(): + setattr(user, k, v) + + +def filter_prefs(prefs, user): + for pref_key in prefs.keys(): + if pref_key not in user._preference_attrs: + del prefs[pref_key] + + #temporary. eventually we'll change pref_clickgadget to an + #integer preference + prefs['pref_clickgadget'] = 5 if prefs['pref_clickgadget'] else 0 + if user.pref_show_promote is None: + prefs['pref_show_promote'] = None + elif not prefs.get('pref_show_promote'): + prefs['pref_show_promote'] = False + + if not prefs.get("pref_over_18") or not user.pref_over_18: + prefs['pref_no_profanity'] = True + + if prefs.get("pref_no_profanity") or user.pref_no_profanity: + prefs['pref_label_nsfw'] = True + + # default all the gold options to on if they don't have gold + if not user.gold: + for pref in ('pref_show_adbox', + 'pref_show_sponsors', + 'pref_show_sponsorships', + 'pref_highlight_new_comments', + 'pref_monitor_mentions'): + prefs[pref] = True