summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--askbot/auth.py14
-rw-r--r--askbot/context.py2
-rw-r--r--askbot/locale/de/LC_MESSAGES/django.po10
-rw-r--r--askbot/locale/en/LC_MESSAGES/django.po8
-rw-r--r--askbot/locale/es/LC_MESSAGES/django.po6
-rw-r--r--askbot/locale/fi/LC_MESSAGES/django.po10
-rw-r--r--askbot/locale/ru/LC_MESSAGES/django.po10
-rw-r--r--askbot/locale/sr/LC_MESSAGES/django.po10
-rw-r--r--askbot/locale/tr/LC_MESSAGES/django.po10
-rw-r--r--askbot/locale/vi/LC_MESSAGES/django.po8
-rw-r--r--askbot/locale/zh-cn/LC_MESSAGES/django.po10
-rw-r--r--askbot/models/__init__.py53
-rw-r--r--askbot/setup_templates/settings.py16
-rw-r--r--askbot/setup_templates/urls.py2
-rwxr-xr-xaskbot/skins/default/media/js/wmd/wmd.js5
-rw-r--r--askbot/skins/default/templates/base.html2
-rw-r--r--askbot/skins/default/templates/base_content.html2
-rw-r--r--askbot/startup_tests.py43
-rw-r--r--askbot/templatetags/extra_tags.py4
-rw-r--r--askbot/tests.py59
-rw-r--r--askbot/utils/forms.py2
-rw-r--r--askbot/views/commands.py5
-rw-r--r--askbot/views/readers.py2
-rw-r--r--askbot/views/writers.py94
24 files changed, 274 insertions, 113 deletions
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 @@
<script type="text/javascript">google.load("jquery", "1.2.6");</script>
<script type="text/javascript">
var i18nLang = '{{settings.LANGUAGE_CODE}}';
- var scriptUrl = '/{{settings.FORUM_SCRIPT_ALIAS}}'
+ var scriptUrl = '/{{settings.ASKBOT_URL}}'
var askbotSkin = '{{settings.ASKBOT_DEFAULT_SKIN}}';
</script>
<script type='text/javascript' src='{% media "/media/js/com.cnprog.i18n.js" %}'></script>
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 @@
<script type="text/javascript">google.load("jquery", "1.2.6");</script>
<script type="text/javascript">
var i18nLang = '{{ settings.LANGUAGE_CODE }}';
- var scriptUrl = '/{{settings.FORUM_SCRIPT_ALIAS}}'
+ var scriptUrl = '/{{settings.ASKBOT_URL}}'
var askbotSkin = '{{settings.ASKBOT_DEFAULT_SKIN}}';
</script>
<script type='text/javascript' src='{% media "/media/js/com.cnprog.i18n.js" %}'></script>
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
+ """
#<result><msg><![CDATA[%s]]></msg><error><![CDATA[%s]]></error><file_url>%s</file_url></result>
xml_template = "<result><msg><![CDATA[%s]]></msg><error><![CDATA[%s]]></error><file_url>%s</file_url></result>"
+ 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()