From bb627e7b067c1548ca0f9f41eeb24d247b0bdc07 Mon Sep 17 00:00:00 2001 From: Evgeny Fadeev Date: Wed, 28 Jul 2010 21:28:10 -0400 Subject: applied permissions to file upload --- askbot/auth.py | 14 ---- askbot/context.py | 2 +- askbot/locale/de/LC_MESSAGES/django.po | 10 ++- askbot/locale/en/LC_MESSAGES/django.po | 8 +- askbot/locale/es/LC_MESSAGES/django.po | 6 +- askbot/locale/fi/LC_MESSAGES/django.po | 10 ++- askbot/locale/ru/LC_MESSAGES/django.po | 10 ++- askbot/locale/sr/LC_MESSAGES/django.po | 10 ++- askbot/locale/tr/LC_MESSAGES/django.po | 10 ++- askbot/locale/vi/LC_MESSAGES/django.po | 8 +- askbot/locale/zh-cn/LC_MESSAGES/django.po | 10 ++- askbot/models/__init__.py | 53 +++++++++---- askbot/setup_templates/settings.py | 16 ++-- askbot/setup_templates/urls.py | 2 +- askbot/skins/default/media/js/wmd/wmd.js | 5 +- askbot/skins/default/templates/base.html | 2 +- askbot/skins/default/templates/base_content.html | 2 +- askbot/startup_tests.py | 43 +++++++++++ askbot/templatetags/extra_tags.py | 4 +- askbot/tests.py | 59 +++++++++++++++ askbot/utils/forms.py | 2 +- askbot/views/commands.py | 5 +- askbot/views/readers.py | 2 +- askbot/views/writers.py | 94 +++++++++++++++--------- 24 files changed, 274 insertions(+), 113 deletions(-) create mode 100644 askbot/startup_tests.py diff --git a/askbot/auth.py b/askbot/auth.py index f1d8b5a2..809fc708 100644 --- a/askbot/auth.py +++ b/askbot/auth.py @@ -164,20 +164,6 @@ def can_view_user_preferences(request_user, target_user): def can_view_user_edit(request_user, target_user): return (request_user.is_authenticated() and request_user == target_user) -def can_upload_files(request_user): - if request_user.is_authenticated(): - if request_user.is_suspended(): - return False - elif request_user.is_blocked(): - return False - elif request_user.is_moderator(): - return True - elif request_user.is_administrator(): - return True - if request_user.reputation >= askbot_settings.MIN_REP_TO_UPLOAD_FILES: - return True - return False - ########################################### ## actions and reputation changes event ########################################### diff --git a/askbot/context.py b/askbot/context.py index 3d246dd2..4a090309 100644 --- a/askbot/context.py +++ b/askbot/context.py @@ -3,7 +3,7 @@ from askbot.conf import settings as askbot_settings def application_settings(context): my_settings = askbot_settings.as_dict() my_settings['LANGUAGE_CODE'] = settings.LANGUAGE_CODE - my_settings['FORUM_SCRIPT_ALIAS'] = settings.FORUM_SCRIPT_ALIAS + my_settings['ASKBOT_URL'] = settings.ASKBOT_URL #print '\n'.join(sorted(my_settings.keys())) return {'settings':my_settings} diff --git a/askbot/locale/de/LC_MESSAGES/django.po b/askbot/locale/de/LC_MESSAGES/django.po index 1ded3e79..56cc1160 100644 --- a/askbot/locale/de/LC_MESSAGES/django.po +++ b/askbot/locale/de/LC_MESSAGES/django.po @@ -4154,12 +4154,14 @@ msgid "profile - email subscriptions" msgstr "E-Mail-Abonnements" #: forum/views/writers.py:70 -msgid "uploading images is limited to users with >60 reputation points" -msgstr "Das Hochladen von Dateien benötigt 60 Punkte oder mehr" +#, python-format +msgid "uploading images is limited to users with >%(min_rep)s reputation points" +msgstr "Das Hochladen von Dateien benötigt %(min_rep)s Punkte oder mehr" #: forum/views/writers.py:72 -msgid "allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'" -msgstr "Erlaubte Dateitypen: 'jpg', 'jpeg', 'gif', 'bmp', 'png' und 'tiff'" +#, python-format +msgid "allowed file types are '%(file_types)s'" +msgstr "Erlaubte Dateitypen: '%(file_types)s'" #: forum/views/writers.py:74 #, python-format diff --git a/askbot/locale/en/LC_MESSAGES/django.po b/askbot/locale/en/LC_MESSAGES/django.po index d259f4fc..50125247 100644 --- a/askbot/locale/en/LC_MESSAGES/django.po +++ b/askbot/locale/en/LC_MESSAGES/django.po @@ -4521,11 +4521,13 @@ msgid "profile - email subscriptions" msgstr "" #: forum/views/writers.py:67 -msgid "uploading images is limited to users with >60 reputation points" -msgstr "sorry, file uploading requires karma >60" +#, python-format +msgid "uploading images is limited to users with >%(min_rep)s reputation points" +msgstr "sorry, file uploading requires karma >%(min_rep)s" #: forum/views/writers.py:69 -msgid "allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'" +#, python-format +msgid "allowed file types are '%(file_types)s'" msgstr "" #: forum/views/writers.py:71 diff --git a/askbot/locale/es/LC_MESSAGES/django.po b/askbot/locale/es/LC_MESSAGES/django.po index 857c175e..16f2fd17 100644 --- a/askbot/locale/es/LC_MESSAGES/django.po +++ b/askbot/locale/es/LC_MESSAGES/django.po @@ -4016,11 +4016,13 @@ msgid "profile - email subscriptions" msgstr "perfil - notificación por email" #: forum/views/writers.py:70 -msgid "uploading images is limited to users with >60 reputation points" +#, python-format +msgid "uploading images is limited to users with >%(min_rep)s reputation points" msgstr "" #: forum/views/writers.py:72 -msgid "allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'" +#, python-format +msgid "allowed file types are '%(file_types)s'" msgstr "" #: forum/views/writers.py:74 diff --git a/askbot/locale/fi/LC_MESSAGES/django.po b/askbot/locale/fi/LC_MESSAGES/django.po index 58e73cbd..01528d3d 100644 --- a/askbot/locale/fi/LC_MESSAGES/django.po +++ b/askbot/locale/fi/LC_MESSAGES/django.po @@ -4706,13 +4706,15 @@ msgid "profile - email subscriptions" msgstr "profiili - sähköpostitilaukset" #: views/writers.py:67 -msgid "uploading images is limited to users with >60 reputation points" -msgstr "sorry, file uploading requires karma >60" +#, python-format +msgid "uploading images is limited to users with >%(min_rep)s reputation points" +msgstr "sorry, file uploading requires karma >%(min_rep)s" #: views/writers.py:69 -msgid "allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'" +#, python-format +msgid "allowed file types are '%(file_types)s'" msgstr "" -"hyväksytyt tiedostotyypit ovat 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'" +"hyväksytyt tiedostotyypit ovat '%(file_types)s'" #: views/writers.py:71 #, python-format diff --git a/askbot/locale/ru/LC_MESSAGES/django.po b/askbot/locale/ru/LC_MESSAGES/django.po index e189e983..ecf66f68 100644 --- a/askbot/locale/ru/LC_MESSAGES/django.po +++ b/askbot/locale/ru/LC_MESSAGES/django.po @@ -4279,12 +4279,14 @@ msgid "profile - email subscriptions" msgstr "профиль - email подписки" #: forum/views/writers.py:69 -msgid "uploading images is limited to users with >60 reputation points" -msgstr "загрузка изображений доступна только пользователям с репутацией > 60" +#, python-format +msgid "uploading images is limited to users with >%(min_rep)s reputation points" +msgstr "загрузка изображений доступна только пользователям с репутацией > %(min_rep)s" #: forum/views/writers.py:71 -msgid "allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'" -msgstr "допустимые типы файлов: 'JPG ',' JPEG ',' GIF ',' BMP ',' PNG ',' TIFF'" +#, python-format +msgid "allowed file types are '%(file_types)s'" +msgstr "допустимые типы файлов: '%(file_types)s'" #: forum/views/writers.py:73 #, python-format diff --git a/askbot/locale/sr/LC_MESSAGES/django.po b/askbot/locale/sr/LC_MESSAGES/django.po index d4980ec9..c4d12f9b 100644 --- a/askbot/locale/sr/LC_MESSAGES/django.po +++ b/askbot/locale/sr/LC_MESSAGES/django.po @@ -4055,13 +4055,15 @@ msgid "profile - email subscriptions" msgstr "профил - претплата е-поштом" #: forum/views/writers.py:70 -msgid "uploading images is limited to users with >60 reputation points" -msgstr "нажалост, слање датотека на сервер захтева да имате карму >60" +#, python-format +msgid "uploading images is limited to users with >%(min_rep)s reputation points" +msgstr "нажалост, слање датотека на сервер захтева да имате карму >%(min_rep)s" #: forum/views/writers.py:72 -msgid "allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'" +#, python-format +msgid "allowed file types are '%(file_types)s'" msgstr "" -"дозвољени типови датотека су 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'" +"дозвољени типови датотека су '%(file_types)s'" #: forum/views/writers.py:74 #, python-format diff --git a/askbot/locale/tr/LC_MESSAGES/django.po b/askbot/locale/tr/LC_MESSAGES/django.po index 8cfe11d6..ccaabdbf 100644 --- a/askbot/locale/tr/LC_MESSAGES/django.po +++ b/askbot/locale/tr/LC_MESSAGES/django.po @@ -4172,12 +4172,14 @@ msgid "profile - email subscriptions" msgstr "profil - e-mail abonelikleri" #: forum/views/writers.py:70 -msgid "uploading images is limited to users with >60 reputation points" -msgstr "resim göndermek için en az 60 puan toplamalısınız" +#,python-format +msgid "uploading images is limited to users with >%(min_rep)s reputation points" +msgstr "resim göndermek için en az %(min_rep)s puan toplamalısınız" #: forum/views/writers.py:72 -msgid "allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'" -msgstr "izin verilen dosya türleri ''jpeg, jpg, gif, bmp, tif, png''" +#, python-format +msgid "allowed file types are '%(file_types)s'" +msgstr "izin verilen dosya türleri '%(file_types)s'" #: forum/views/writers.py:74 #, python-format diff --git a/askbot/locale/vi/LC_MESSAGES/django.po b/askbot/locale/vi/LC_MESSAGES/django.po index 0c8cb9af..00b324e6 100644 --- a/askbot/locale/vi/LC_MESSAGES/django.po +++ b/askbot/locale/vi/LC_MESSAGES/django.po @@ -3986,11 +3986,13 @@ msgid "profile - email subscriptions" msgstr "" #: forum/views/writers.py:70 -msgid "uploading images is limited to users with >60 reputation points" -msgstr "sorry, file uploading requires karma >60" +#, python-format +msgid "uploading images is limited to users with >%(min_rep)s reputation points" +msgstr "sorry, file uploading requires karma >%(min_rep)s" #: forum/views/writers.py:72 -msgid "allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'" +#, python-format +msgid "allowed file types are '%(file_types)s'" msgstr "" #: forum/views/writers.py:74 diff --git a/askbot/locale/zh-cn/LC_MESSAGES/django.po b/askbot/locale/zh-cn/LC_MESSAGES/django.po index b23f6ea6..a5d9375c 100644 --- a/askbot/locale/zh-cn/LC_MESSAGES/django.po +++ b/askbot/locale/zh-cn/LC_MESSAGES/django.po @@ -4050,13 +4050,15 @@ msgid "profile - email subscriptions" msgstr "收藏 - 用户资料" #: forum/views/writers.py:70 -msgid "uploading images is limited to users with >60 reputation points" -msgstr "上传图片只限于积分+60以上注册用户!" +#, python-format +msgid "uploading images is limited to users with >%(min_rep)s reputation points" +msgstr "上传图片只限于积分+%(min_rep)s以上注册用户!" # todo take these out of settings #: forum/views/writers.py:72 -msgid "allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'" -msgstr "只允许上传'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'类型的文件!" +#, python-format +msgid "allowed file types are '%(file_types)s'" +msgstr "只允许上传'%(file_types)s'类型的文件!" #: forum/views/writers.py:74 #, python-format diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py index 8738ce41..ceb93dd7 100644 --- a/askbot/models/__init__.py +++ b/askbot/models/__init__.py @@ -14,6 +14,7 @@ from django.utils.safestring import mark_safe from django.db import models from django.conf import settings as django_settings from django.contrib.contenttypes.models import ContentType +from django.core import exceptions from askbot import const from askbot.conf import settings as askbot_settings from askbot.models.question import Question, QuestionRevision @@ -28,9 +29,9 @@ from askbot.models import signals from askbot.models.repute import Badge, Award, Repute from askbot import auth from askbot.utils.decorators import auto_now_timestamp +from askbot.startup_tests import run_startup_tests -class PermissionError(Exception): - pass +run_startup_tests() User.add_to_class( 'status', @@ -77,14 +78,14 @@ def user_assert_can_vote_for_post( post = None, direction = None, ): - """raises PermissionError exception + """raises exceptions.PermissionDenied exception if user can't in fact upvote :param:direction can be 'up' or 'down' :param:post can be instance of question or answer """ if self.is_blocked(): - raise PermissionError( + raise exceptions.PermissionDenied( _( 'Sorry your account appears to be blocked ' + 'and you cannot vote - please contact the ' + @@ -92,7 +93,7 @@ def user_assert_can_vote_for_post( ) ) if self.is_suspended(): - raise PermissionError( + raise exceptions.PermissionDenied( _( 'Sorry your account appears to be suspended ' + 'and you cannot vote - please contact the ' + @@ -104,17 +105,17 @@ def user_assert_can_vote_for_post( if direction == 'up': if self.reputation < askbot_settings.MIN_REP_TO_VOTE_UP: - msg = _(">%(points)s points required to upvote, bitch") % \ + msg = _(">%(points)s points required to upvote") % \ {'points': askbot_settings.MIN_REP_TO_VOTE_UP} - raise PermissionError(msg) + raise exceptions.PermissionDenied(msg) else: if self.reputation < askbot_settings.MIN_REP_TO_VOTE_DOWN: msg = _(">%(points)s points required to downvote") % \ {'points': askbot_settings.MIN_REP_TO_VOTE_DOWN} - raise PermissionError(msg) + raise exceptions.PermissionDenied(msg) if self == post.author: - raise PermissionError('cannot vote for own posts') + raise exceptions.PermissionDenied('cannot vote for own posts') def user_get_old_vote_for_post(self, post): @@ -137,13 +138,39 @@ def user_get_old_vote_for_post(self, post): return old_votes[0] + +def user_assert_can_upload_file(request_user): + + if request_user.is_authenticated(): + if request_user.is_suspended(): + raise exceptions.PermissionDenied( + _('Sorry, suspended users cannot upload files') + ) + elif request_user.is_blocked(): + raise exceptions.PermissionDenied( + _('Sorry, blocked users cannot upload files') + ) + elif request_user.is_moderator(): + return + elif request_user.is_administrator(): + return + if request_user.reputation < askbot_settings.MIN_REP_TO_UPLOAD_FILES: + msg = _( + 'uploading images is limited to users ' + + 'with >%(min_rep)s reputation points' + ) % {'min_rep': askbot_settings.MIN_REP_TO_UPLOAD_FILES } + raise exceptions.PermissionDenied(msg) + else: + raise exceptions.PermissionDenied(_('Sorry, anonymous users cannot upload files')) + + def user_assert_can_revoke_old_vote(self, vote): - """raises PermissionError if old vote + """raises exceptions.PermissionDenied if old vote cannot be revoked due to age of the vote """ if (datetime.datetime.now().day - vote.voted_at.day) \ >= askbot_settings.MAX_DAYS_TO_CANCEL_VOTE: - raise PermissionError(_('cannot revoke old vote')) + raise exceptions.PermissionDenied(_('cannot revoke old vote')) def user_get_unused_votes_today(self): """returns number of votes that are @@ -437,6 +464,7 @@ def user_can_moderate_user(self, other): else: return False + def user_get_q_sel_email_feed_frequency(self): #print 'looking for frequency for user %s' % self try: @@ -664,6 +692,7 @@ User.add_to_class('get_status_display', user_get_status_display) User.add_to_class('assert_can_vote_for_post', user_assert_can_vote_for_post) User.add_to_class('get_old_vote_for_post', user_get_old_vote_for_post) User.add_to_class('assert_can_revoke_old_vote', user_assert_can_revoke_old_vote) +User.add_to_class('assert_can_upload_file', user_assert_can_upload_file) User.add_to_class('get_unused_votes_today', user_get_unused_votes_today) #todo: move this to askbot/utils ?? @@ -1098,8 +1127,6 @@ EmailFeedSetting = EmailFeedSetting __all__ = [ 'signals', - 'PermissionError', - 'Question', 'QuestionRevision', 'QuestionView', diff --git a/askbot/setup_templates/settings.py b/askbot/setup_templates/settings.py index 6dd443c4..8dfc765e 100644 --- a/askbot/setup_templates/settings.py +++ b/askbot/setup_templates/settings.py @@ -56,12 +56,12 @@ LANGUAGE_CODE = 'en' # Absolute path to the directory that holds media. # Example: "/home/media/media.lawrence.com/" -MEDIA_ROOT = os.path.join(os.path.dirname(__file__), 'askbot', 'upfiles') +ASKBOT_FILE_UPLOAD_DIR = os.path.join(os.path.dirname(__file__), 'askbot', 'upfiles') -# URL that handles the media served from MEDIA_ROOT. Make sure to use a +# URL that handles the media served from ASKBOT_FILE_UPLOAD_DIR. Make sure to use a # trailing slash if there is a path component (optional in other cases). # Examples: "http://media.lawrence.com", "http://example.com/media/" -MEDIA_URL = ''#set this to serve uploaded files correctly +ASKBOT_FILE_UPLOAD_URL = ''#set this to serve uploaded files correctly PROJECT_ROOT = os.path.dirname(__file__) @@ -118,8 +118,8 @@ FILE_UPLOAD_HANDLERS = ( 'django.core.files.uploadhandler.MemoryFileUploadHandler', 'django.core.files.uploadhandler.TemporaryFileUploadHandler', ) -ALLOW_FILE_TYPES = ('.jpg', '.jpeg', '.gif', '.bmp', '.png', '.tiff') -ALLOW_MAX_FILE_SIZE = 1024 * 1024 #result in bytes +ASKBOT_ALLOWED_UPLOAD_FILE_TYPES = ('.jpg', '.jpeg', '.gif', '.bmp', '.png', '.tiff') +ASKBOT_MAX_UPLOAD_FILE_SIZE = 1024 * 1024 #result in bytes DEFAULT_FILE_STORAGE = 'django.core.files.storage.FileSystemStorage' @@ -196,8 +196,8 @@ logging.basicConfig( # # this will allow running your forum with url like http://site.com/forum # -# FORUM_SCRIPT_ALIAS = 'forum/' +# ASKBOT_URL = 'forum/' # -FORUM_SCRIPT_ALIAS = '' #no leading slash, default = '' empty string +ASKBOT_URL = '' #no leading slash, default = '' empty string _ = lambda v:v #fake translation function for the login url -LOGIN_URL = '/%s%s%s' % (FORUM_SCRIPT_ALIAS,_('account/'),_('signin/')) +LOGIN_URL = '/%s%s%s' % (ASKBOT_URL,_('account/'),_('signin/')) diff --git a/askbot/setup_templates/urls.py b/askbot/setup_templates/urls.py index 3868ae74..3d05276b 100644 --- a/askbot/setup_templates/urls.py +++ b/askbot/setup_templates/urls.py @@ -8,7 +8,7 @@ from django.contrib import admin admin.autodiscover() urlpatterns = patterns('', - (r'^%s' % settings.FORUM_SCRIPT_ALIAS, include('askbot.urls')), + (r'%s' % settings.ASKBOT_URL, include('askbot.urls')), (r'^admin/', include(admin.site.urls)), #(r'^cache/', include('keyedcache.urls')), - broken views disable for now (r'^settings/', include('askbot.deps.livesettings.urls')), diff --git a/askbot/skins/default/media/js/wmd/wmd.js b/askbot/skins/default/media/js/wmd/wmd.js index 70271d4d..e4ed2764 100755 --- a/askbot/skins/default/media/js/wmd/wmd.js +++ b/askbot/skins/default/media/js/wmd/wmd.js @@ -252,7 +252,10 @@ Attacklab.wmdBase = function(){ text = text.replace('http://ftp://', 'ftp://'); if (text.indexOf('http://') === -1 && text.indexOf('ftp://') === -1) { - text = 'http://' + text; + if (type == 0){ + //add http only to urls + text = 'http://' + text; + } } } diff --git a/askbot/skins/default/templates/base.html b/askbot/skins/default/templates/base.html index dd7c6083..5823c1ac 100644 --- a/askbot/skins/default/templates/base.html +++ b/askbot/skins/default/templates/base.html @@ -24,7 +24,7 @@ diff --git a/askbot/skins/default/templates/base_content.html b/askbot/skins/default/templates/base_content.html index 000b5358..a2ab8a47 100644 --- a/askbot/skins/default/templates/base_content.html +++ b/askbot/skins/default/templates/base_content.html @@ -22,7 +22,7 @@ diff --git a/askbot/startup_tests.py b/askbot/startup_tests.py new file mode 100644 index 00000000..6a238965 --- /dev/null +++ b/askbot/startup_tests.py @@ -0,0 +1,43 @@ +"""tests to be performed +in the beginning of models/__init__.py + +the purpose of this module is to validate deployment of askbot + +the main function is run_startup_tests +""" +from django.conf import settings +from django.core.exceptions import ImproperlyConfigured + +def run_startup_tests(): + """main function that runs + all startup tests + """ + + #todo: refactor this when another test arrives + url = settings.ASKBOT_URL + if url != '': + + if isinstance(url, str) or isinstance(url, unicode): + pass + else: + msg = 'setting ASKBOT_URL must be of string or unicode type' + raise ImproperlyConfigured(msg) + + if url == '/': + msg = 'value "/" for ASKBOT_URL is invalid. '+ \ + 'Please, either make ASKBOT_URL an empty string ' + \ + 'or a non-empty path, ending with "/" but not ' + \ + 'starting with "/", for example: "forum/"' + raise ImproperlyConfigured(msg) + else: + try: + assert(url.endswith('/')) + except AssertionError: + msg = 'if ASKBOT_URL setting is not empty, ' + \ + 'it must end with /' + raise ImproperlyConfigured(msg) + try: + assert(not url.startswith('/')) + except AssertionError: + msg = 'if ASKBOT_URL setting is not empty, ' + \ + 'it must not start with /' diff --git a/askbot/templatetags/extra_tags.py b/askbot/templatetags/extra_tags.py index ebe6dc7f..69ed4669 100644 --- a/askbot/templatetags/extra_tags.py +++ b/askbot/templatetags/extra_tags.py @@ -349,7 +349,7 @@ def get_latest_changed_timestamp(): def media(url): url = skins.loaders.find_media_source(url) if url: - url = '///' + settings.FORUM_SCRIPT_ALIAS + '/m/' + url + url = '///' + settings.ASKBOT_URL + '/m/' + url return os.path.normpath(url) + '?v=%d' \ % askbot_settings.MEDIA_RESOURCE_REVISION else: @@ -424,7 +424,7 @@ class BlockMediaUrlNode(template.Node): def __init__(self,nodelist): self.items = nodelist def render(self,context): - prefix = '///' + settings.FORUM_SCRIPT_ALIAS + 'm/' + prefix = '///' + settings.ASKBOT_URL + 'm/' url = '' if self.items: url += '/' diff --git a/askbot/tests.py b/askbot/tests.py index c56f70c5..804553f0 100644 --- a/askbot/tests.py +++ b/askbot/tests.py @@ -12,14 +12,17 @@ import datetime import time import functools import django.core.mail +from django.core import exceptions from django.conf import settings as django_settings from django.test import TestCase from django.template import defaultfilters from django.core import management from django.core.urlresolvers import reverse +from django.contrib.auth.models import AnonymousUser from askbot.models import User, Question, Answer, Activity from askbot.models import EmailFeedSetting from askbot import const +from askbot.conf import settings as askbot_settings def email_alert_test(test_func): """decorator for test methods in EmailAlertTests @@ -119,6 +122,62 @@ def get_re_notif_after(timestamp): ) return notifications + +class UploadPermissionTests(TestCase): + """Tests permissions for file uploads + """ + + def setUp(self): + self.user = create_user( + username = 'test', + email = 'test@test.com' + ) + self.min_rep = askbot_settings.MIN_REP_TO_UPLOAD_FILES + + def test_suspended_user_cannot_upload(self): + self.user.set_status('s') + self.assertRaises( + exceptions.PermissionDenied, + self.user.assert_can_upload_file + ) + + def test_blocked_user_cannot_upload(self): + self.user.set_status('b') + self.assertRaises( + exceptions.PermissionDenied, + self.user.assert_can_upload_file + ) + def test_low_rep_user_cannot_upload(self): + self.user.reputation = self.min_rep - 1 + self.assertRaises( + exceptions.PermissionDenied, + self.user.assert_can_upload_file + ) + + def test_high_rep_user_can_upload(self): + self.user.reputation = self.min_rep + try: + self.user.assert_can_upload_file() + except exceptions.PermissionDenied: + fail('high rep user must be able to upload') + + def test_low_rep_moderator_can_upload(self): + assert(self.user.reputation < self.min_rep) + self.user.set_status('m') + try: + self.user.assert_can_upload_file() + except exceptions.PermissionDenied: + fail('high rep user must be able to upload') + + def test_low_rep_administrator_can_upload(self): + assert(self.user.reputation < self.min_rep) + self.user.is_superuser = True + try: + self.user.assert_can_upload_file() + except exceptions.PermissionDenied: + fail('high rep user must be able to upload') + + class EmailAlertTests(TestCase): """Base class for testing delayed Email notifications that are triggered by the send_email_alerts diff --git a/askbot/utils/forms.py b/askbot/utils/forms.py index a480419e..62aa0170 100644 --- a/askbot/utils/forms.py +++ b/askbot/utils/forms.py @@ -10,7 +10,7 @@ from askbot import const import logging import urllib -DEFAULT_NEXT = '/' + getattr(settings, 'FORUM_SCRIPT_ALIAS') +DEFAULT_NEXT = '/' + getattr(settings, 'ASKBOT_URL') def clean_next(next): if next is None: return DEFAULT_NEXT diff --git a/askbot/views/commands.py b/askbot/views/commands.py index 0ddfc36e..07cc57a5 100644 --- a/askbot/views/commands.py +++ b/askbot/views/commands.py @@ -10,6 +10,7 @@ import datetime from django.conf import settings from askbot.conf import settings as askbot_settings from django.utils import simplejson +from django.core import exceptions from django.http import HttpResponse, HttpResponseRedirect from django.http import HttpResponseForbidden from django.shortcuts import get_object_or_404, render_to_response @@ -35,7 +36,7 @@ def process_vote(user = None, vote_direction = None, post = None): """ if user.is_anonymous(): - raise PermissionError(_('anonymous users cannot vote')) + raise exceptions.PermissionDenied(_('anonymous users cannot vote')) user.assert_can_vote_for_post( post = post, @@ -54,7 +55,7 @@ def process_vote(user = None, vote_direction = None, post = None): #this is a new vote votes_left = user.get_unused_votes_today() if votes_left <= 0: - raise PermissionError( + raise exceptions.PermissionDenied( _('Sorry you ran out of votes for today') ) diff --git a/askbot/views/readers.py b/askbot/views/readers.py index 9d3229c7..5bd67422 100644 --- a/askbot/views/readers.py +++ b/askbot/views/readers.py @@ -269,7 +269,7 @@ def question(request, id):#refactor - long subroutine. display question body, an question = get_object_or_404(Question, id=id) try: - pattern = r'/%s%s%d/([\w-]+)' % (settings.FORUM_SCRIPT_ALIAS,_('question/'), question.id) + pattern = r'/%s%s%d/([\w-]+)' % (settings.ASKBOT_URL,_('question/'), question.id) path_re = re.compile(pattern) logging.debug(pattern) logging.debug(request.path) diff --git a/askbot/views/writers.py b/askbot/views/writers.py index 03707205..97777afa 100644 --- a/askbot/views/writers.py +++ b/askbot/views/writers.py @@ -5,8 +5,11 @@ This module contains views that allow adding, editing, and deleting main textual content. """ import os.path -import time, datetime, random -from django.core.files.storage import default_storage +import time +import datetime +import random +import logging +from django.core.files.storage import FileSystemStorage from django.shortcuts import render_to_response, get_object_or_404 from django.contrib.auth.decorators import login_required from django.http import HttpResponseRedirect, HttpResponse, HttpResponseForbidden, Http404 @@ -15,7 +18,7 @@ from django.utils import simplejson from django.utils.html import strip_tags from django.utils.translation import ugettext as _ from django.core.urlresolvers import reverse -from django.core.exceptions import PermissionDenied +from django.core import exceptions from django.conf import settings from askbot import auth @@ -35,49 +38,69 @@ QUESTIONS_PAGE_SIZE = 10 ANSWERS_PAGE_SIZE = 10 def upload(request):#ajax upload file to a question or answer - class FileTypeNotAllow(Exception): - pass - class FileSizeNotAllow(Exception): - pass - class UploadPermissionNotAuthorized(Exception): - pass + """view that handles file upload via Ajax + """ #%s xml_template = "%s" + f = request.FILES['file-upload'] + # check upload permission + result = '' + error = '' + new_file_name = '' try: - f = request.FILES['file-upload'] - # check upload permission - if not auth.can_upload_files(request.user): - raise UploadPermissionNotAuthorized + + #may raise exceptions.PermissionDenied + request.user.assert_can_upload_file() # check file type - file_name_suffix = os.path.splitext(f.name)[1].lower() - if not file_name_suffix in settings.ALLOW_FILE_TYPES: - raise FileTypeNotAllow + file_extension = os.path.splitext(f.name)[1].lower() + if not file_extension in settings.ASKBOT_ALLOWED_UPLOAD_FILE_TYPES: + msg = _("allowed file types are '%(file_types)s'") % \ + "', '".join(settings.ASKBOT_ALLOWED_UPLOAD_FILE_TYPES) + raise exceptions.PermissionDenied(msg) # generate new file name - new_file_name = str(time.time()).replace('.', str(random.randint(0,100000))) + file_name_suffix + new_file_name = str( + time.time() + ).replace( + '.', + str(random.randint(0,100000)) + ) + file_extension + + file_storage = FileSystemStorage( + location = settings.ASKBOT_FILE_UPLOAD_DIR, + base_url = reverse('uploaded_file', kwargs = {'path':''}), + ) # use default storage to store file - default_storage.save(new_file_name, f) + file_storage.save(new_file_name, f) # check file size # byte - size = default_storage.size(new_file_name) - if size > settings.ALLOW_MAX_FILE_SIZE: - default_storage.delete(new_file_name) - raise FileSizeNotAllow - - result = xml_template % ('Good', '', default_storage.url(new_file_name)) - except UploadPermissionNotAuthorized: - result = xml_template % ('', _('uploading images is limited to users with >60 reputation points'), '') - except FileTypeNotAllow: - result = xml_template % ('', _("allowed file types are 'jpg', 'jpeg', 'gif', 'bmp', 'png', 'tiff'"), '') - except FileSizeNotAllow: - result = xml_template % ('', _("maximum upload file size is %sK") % settings.ALLOW_MAX_FILE_SIZE / 1024, '') - except Exception: - result = xml_template % ('', _('Error uploading file. Please contact the site administrator. Thank you. %s' % Exception), '') - - return HttpResponse(result, mimetype="application/xml") + size = file_storage.size(new_file_name) + if size > settings.ASKBOT_MAX_UPLOAD_FILE_SIZE: + file_storage.delete(new_file_name) + msg = _("maximum upload file size is %(file_size)sK") % \ + {'file_size': settings.ASKBOT_MAX_UPLOAD_FILE_SIZE} + raise exceptions.PermissionDenied(msg) + + except exceptions.PermissionDenied, e: + error = str(e) + except Exception, e: + logging.critical(str(e)) + error = _('Error uploading file. Please contact the site administrator. Thank you.') + + if error == '': + result = 'Good' + file_url = file_storage.url(new_file_name) + else: + result = '' + file_url = '' + + xml = xml_template % (result, error, file_url) + print xml + + return HttpResponse(xml, mimetype="application/xml") #@login_required #actually you can post anonymously, but then must register def ask(request):#view used to ask a new question @@ -87,6 +110,7 @@ def ask(request):#view used to ask a new question user can start posting a question anonymously but then must login/register in order for the question go be shown """ + if request.method == "POST": form = forms.AskForm(request.POST) if form.is_valid(): @@ -391,4 +415,4 @@ def delete_comment(request, object_id='', comment_id='', commented_object_type=N obj.save() user = request.user return __generate_comments_json(obj, user) - raise PermissionDenied() + raise exceptions.PermissionDenied() -- cgit v1.2.3-1-g7c22