mirror of
https://github.com/reddit-archive/reddit.git
synced 2026-01-29 16:58:21 -05:00
Move permissions (and related strings) to lib.
This commit is contained in:
@@ -169,6 +169,13 @@ class StringsSource(Source):
|
||||
self.keys = keys
|
||||
self.prepend = prepend
|
||||
|
||||
@staticmethod
|
||||
def _encoder(obj):
|
||||
from r2.lib import strings, translation
|
||||
if isinstance(obj, strings.StringHandler):
|
||||
return obj.string_dict
|
||||
raise TypeError
|
||||
|
||||
def get_source(self):
|
||||
from pylons.i18n import get_lang
|
||||
from r2.lib import strings, translation
|
||||
@@ -184,7 +191,7 @@ class StringsSource(Source):
|
||||
else:
|
||||
data = dict(strings.strings)
|
||||
|
||||
output = self.prepend + json.dumps(data) + "\n"
|
||||
output = self.prepend + json.dumps(data, default=self._encoder) + "\n"
|
||||
|
||||
if self.lang:
|
||||
translation.set_lang(old_lang)
|
||||
|
||||
97
r2/r2/lib/permissions.py
Normal file
97
r2/r2/lib/permissions.py
Normal file
@@ -0,0 +1,97 @@
|
||||
# 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.i18n import _
|
||||
|
||||
class PermissionSet(dict):
|
||||
ALL = 'all'
|
||||
|
||||
info = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(PermissionSet, self).__init__(*args, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def loads(cls, encoded, validate=False):
|
||||
if not encoded:
|
||||
return cls()
|
||||
result = cls(((term[1:], term[0] == '+')
|
||||
for term in encoded.split(',')))
|
||||
if result.get(cls.ALL) == False:
|
||||
del result[cls.ALL]
|
||||
if validate and not result.is_valid():
|
||||
raise ValueError
|
||||
return result
|
||||
|
||||
def dumps(self):
|
||||
if self.is_superuser():
|
||||
return '+all'
|
||||
return ','.join('-+'[bool(v)] + k for k, v in sorted(self.iteritems()))
|
||||
|
||||
def is_superuser(self):
|
||||
return bool(super(PermissionSet, self).get(self.ALL))
|
||||
|
||||
def is_valid(self):
|
||||
if not self.info:
|
||||
return False
|
||||
for k in self:
|
||||
if k != self.ALL and k not in self.info:
|
||||
return False
|
||||
return True
|
||||
|
||||
def get(self, key, default=None):
|
||||
if self.info and self.is_superuser():
|
||||
return True if key in self.info else default
|
||||
return super(PermissionSet, self).get(key, default)
|
||||
|
||||
def __getitem__(self, key):
|
||||
if self.info and self.is_superuser():
|
||||
return key in self.info
|
||||
return super(PermissionSet, self).get(key, False)
|
||||
|
||||
|
||||
class ModeratorPermissionSet(PermissionSet):
|
||||
info = dict(
|
||||
access=dict(
|
||||
title=_('access'),
|
||||
description=_('manage the lists of contributors and banned users'),
|
||||
),
|
||||
config=dict(
|
||||
title=_('config'),
|
||||
description=_('edit settings, sidebar, css, and images'),
|
||||
),
|
||||
flair=dict(
|
||||
title=_('flair'),
|
||||
description=_('manage user flair, link flair, and flair templates'),
|
||||
),
|
||||
posts=dict(
|
||||
title=_('posts'),
|
||||
description=_(
|
||||
'use the approve, remove, spam, distinguish, and nsfw buttons'),
|
||||
),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def loads(cls, encoded, **kwargs):
|
||||
if encoded is None:
|
||||
return cls(all=True)
|
||||
return super(ModeratorPermissionSet, cls).loads(encoded, **kwargs)
|
||||
@@ -33,6 +33,7 @@ from pylons.i18n import _, ungettext, get_lang
|
||||
import random
|
||||
import babel.numbers
|
||||
|
||||
from r2.lib.permissions import ModeratorPermissionSet
|
||||
from r2.lib.translation import set_lang
|
||||
|
||||
__all__ = ['StringHandler', 'strings', 'PluralManager', 'plurals',
|
||||
@@ -192,6 +193,15 @@ Note: there are a couple of places outside of your subreddit where someone can c
|
||||
missing_credit_city = _("missing city"),
|
||||
missing_credit_state = _("missing state or province"),
|
||||
missing_credit_zip = _("missing zip code"),
|
||||
|
||||
permissions = dict(
|
||||
info=dict(
|
||||
moderator=ModeratorPermissionSet.info,
|
||||
moderator_invite=ModeratorPermissionSet.info,
|
||||
),
|
||||
all_msg=_("full permissions"),
|
||||
none_msg=_("no permissions"),
|
||||
),
|
||||
)
|
||||
|
||||
class StringHandler(object):
|
||||
@@ -213,7 +223,7 @@ class StringHandler(object):
|
||||
if isinstance(rval, (str, unicode)):
|
||||
return _(rval)
|
||||
elif isinstance(rval, dict):
|
||||
return dict((k, _(v)) for k, v in rval.iteritems())
|
||||
return StringHandler(**rval)
|
||||
else:
|
||||
raise AttributeError
|
||||
|
||||
|
||||
@@ -144,14 +144,6 @@ def js_config(extra_config=None):
|
||||
"clicktracker_url": g.clicktracker_url,
|
||||
"uitracker_url": g.uitracker_url,
|
||||
"static_root": static(''),
|
||||
"permissions": {
|
||||
"info": {
|
||||
"moderator": ModeratorPermissionSet.info,
|
||||
"moderator_invite": ModeratorPermissionSet.info,
|
||||
},
|
||||
"all_msg": _("full permissions"),
|
||||
"none_msg": _("no permissions"),
|
||||
},
|
||||
}
|
||||
|
||||
if extra_config:
|
||||
|
||||
@@ -37,6 +37,7 @@ from r2.lib.db.userrel import UserRel
|
||||
from r2.lib.db.operators import lower, or_, and_, desc
|
||||
from r2.lib.errors import UserRequiredException
|
||||
from r2.lib.memoize import memoize
|
||||
from r2.lib.permissions import ModeratorPermissionSet
|
||||
from r2.lib.utils import tup, interleave_lists, last_modified_multi, flatten
|
||||
from r2.lib.utils import timeago, summarize_markdown
|
||||
from r2.lib.cache import sgm
|
||||
@@ -57,81 +58,6 @@ from r2.models.wiki import WikiPage
|
||||
import os.path
|
||||
import random
|
||||
|
||||
class PermissionSet(dict):
|
||||
ALL = 'all'
|
||||
|
||||
info = None
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(PermissionSet, self).__init__(*args, **kwargs)
|
||||
|
||||
@classmethod
|
||||
def loads(cls, encoded, validate=False):
|
||||
if not encoded:
|
||||
return cls()
|
||||
result = cls(((term[1:], term[0] == '+')
|
||||
for term in encoded.split(',')))
|
||||
if result.get(cls.ALL) == False:
|
||||
del result[cls.ALL]
|
||||
if validate and not result.is_valid():
|
||||
raise ValueError
|
||||
return result
|
||||
|
||||
def dumps(self):
|
||||
if self.is_superuser():
|
||||
return '+all'
|
||||
return ','.join('-+'[bool(v)] + k for k, v in sorted(self.iteritems()))
|
||||
|
||||
def is_superuser(self):
|
||||
return bool(super(PermissionSet, self).get(self.ALL))
|
||||
|
||||
def is_valid(self):
|
||||
if not self.info:
|
||||
return False
|
||||
for k in self:
|
||||
if k != self.ALL and k not in self.info:
|
||||
return False
|
||||
return True
|
||||
|
||||
def get(self, key, default=None):
|
||||
if self.info and self.is_superuser():
|
||||
return True if key in self.info else default
|
||||
return super(PermissionSet, self).get(key, default)
|
||||
|
||||
def __getitem__(self, key):
|
||||
if self.info and self.is_superuser():
|
||||
return key in self.info
|
||||
return super(PermissionSet, self).get(key, False)
|
||||
|
||||
|
||||
class ModeratorPermissionSet(PermissionSet):
|
||||
info = dict(
|
||||
access=dict(
|
||||
title=_('access'),
|
||||
description=_('manage the lists of contributors and banned users'),
|
||||
),
|
||||
config=dict(
|
||||
title=_('config'),
|
||||
description=_('edit settings, sidebar, css, and images'),
|
||||
),
|
||||
flair=dict(
|
||||
title=_('flair'),
|
||||
description=_('manage user flair, link flair, and flair templates'),
|
||||
),
|
||||
posts=dict(
|
||||
title=_('posts'),
|
||||
description=_(
|
||||
'use the approve, remove, spam, distinguish, and nsfw buttons'),
|
||||
),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def loads(cls, encoded, **kwargs):
|
||||
if encoded is None:
|
||||
return cls(all=True)
|
||||
return super(ModeratorPermissionSet, cls).loads(encoded, **kwargs)
|
||||
|
||||
|
||||
class SubredditExists(Exception): pass
|
||||
|
||||
class Subreddit(Thing, Printable):
|
||||
|
||||
@@ -212,7 +212,7 @@ r.ui.PermissionEditor = function(el) {
|
||||
var permission_type = params.type
|
||||
var name = params.name
|
||||
this.form_id = permission_type + "-permissions-" + name
|
||||
this.permission_info = r.config.permissions.info[permission_type]
|
||||
this.permission_info = r.strings.permissions.info[permission_type]
|
||||
this.sorted_perm_keys = $.map(this.permission_info,
|
||||
function(v, k) { return k })
|
||||
this.sorted_perm_keys.sort()
|
||||
@@ -235,7 +235,7 @@ r.ui.PermissionEditor.init = function() {
|
||||
})
|
||||
}
|
||||
activate('body')
|
||||
for (var permission_type in r.config.permissions.info) {
|
||||
for (var permission_type in r.strings.permissions.info) {
|
||||
$('.' + permission_type + '-table')
|
||||
.on('insert-row', 'tr', function(e) { activate(this) })
|
||||
}
|
||||
@@ -290,7 +290,7 @@ r.ui.PermissionEditor.prototype = $.extend(new r.ui.Base(), {
|
||||
update()
|
||||
})
|
||||
$label.append(
|
||||
document.createTextNode(r.config.permissions.all_msg))
|
||||
document.createTextNode(r.strings.permissions.all_msg))
|
||||
} else if (info) {
|
||||
$input.change(update)
|
||||
$label.append(document.createTextNode(info.title))
|
||||
@@ -335,7 +335,7 @@ r.ui.PermissionEditor.prototype = $.extend(new r.ui.Base(), {
|
||||
var info = this.permission_info[perm]
|
||||
var text
|
||||
if (perm == "all") {
|
||||
text = r.config.permissions.all_msg
|
||||
text = r.strings.permissions.all_msg
|
||||
} else if (info) {
|
||||
text = info.title
|
||||
} else {
|
||||
@@ -388,7 +388,7 @@ r.ui.PermissionEditor.prototype = $.extend(new r.ui.Base(), {
|
||||
}
|
||||
if (!spans.length) {
|
||||
spans.push($('<span class="permission-bit">')
|
||||
.text(r.config.permissions.none_msg)
|
||||
.text(r.strings.permissions.none_msg)
|
||||
.addClass("none"))
|
||||
}
|
||||
var $new_summary = $('<div class="permission-summary">')
|
||||
|
||||
82
r2/r2/tests/unit/lib/permissions_test.py
Normal file
82
r2/r2/tests/unit/lib/permissions_test.py
Normal file
@@ -0,0 +1,82 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import unittest
|
||||
|
||||
from r2.tests import stage_for_paste
|
||||
|
||||
stage_for_paste()
|
||||
|
||||
from r2.lib.permissions import PermissionSet, ModeratorPermissionSet
|
||||
|
||||
class TestPermissionSet(PermissionSet):
|
||||
info = dict(x={}, y={})
|
||||
|
||||
class PermissionSetTest(unittest.TestCase):
|
||||
def test_dumps(self):
|
||||
self.assertEquals(
|
||||
'+all', PermissionSet(all=True).dumps())
|
||||
self.assertEquals(
|
||||
'+all', PermissionSet(all=True, other=True).dumps())
|
||||
self.assertEquals(
|
||||
'+a,-b', PermissionSet(a=True, b=False).dumps())
|
||||
|
||||
def test_loads(self):
|
||||
self.assertEquals("", TestPermissionSet.loads(None).dumps())
|
||||
self.assertEquals("", TestPermissionSet.loads("").dumps())
|
||||
self.assertEquals("+x,+y", TestPermissionSet.loads("+x,+y").dumps())
|
||||
self.assertEquals("+x,-y", TestPermissionSet.loads("+x,-y").dumps())
|
||||
self.assertEquals("+all", TestPermissionSet.loads("+x,-y,+all").dumps())
|
||||
self.assertEquals("+x,-y,+z",
|
||||
TestPermissionSet.loads("+x,-y,+z").dumps())
|
||||
self.assertRaises(ValueError,
|
||||
TestPermissionSet.loads, "+x,-y,+z", validate=True)
|
||||
self.assertEquals(
|
||||
"+x,-y",
|
||||
TestPermissionSet.loads("-all,+x,-y", validate=True).dumps())
|
||||
|
||||
def test_is_superuser(self):
|
||||
perm_set = PermissionSet()
|
||||
self.assertFalse(perm_set.is_superuser())
|
||||
perm_set[perm_set.ALL] = True
|
||||
self.assertTrue(perm_set.is_superuser())
|
||||
perm_set[perm_set.ALL] = False
|
||||
self.assertFalse(perm_set.is_superuser())
|
||||
|
||||
def test_is_valid(self):
|
||||
perm_set = PermissionSet()
|
||||
self.assertFalse(perm_set.is_valid())
|
||||
|
||||
perm_set = TestPermissionSet()
|
||||
self.assertTrue(perm_set.is_valid())
|
||||
perm_set['x'] = True
|
||||
self.assertTrue(perm_set.is_valid())
|
||||
perm_set[perm_set.ALL] = True
|
||||
self.assertTrue(perm_set.is_valid())
|
||||
perm_set['z'] = True
|
||||
self.assertFalse(perm_set.is_valid())
|
||||
|
||||
def test_getitem(self):
|
||||
perm_set = PermissionSet()
|
||||
perm_set[perm_set.ALL] = True
|
||||
self.assertFalse(perm_set['x'])
|
||||
|
||||
perm_set = TestPermissionSet()
|
||||
perm_set['x'] = True
|
||||
self.assertTrue(perm_set['x'])
|
||||
self.assertFalse(perm_set['y'])
|
||||
perm_set['x'] = False
|
||||
self.assertFalse(perm_set['x'])
|
||||
perm_set[perm_set.ALL] = True
|
||||
self.assertTrue(perm_set['x'])
|
||||
self.assertTrue(perm_set['y'])
|
||||
self.assertFalse(perm_set['z'])
|
||||
self.assertTrue(perm_set.get('x', False))
|
||||
self.assertFalse(perm_set.get('z', False))
|
||||
self.assertTrue(perm_set.get('z', True))
|
||||
|
||||
|
||||
class ModeratorPermissionSetTest(unittest.TestCase):
|
||||
def test_loads(self):
|
||||
self.assertTrue(ModeratorPermissionSet.loads(None).is_superuser())
|
||||
self.assertFalse(ModeratorPermissionSet.loads('').is_superuser())
|
||||
|
||||
@@ -2,86 +2,14 @@
|
||||
|
||||
import unittest
|
||||
|
||||
from r2.lib.permissions import PermissionSet
|
||||
|
||||
from r2.models.account import Account
|
||||
from r2.models.subreddit import (
|
||||
ModeratorPermissionSet,
|
||||
PermissionSet,
|
||||
SRMember,
|
||||
Subreddit,
|
||||
)
|
||||
from r2.models.subreddit import SRMember, Subreddit
|
||||
|
||||
class TestPermissionSet(PermissionSet):
|
||||
info = dict(x={}, y={})
|
||||
|
||||
class PermissionSetTest(unittest.TestCase):
|
||||
def test_dumps(self):
|
||||
self.assertEquals(
|
||||
'+all', PermissionSet(all=True).dumps())
|
||||
self.assertEquals(
|
||||
'+all', PermissionSet(all=True, other=True).dumps())
|
||||
self.assertEquals(
|
||||
'+a,-b', PermissionSet(a=True, b=False).dumps())
|
||||
|
||||
def test_loads(self):
|
||||
self.assertEquals("", TestPermissionSet.loads(None).dumps())
|
||||
self.assertEquals("", TestPermissionSet.loads("").dumps())
|
||||
self.assertEquals("+x,+y", TestPermissionSet.loads("+x,+y").dumps())
|
||||
self.assertEquals("+x,-y", TestPermissionSet.loads("+x,-y").dumps())
|
||||
self.assertEquals("+all", TestPermissionSet.loads("+x,-y,+all").dumps())
|
||||
self.assertEquals("+x,-y,+z",
|
||||
TestPermissionSet.loads("+x,-y,+z").dumps())
|
||||
self.assertRaises(ValueError,
|
||||
TestPermissionSet.loads, "+x,-y,+z", validate=True)
|
||||
self.assertEquals(
|
||||
"+x,-y",
|
||||
TestPermissionSet.loads("-all,+x,-y", validate=True).dumps())
|
||||
|
||||
def test_is_superuser(self):
|
||||
perm_set = PermissionSet()
|
||||
self.assertFalse(perm_set.is_superuser())
|
||||
perm_set[perm_set.ALL] = True
|
||||
self.assertTrue(perm_set.is_superuser())
|
||||
perm_set[perm_set.ALL] = False
|
||||
self.assertFalse(perm_set.is_superuser())
|
||||
|
||||
def test_is_valid(self):
|
||||
perm_set = PermissionSet()
|
||||
self.assertFalse(perm_set.is_valid())
|
||||
|
||||
perm_set = TestPermissionSet()
|
||||
self.assertTrue(perm_set.is_valid())
|
||||
perm_set['x'] = True
|
||||
self.assertTrue(perm_set.is_valid())
|
||||
perm_set[perm_set.ALL] = True
|
||||
self.assertTrue(perm_set.is_valid())
|
||||
perm_set['z'] = True
|
||||
self.assertFalse(perm_set.is_valid())
|
||||
|
||||
def test_getitem(self):
|
||||
perm_set = PermissionSet()
|
||||
perm_set[perm_set.ALL] = True
|
||||
self.assertFalse(perm_set['x'])
|
||||
|
||||
perm_set = TestPermissionSet()
|
||||
perm_set['x'] = True
|
||||
self.assertTrue(perm_set['x'])
|
||||
self.assertFalse(perm_set['y'])
|
||||
perm_set['x'] = False
|
||||
self.assertFalse(perm_set['x'])
|
||||
perm_set[perm_set.ALL] = True
|
||||
self.assertTrue(perm_set['x'])
|
||||
self.assertTrue(perm_set['y'])
|
||||
self.assertFalse(perm_set['z'])
|
||||
self.assertTrue(perm_set.get('x', False))
|
||||
self.assertFalse(perm_set.get('z', False))
|
||||
self.assertTrue(perm_set.get('z', True))
|
||||
|
||||
|
||||
class ModeratorPermissionSetTest(unittest.TestCase):
|
||||
def test_loads(self):
|
||||
self.assertTrue(ModeratorPermissionSet.loads(None).is_superuser())
|
||||
self.assertFalse(ModeratorPermissionSet.loads('').is_superuser())
|
||||
|
||||
|
||||
class SRMemberTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
|
||||
Reference in New Issue
Block a user