Commit 9c31deee authored by Laurent Bachelier's avatar Laurent Bachelier

Add the "in" permission

This decouples the "list" permission (listing a directory) from the "see
in" permission (seeing a file in a directory listing).
parent 3298da51
......@@ -31,15 +31,17 @@ __all__ = ['File']
class File(IObject):
PERM_READ = 0x001
PERM_LIST = 0x002
PERM_READ = 0x001
PERM_LIST = 0x002
PERM_WRITE = 0x004
PERM_IN = 0x008
PERM_ALL = 0xfff
PERMS = (('r', PERM_READ),
PERMS = (('i', PERM_IN),
('r', PERM_READ),
('l', PERM_LIST),
('w', PERM_WRITE)
('w', PERM_WRITE),
)
@staticmethod
......
......@@ -195,6 +195,7 @@ class ListAction(ViewAction):
class CoreCleaner(ICleaner):
def fsck(self):
self.v1()
self.invalid_paths = []
for f in self.storage.iter_files():
if f.path is None or f._get_confname() != File._get_confname(f):
......@@ -206,6 +207,29 @@ class CoreCleaner(ICleaner):
f.save()
print "%s: fixed empty view." % f._get_confname()
def v1(self):
"""
Migration for the introduction of the +i permission
"""
config = self.storage.get_config()
if config.data['storage'].get('version', 0) > 0:
return
for f in self.storage.iter_files():
for key in f.perms.keys():
perms = f.perms[key]
# directories with the LIST perm will also get the IN perm
# so files inherit it
if perms & File.PERM_LIST:
perms = perms | File.PERM_IN
# remove LIST perm for files (does not make sense)
if f.isfile() and perms & File.PERM_LIST:
perms = perms & File.PERM_LIST
f.perms[key] = perms
f.save()
print 'Migrated storage to v1'
config.data['storage']['version'] = 1
config.save()
def gc(self):
for f in self.invalid_paths:
self.remove(f)
......
......@@ -148,7 +148,7 @@ class Context(object):
def iter_files(self):
if self.object_type == "directory":
for f in self.file.iter_children():
if self.user.has_perms(f, f.PERM_LIST):
if self.user.has_perms(f, f.PERM_IN):
yield f
def login(self, user, set_cookie=True):
......@@ -359,7 +359,10 @@ class Dispatcher(object):
# check perms
f = ctx.file
if not ctx.user.has_perms(f, f.PERM_READ):
if ctx.object_type == 'directory':
if not ctx.user.has_perms(f, f.PERM_LIST):
raise HTTPForbidden()
elif not ctx.user.has_perms(f, f.PERM_READ):
raise HTTPForbidden()
# normalize paths
......
......@@ -96,14 +96,18 @@ class Storage(object):
def create(cls, path):
storage = cls(os.path.join(path, cls.DIRNAME))
config = storage.get_config()
config.data['storage']['version'] = 1
config.save()
# Default perms on /.ass2m
f = File(storage, '/.ass2m')
f = storage.get_file('/.ass2m')
f.perms = {'all': 0}
f.save()
# Default perms on /
f = File(storage, '')
f.perms = {'all': File.PERM_READ | File.PERM_LIST}
f = storage.get_file('')
f.perms = {'all': File.PERM_READ | File.PERM_LIST | File.PERM_IN}
f.save()
return storage
......
......@@ -49,8 +49,8 @@ class BaseCLITest(TestCase):
self.beginCapture()
assert self.app.main(['ass2m_test', 'tree']) in (0, None)
output = self.endCapture()
assert re.match(re.escape(r'/') + r'\s+' + re.escape(r'all(rl-)'), output, re.S)
assert re.match(".+" + re.escape(r'/.ass2m/') + r'\s+' + re.escape(r'all(---)'), output, re.S)
assert re.match(re.escape(r'/') + r'\s+' + re.escape(r'all(irl-)'), output, re.S)
assert re.match(".+" + re.escape(r'/.ass2m/') + r'\s+' + re.escape(r'all(----)'), output, re.S)
def test_findRoot(self):
self.beginCapture()
......
......@@ -86,7 +86,7 @@ class ConfigCLITest(TestCase):
self.beginCapture()
assert self.app.main(['ass2m_test', 'config', '-g', 'list']) in (0, None)
output = self.endCapture()
assert len(output) == 0
assert 'storage.version' in output
self.beginCapture()
assert self.app.main(['ass2m_test', 'config', '-f', self.root, 'list']) in (0, None)
......@@ -115,7 +115,7 @@ class ConfigCLITest(TestCase):
self.beginCapture()
assert self.app.main(['ass2m_test', 'config', '-g', 'list']) in (0, None)
output = self.endCapture()
assert len(output) == 0
assert 'lol.cat' not in output
self.beginCapture(True)
assert self.app.main(['ass2m_test', 'config', '-g', 'get', 'lol.cat']) == 2
......@@ -134,4 +134,4 @@ class ConfigCLITest(TestCase):
self.beginCapture()
assert self.app.main(['ass2m_test', 'config', '-g', 'list']) in (0, None)
output = self.endCapture()
assert len(output.strip().split('\n')) == 1
assert 'lol.cat=42' in output
......@@ -49,7 +49,7 @@ Attendees:
f = storage.get_file('/event1.txt')
f.mimetype = 'text/event'
f.perms['u.penguin'] = f.PERM_READ | f.PERM_WRITE
f.perms['u.penguin'] = f.PERM_READ | f.PERM_WRITE | f.PERM_IN
f.save()
def tearDown(self):
......
......@@ -138,13 +138,13 @@ class StorageTest(TestCase):
def test_filePreAndPost(self):
f = File(self.storage, '/penguin')
f.perms['all'] = File.PERM_READ | File.PERM_LIST
f.perms['all'] = File.PERM_READ | File.PERM_LIST | File.PERM_IN
f.view = 'html'
f.save()
f = File(self.storage, '/penguin')
f.read()
assert f.perms['all'] == File.PERM_READ | File.PERM_LIST
assert f.perms['all'] == File.PERM_READ | File.PERM_LIST | File.PERM_IN
assert f.view == 'html'
f.remove()
assert len(f.perms) == 0
......
......@@ -61,7 +61,7 @@ class WebPermsTest(TestCase):
assert 'HELLO' == res.body
# files are hidden, but it is still possible do download them if we know the URL
self._set_perms('/penguins', all=File.PERM_READ)
self._set_perms('/penguins', all=File.PERM_READ | File.PERM_LIST)
res = self.app.get('/', status=200)
assert 'penguins' not in res.body
res = self.app.get('/penguins/', status=200)
......@@ -70,7 +70,7 @@ class WebPermsTest(TestCase):
assert 'HELLO' == res.body
# force the display of one file in the directory
self._set_perms('/penguins/gentoo', all=File.PERM_READ | File.PERM_LIST)
self._set_perms('/penguins/gentoo', all=File.PERM_READ | File.PERM_IN)
res = self.app.get('/penguins/', status=200)
assert 'gentoo' in res.body
......@@ -93,40 +93,40 @@ class WebPermsTest(TestCase):
res = form.submit(status=302)
# check user perms
self._set_perms('/penguins', all=0, u_penguin=File.PERM_READ | File.PERM_LIST)
self._set_perms('/penguins', all=0, u_penguin=File.PERM_READ | File.PERM_LIST | File.PERM_IN)
res = self.app.get('/', status=200)
assert 'penguins' in res.body
res = self.app.get('/penguins/', status=200)
assert 'gentoo' in res.body
self._set_perms('/penguins', all=0, u_penguin=File.PERM_LIST)
self._set_perms('/penguins', all=0, u_penguin=File.PERM_READ | File.PERM_IN)
res = self.app.get('/', status=200)
assert 'penguins' in res.body
self.app.get('/penguins/', status=403)
# check group perms
self._set_perms('/penguins', all=0, g_admin=File.PERM_READ | File.PERM_LIST)
self._set_perms('/penguins', all=0, g_admin=File.PERM_READ | File.PERM_LIST | File.PERM_IN)
res = self.app.get('/', status=200)
assert 'penguins' in res.body
res = self.app.get('/penguins/', status=200)
assert 'gentoo' in res.body
self._set_perms('/penguins', all=0, g_admin=File.PERM_LIST)
self._set_perms('/penguins', all=0, g_admin=File.PERM_READ | File.PERM_IN)
res = self.app.get('/', status=200)
assert 'penguins' in res.body
self.app.get('/penguins/', status=403)
# check recursive perms
self._set_perms('/', all=0, g_admin=File.PERM_LIST | File.PERM_READ)
self._set_perms('/', all=0, g_admin=File.PERM_LIST | File.PERM_READ | File.PERM_IN)
self._set_perms('/penguins')
res = self.app.get('/penguins/', status=200)
assert 'gentoo' in res.body
self._set_perms('/', all=File.PERM_LIST | File.PERM_READ, g_admin=0)
self._set_perms('/', all=File.PERM_LIST | File.PERM_READ | File.PERM_IN, g_admin=0)
self.app.get('/penguins/', status=403)
self._set_perms('/', all=File.PERM_LIST | File.PERM_READ, u_penguins=0)
self._set_perms('/penguins', g_admin=File.PERM_LIST | File.PERM_READ)
self._set_perms('/', all=File.PERM_LIST | File.PERM_READ | File.PERM_IN, u_penguins=0)
self._set_perms('/penguins', g_admin=File.PERM_LIST | File.PERM_READ | File.PERM_IN)
self.app.get('/penguins/', status=200)
def _set_perms(self, path, **perms):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment