From fdce26f7a8ff38daa25323733bab8efe5250ce9c Mon Sep 17 00:00:00 2001 From: mdipierro Date: Wed, 1 Aug 2012 01:02:45 -0500 Subject: [PATCH] better permission handling for auth.wiki, not yet for wiki_media --- VERSION | 2 +- gluon/tools.py | 99 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 65 insertions(+), 36 deletions(-) diff --git a/VERSION b/VERSION index 94718922..5eda5859 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.00.0 (2012-07-31 22:03:43) dev +Version 2.00.0 (2012-08-01 01:02:41) dev diff --git a/gluon/tools.py b/gluon/tools.py index 36ac46ad..360fba00 100644 --- a/gluon/tools.py +++ b/gluon/tools.py @@ -3079,9 +3079,10 @@ class Auth(object): new_record[key] = value id = archive_table.insert(**new_record) return id - def wiki(self,slug=None,env=None): + def wiki(self,slug=None,env=None,manage_permissions=False,force_prefix=''): if not hasattr(self,'_wiki'): - self._wiki = Wiki(self,env=env) + self._wiki = Wiki(self,manage_permissions=manage_permissions, + force_prefix=force_prefix,env=env) else: self._wiki.env.update(env or {}) return self._wiki.read(slug)['content'] if slug else self._wiki() @@ -4393,15 +4394,18 @@ class Wiki(object): rows_page = 25 regex_redirect = re.compile('redirect\s+(\w+\://\S+)\s*') def __init__(self,auth,env=None,automenu=True,render='markmin', - manage_permissions=False,force_prefix=None): + manage_permissions=False,force_prefix=''): self.env = env or {} if render == 'markmin': render = lambda t,env=self.env: \ MARKMIN(t.body,url=True,environment=env).xml() self.auth = auth self.automenu = automenu + if self.auth.user: + self.force_prefix = force_prefix % self.auth.user + else: + self.force_prefix = force_prefix perms = self.manage_permissions = manage_permissions - self.force_prefix = force_prefix or '' db = auth.db db.define_table( 'wiki_page', @@ -4441,7 +4445,33 @@ class Wiki(object): if tag: db.wiki_tag.insert(name=tag,wiki_page=page.id) db.wiki_page._after_insert.append(update_tags_insert) db.wiki_page._after_update.append(update_tags_update) - + # WIKI ACCESS POLICY + def not_authorized(self,page=None): + raise HTTH(401) + def can_read(self,page): + if 'everybody' in page.can_read or not self.manage_permissions: + return True + elif self.auth.user: + groups = self.auth.user_groups.values() + if ('wiki_editor' in groups or + set(groups).intersection(set(page.can_read+page.can_edit)) or + page.created_by==self.auth.user.id): return True + return False + def can_edit(self,page=None): + if not self.auth.user: redirect(self.auth.settings.login_url) + groups = self.auth.user_groups.values() + return ('wiki_editor' in groups or + (page is None and 'wiki_author' in groups) or + not page is None and ( + set(groups).intersection(set(page.can_edit)) or + page.created_by==self.auth.user.id)) + def can_manage(self): + if not self.auth.user: redirect(self.auth.settings.login_url) + groups = self.auth.user_groups.values() + return 'wiki_editor' in groups + def can_search(self): + return True + ### END POLICY def __call__(self): request = current.request if self.automenu: @@ -4468,29 +4498,19 @@ class Wiki(object): else: return self.read(request.args(0) or 'index') - def first_paragraph(self,mm): - if self.manage_permissions: - return '' - mm = mm.replace('\r','') - ps = [p for p in mm.split('\n\n') \ - if not p.startswith('#') and p.strip()] - if ps: return ps[0] + def first_paragraph(self,page): + if not self.can_read(page): + mm = page.body.replace('\r','') + ps = [p for p in mm.split('\n\n') \ + if not p.startswith('#') and p.strip()] + if ps: return ps[0] return '' - def check_permission(self,page,field='can_read'): - if not self.manage_permissions: - return True - groups = set(page.get(field,None) or []) - if Wiki.everybody in groups or \ - self.auth.user and groups.intersect(self.auth.user_groups.values()): - return True - return False def read(self,slug): if slug in '_cloud': return self.cloud() page = self.auth.db.wiki_page(slug=slug) - #if page and not self.check_permission(page,'can_read'): - # raise HTTP(401) + if not self.can_read(page): return self.not_authorized(page) if current.request.extension == 'html': if not page: url = URL(args=('_edit',slug)) @@ -4520,30 +4540,31 @@ class Wiki(object): raise HTTP(401, "Not Authorized") return True def edit(self,slug): - self.check_editor() auth = self.auth db = auth.db page = db.wiki_page(slug=slug) + if not self.can_edit(page): return self.not_authorized(page) title_guess = ' '.join(c.capitalize() for c in slug.split('-')) if not page: if not slug.startswith(self.force_prefix): - session.flash='slug bust have "%s" prefix' % self.force_prefix - redirect(URL(args=('_edit',force_prefix+slug))) - db.wiki_page.can_read = [Wiki.everybody] - db.wiki_page.can_edit = [auth.user_group_role()] + current.session.flash='slug must have "%s" prefix' \ + % self.force_prefix + redirect(URL(args=('_edit',self.force_prefix+slug))) + db.wiki_page.can_read.default = [Wiki.everybody] + db.wiki_page.can_edit.default = [auth.user_group_role()] db.wiki_page.title.default = title_guess db.wiki_page.slug.default = slug db.wiki_page.menu.default = slug db.wiki_page.body.default = '## %s\n\npage content' % title_guess - elif not self.check_permission(page,'can_edit'): - raise HTTP(401) form = SQLFORM(db.wiki_page,page,deletable=True,showid=False).process() if form.accepted: current.session.flash = 'page created' redirect(URL(args=slug)) + elif form.deleted: + redirect(URL()) return dict(content=form) def pages(self): - self.check_editor() + if not self.can_manage(): return self.not_authorized() self.auth.db.wiki_page.title.represent = lambda title,row: \ A(title,_href=URL(args=row.slug)) content=SQLFORM.smartgrid( @@ -4561,6 +4582,9 @@ class Wiki(object): request, db = current.request, self.auth.db media = db.wiki_media(id) if media: + if self.manage_permissions: + page = db.wiki_page(media.page) + if not self.can_read(page): return self.not_authorized(page) request.args = [media.file] return current.response.download(request,db) else: @@ -4573,9 +4597,10 @@ class Wiki(object): orderby = db.wiki_page.menu) menu = [] tree = {'.':menu} + regex = re.compile('\d\:') for row in rows: if row.menu: - key = './'+row.menu + key = './'+regex.sub('',row.menu) base = key.rsplit('/',1)[0] subtree = tree[key] = [] if base in tree: @@ -4583,23 +4608,27 @@ class Wiki(object): request.args(0)==row.slug, URL(controller,function,args=row.slug), subtree)) - if self.check_editor(act=False): + #if self.auth.user: + if True: submenu = [] + menu.append((current.T('[Wiki]'),None,None,submenu)) if URL() == URL(controller,function) and \ not str(request.args(0)).startswith('_'): submenu.append((current.T('Edit'),None, URL(controller,function, args=('_edit',request.args(0) or 'index')))) + # if self.can_manage(): submenu.append((current.T('Manage Pages'),None, - URL(controller,function,args=('_pages')))) + URL(controller,function,args=('_pages')))) + # if self.can_search(): submenu.append((current.T('Search Pages'),None, URL(controller,function,args=('_search')))) submenu.append((current.T('Tag Cloud'),None, URL(controller,function,args=('_cloud')))) - menu.append((current.T('[Wiki]'),None,None,submenu)) return menu def search(self,tags=None,query=None,cloud=True,preview=True, limitby=(0,100),orderby=None): + if not self.can_search(): return self.not_authorized() request = current.request content = CAT() if tags is None and query is None: @@ -4630,7 +4659,7 @@ class Wiki(object): def link(t): return A(t,_href=URL(args='_search',vars=dict(tags=t))) items = [DIV(H3(A(p.title,_href=URL(args=p.slug))), - MARKMIN(self.first_paragraph(p.body)) \ + MARKMIN(self.first_paragraph(p)) \ if preview else '', SPAN(*[link(t.strip()) for t in \ p.tags or [] if t.strip()]),