Opened 19 years ago
Closed 19 years ago
#221 closed defect (fixed)
Patch for 0.9.3
Reported by: | Owned by: | puffy | |
---|---|---|---|
Priority: | normal | Component: | WikiRbacPatch |
Severity: | major | Keywords: | |
Cc: | Trac Release: | 0.9 |
Description
The existing patch doesn't apply cleanly on 0.9.3 or 0.9.4. Here's a diff that works for us. It was written for 0.9.3, but it seems to work on 0.9.4 just as well.
The biggest change from 0.9.2 is that 0.9.3 no longer uses the escape()
routine, opting instead for one called Markup()
.
The only other issue I encountered is that in the very last section of the original (0.9.2) patch of web_ui.py
, self.authz.has_authorization()
was passed only three parameters. As far as I can tell, it needs four -- so the second one is now req.authname
. I'm most definitely not a python hacker, so you might want to double check that for me.
Anyway, the patch seems to work here, but I don't have a set of regression tests, so my QA is mostly along the lines of, "That page works... And that one... And that one... OK, everything looks right."
Thanks for all your work coding this up. We needed just this sort of access control on our intranet wiki.
--Paul
--- trac/wiki/web_ui.py.orig 2006-02-13 15:32:40.000000000 -0800 +++ trac/wiki/web_ui.py 2006-02-13 15:32:09.000000000 -0800 @@ -32,13 +32,15 @@ from trac.web import IRequestHandler from trac.wiki.model import WikiPage from trac.wiki.formatter import wiki_to_html, wiki_to_oneliner - +from trac.wiki.rbac import WikiAuthorizer class WikiModule(Component): implements(INavigationContributor, IPermissionRequestor, IRequestHandler, ITimelineEventProvider, ISearchSource) + authz = property(fget=lambda self: self._get_authz()) + # INavigationContributor methods def get_active_navigation_item(self, req): @@ -74,6 +76,7 @@ pagename = req.args.get('page', 'WikiStart') version = req.args.get('version') + self.authz.assert_authorization(req.perm, req.authname, pagename, 'WIKI_VIEW') db = self.env.get_db_cnx() page = WikiPage(self.env, pagename, version, db) @@ -118,6 +121,13 @@ req.hdf['wiki.action'] = action req.hdf['wiki.page_name'] = page.name req.hdf['wiki.current_href'] = self.env.href.wiki(page.name) + for permission in self.get_permission_actions(): + if isinstance(permission, (list, tuple)): + permission = permission[0] + self.log.debug("PERMISSION: %s", permission) + req.hdf['trac.acl.' + permission] =\ + self.authz.has_authorization(req.perm, req.authname, page.name, permission) + return 'wiki.cs', None # ITimelineEventProvider methods @@ -135,24 +145,29 @@ "FROM wiki WHERE time>=%s AND time<=%s", (start, stop)) for t,name,comment,author in cursor: - title = Markup('<em>%s</em> edited by %s', name, author) - if format == 'rss': - href = self.env.abs_href.wiki(name) - comment = wiki_to_html(comment or '--', self.env, req, db, - absurls=True) - else: - href = self.env.href.wiki(name) - comment = wiki_to_oneliner(comment, self.env, db, - shorten=True) - yield 'wiki', href, title, t, author, comment + if self.authz.has_authorization(req.perm, req.authname, name, 'WIKI_VIEW'): + title = Markup('<em>%s</em> edited by %s', name, author) + if format == 'rss': + href = self.env.abs_href.wiki(name) + comment = wiki_to_html(comment or '--', self.env, req, db, + absurls=True) + else: + href = self.env.href.wiki(name) + comment = wiki_to_oneliner(comment, self.env, db, + shorten=True) + yield 'wiki', href, title, t, author, comment # Internal methods + def _get_authz(self): + return WikiAuthorizer(self.env) + def _do_delete(self, req, db, page): if page.readonly: req.perm.assert_permission('WIKI_ADMIN') else: req.perm.assert_permission('WIKI_DELETE') + self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_DELETE') if req.args.has_key('cancel'): req.redirect(self.env.href.wiki(page.name)) @@ -174,8 +189,10 @@ req.perm.assert_permission('WIKI_ADMIN') elif not page.exists: req.perm.assert_permission('WIKI_CREATE') + self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_CREATE') else: req.perm.assert_permission('WIKI_MODIFY') + self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_MODIFY') page.text = req.args.get('text') if req.perm.has_permission('WIKI_ADMIN'): @@ -192,6 +209,7 @@ req.perm.assert_permission('WIKI_ADMIN') else: req.perm.assert_permission('WIKI_DELETE') + self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_DELETE') version = None if req.args.has_key('delete_version'): @@ -210,6 +228,7 @@ def _render_diff(self, req, db, page): req.perm.assert_permission('WIKI_VIEW') + self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_VIEW') if not page.exists: raise TracError, "Version %s of page %s does not exist" \ @@ -277,6 +296,7 @@ def _render_editor(self, req, db, page, preview=False): req.perm.assert_permission('WIKI_MODIFY') + self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_MODIFY') if req.args.has_key('text'): page.text = req.args.get('text') @@ -320,6 +340,7 @@ page. """ req.perm.assert_permission('WIKI_VIEW') + self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_VIEW') if not page.exists: raise TracError, "Page %s does not exist" % page.name @@ -344,6 +365,7 @@ def _render_view(self, req, db, page): req.perm.assert_permission('WIKI_VIEW') + self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_VIEW') if page.name == 'WikiStart': req.hdf['title'] = '' @@ -365,7 +387,8 @@ history_href = self.env.href.wiki(page.name, action='history') req.hdf['wiki.history_href'] = history_href else: - if not req.perm.has_permission('WIKI_CREATE'): + if not req.perm.has_permission('WIKI_CREATE') and\ + self.authz.has_authorization(req.perm, req.authname, page.name, 'WIKI_CREATE'): raise TracError('Page %s not found' % page.name) req.hdf['wiki.page_html'] = Markup('<p>Describe "%s" here</p>', page.name) @@ -375,7 +398,8 @@ for attachment in Attachment.select(self.env, 'wiki', page.name, db): attachments.append(attachment_to_hdf(self.env, db, req, attachment)) req.hdf['wiki.attachments'] = attachments - if req.perm.has_permission('WIKI_MODIFY'): + if req.perm.has_permission('WIKI_MODIFY') and\ + self.authz.has_authorization(req.perm, req.authname, page.name, 'WIKI_MODIFY'): attach_href = self.env.href.attachment('wiki', page.name) req.hdf['wiki.attach_href'] = attach_href @@ -399,7 +423,8 @@ "AND " + sql_query, args) for name, date, author, text in cursor: - yield (self.env.href.wiki(name), - '%s: %s' % (name, shorten_line(text)), - date, author, - shorten_result(text, query.split())) + if self.authz.has_authorization(req.perm, req.authname, name, 'WIKI_VIEW'): + yield (self.env.href.wiki(name), + '%s: %s' % (name, shorten_line(text)), + date, author, + shorten_result(text, query.split())) --- trac/wiki/rbac.py.orig 2006-02-13 15:32:45.000000000 -0800 +++ trac/wiki/rbac.py 2006-02-13 15:29:34.000000000 -0800 @@ -0,0 +1,82 @@ +from trac.core import * +from trac.perm import PermissionError +from trac.versioncontrol.svn_authz import RealSubversionAuthorizer +from trac.versioncontrol import Authorizer, PermissionDenied + +def SubversionAuthorizer(env, authname): + authz_file = env.config.get('wiki', 'authz_file') or\ + env.config.get('trac', 'authz_file') + if not authz_file: + return Authorizer() + + module_name = env.config.get('wiki', 'authz_svn_module_name') + db = env.get_db_cnx() + return ExtendedSubversionAuthorizer(db, authname, module_name, authz_file) + +class IWikiAuthzProvider(Interface): + """Interface for classes that provide some method of checking a + user's access to a portion of the wiki.""" + + def has_authorization(user, path, operation): + """Verify that the given username is authorized to perform + the given operation on the given path. + returns boolean.""" + +class WikiAuthorizer(Component): + providers = ExtensionPoint(IWikiAuthzProvider) + + def _accumulate(self, current, result): + authmode = self.env.config.get('wiki', 'authorization_mode') + + if authmode == 'require_all': + return current & result + elif authmode == 'require_one': + return current | result + else: + return True + + def has_authorization(self, perm, user, path, operation): + if not perm.has_permission('WIKI_VIEW'): + return False + + authzed = True + for provider in self.providers: + authzed = self._accumulate(authzed, provider.has_authorization(user, path, operation)) + return authzed or perm.has_permission('TRAC_ADMIN') + + def assert_authorization(self, perm, user, path, operation): + if not self.has_authorization(perm, user, path, operation): + raise PermissionDenied,\ + '%s authorization on %s is necessary to perform this operation.' % (operation, 'wiki:' + path) + + +class WikiSubversionAuthorizer(Component): + implements(IWikiAuthzProvider) + + def has_authorization(self, user, path, operation): + path = '/' + path + authorizer = SubversionAuthorizer(self.env, user) + self.log.debug("Authorize %s check for: %s on %s:%s", operation, user, authorizer.module_name, path) + return authorizer.has_authorization(path, operation) + +class ExtendedSubversionAuthorizer(RealSubversionAuthorizer): + """Provides extended semantics for the subversion-based authorization""" + + opmap = {'WIKI_CREATE':'c', 'WIKI_DELETE':'d', 'WIKI_MODIFY':'w', 'WIKI_VIEW':'r', 'WIKI_ADMIN':'a'} + + def has_authorization(self, path, op): + self._set_opcheck('WIKI_ADMIN') + if self.has_permission(path): + return True + else: + self._set_opcheck(op) + return self.has_permission(path) + + def _set_opcheck(self, op): + op = self.opmap[op] + self._get_permission = lambda section, subject: self.__get_permission(section, subject, op) + + def __get_permission(self, section, subject, op): + if self.conf_authz.has_option(section, subject): + return op in self.conf_authz.get(section, subject) + return None
Attachments (1)
Change History (6)
comment:1 Changed 19 years ago by
Trac Release: | → 0.9 |
---|---|
Type: | enhancement → defect |
comment:2 Changed 19 years ago by
The patch added a couple minutes ago by "anonymous" is mine. I forgot to enter my address before attaching the file.
Paul
comment:3 Changed 19 years ago by
Resolution: | → duplicate |
---|---|
Status: | new → closed |
I have just noticed there is no need for newer patches, as this functionality is already implemented: http://projects.edgewall.com/trac/wiki/FineGrainedPermissions
I believe puffy should mention that on WikiRbacPatch?'s-site.
Anyway, thanks for th updated patch!
comment:4 Changed 19 years ago by
Resolution: | duplicate |
---|---|
Status: | closed → reopened |
Trac's fine-grained permissions system has nothing to do with the wiki, it is for the repository browser only.
Hi Paul,
please attach your patch to this ticket. The inline one has its indentation broken.
Thanks,
Mark