Ticket #898: rbac.patch
| File rbac.patch, 10.6 kB (added by mnencia, 2 years ago) |
|---|
-
trac/wiki/rbac.py
old new 1 from trac.core import * 2 from trac.perm import PermissionError 3 from trac.versioncontrol.svn_authz import RealSubversionAuthorizer 4 from trac.versioncontrol import Authorizer, PermissionDenied 5 6 def SubversionAuthorizer(env, authname): 7 authz_file = env.config.get('wiki', 'authz_file') or\ 8 env.config.get('trac', 'authz_file') 9 if not authz_file: 10 return Authorizer() 11 12 module_name = env.config.get('wiki', 'authz_svn_module_name') 13 db = env.get_db_cnx() 14 return ExtendedSubversionAuthorizer(db, authname, module_name, authz_file) 15 16 class IWikiAuthzProvider(Interface): 17 """Interface for classes that provide some method of checking a 18 user's access to a portion of the wiki.""" 19 20 def has_authorization(user, path, operation): 21 """Verify that the given username is authorized to perform 22 the given operation on the given path. 23 returns boolean.""" 24 25 class WikiAuthorizer(Component): 26 providers = ExtensionPoint(IWikiAuthzProvider) 27 28 def _accumulate(self, current, result): 29 authmode = self.env.config.get('wiki', 'authorization_mode') 30 31 if authmode == 'require_all': 32 return current & result 33 elif authmode == 'require_one': 34 return current | result 35 else: 36 return True 37 38 def has_authorization(self, perm, user, path, operation): 39 if not perm.has_permission('WIKI_VIEW'): 40 return False 41 42 authzed = True 43 for provider in self.providers: 44 authzed = self._accumulate(authzed, provider.has_authorization(user, path, operation)) 45 return authzed or perm.has_permission('TRAC_ADMIN') 46 47 def assert_authorization(self, perm, user, path, operation): 48 if not self.has_authorization(perm, user, path, operation): 49 raise PermissionDenied,\ 50 '%s authorization on %s is necessary to perform this operation.' % (operation, 'wiki:' + path) 51 52 53 class WikiSubversionAuthorizer(Component): 54 implements(IWikiAuthzProvider) 55 56 def has_authorization(self, user, path, operation): 57 path = '/' + path 58 authorizer = SubversionAuthorizer(self.env, user) 59 self.log.debug("Authorize %s check for: %s on %s:%s", operation, user, authorizer.module_name, path) 60 return authorizer.has_authorization(path, operation) 61 62 class ExtendedSubversionAuthorizer(RealSubversionAuthorizer): 63 """Provides extended semantics for the subversion-based authorization""" 64 65 opmap = {'WIKI_CREATE':'c', 'WIKI_DELETE':'d', 'WIKI_MODIFY':'w', 'WIKI_VIEW':'r', 'WIKI_ADMIN':'a'} 66 67 def has_authorization(self, path, op): 68 self._set_opcheck('WIKI_ADMIN') 69 if self.has_permission(path): 70 return True 71 else: 72 self._set_opcheck(op) 73 return self.has_permission(path) 74 75 def _set_opcheck(self, op): 76 op = self.opmap[op] 77 self._get_permission = lambda section, subject: self.__get_permission(section, subject, op) 78 79 def __get_permission(self, section, subject, op): 80 if self.conf_authz.has_option(section, subject): 81 return op in self.conf_authz.get(section, subject) 82 return None -
trac/wiki/web_ui.py
old new 36 36 from trac.wiki.model import WikiPage 37 37 from trac.wiki.formatter import wiki_to_html, wiki_to_oneliner 38 38 from trac.mimeview.api import Mimeview, IContentConverter 39 from trac.wiki.rbac import WikiAuthorizer 39 40 40 41 41 42 class InvalidWikiPage(TracError): … … 47 48 implements(INavigationContributor, IPermissionRequestor, IRequestHandler, 48 49 ITimelineEventProvider, ISearchSource, IContentConverter) 49 50 51 authz = property(fget=lambda self: self._get_authz()) 52 50 53 page_manipulators = ExtensionPoint(IWikiPageManipulator) 51 54 52 55 # IContentConverter methods … … 93 96 if pagename.endswith('/'): 94 97 req.redirect(req.href.wiki(pagename.strip('/'))) 95 98 99 self.authz.assert_authorization(req.perm, req.authname, pagename, 'WIKI_VIEW') 96 100 db = self.env.get_db_cnx() 97 101 page = WikiPage(self.env, pagename, version, db) 98 102 … … 135 139 136 140 req.hdf['wiki.action'] = action 137 141 req.hdf['wiki.current_href'] = req.href.wiki(page.name) 142 for permission in self.get_permission_actions(): 143 if isinstance(permission, (list, tuple)): 144 permission = permission[0] 145 self.log.debug("PERMISSION: %s", permission) 146 req.hdf['trac.acl.' + permission] =\ 147 self.authz.has_authorization(req.perm, req.authname, page.name, permission) 148 138 149 return 'wiki.cs', None 139 150 140 151 # ITimelineEventProvider methods … … 154 165 "FROM wiki WHERE time>=%s AND time<=%s", 155 166 (start, stop)) 156 167 for t,name,comment,author,version in cursor: 157 title = Markup('<em>%s</em> edited by %s', 158 wiki.format_page_name(name), author) 159 diff_link = html.A('diff', href=href.wiki(name, action='diff', 160 version=version)) 161 if format == 'rss': 162 comment = wiki_to_html(comment or '--', self.env, req, db, 163 absurls=True) 164 else: 165 comment = wiki_to_oneliner(comment, self.env, db, 166 shorten=True) 167 if version > 1: 168 comment = Markup('%s (%s)', comment, diff_link) 169 yield 'wiki', href.wiki(name), title, t, author, comment 168 if self.authz.has_authorization(req.perm, req.authname, name, 'WIKI_VIEW'): 169 title = Markup('<em>%s</em> edited by %s', 170 wiki.format_page_name(name), author) 171 diff_link = html.A('diff', href=href.wiki(name, action='diff', 172 version=version)) 173 if format == 'rss': 174 comment = wiki_to_html(comment or '--', self.env, req, db, 175 absurls=True) 176 else: 177 comment = wiki_to_oneliner(comment, self.env, db, 178 shorten=True) 179 if version > 1: 180 comment = Markup('%s (%s)', comment, diff_link) 181 yield 'wiki', href.wiki(name), title, t, author, comment 170 182 171 183 # Attachments 172 184 def display(id): … … 179 191 180 192 # Internal methods 181 193 194 def _get_authz(self): 195 return WikiAuthorizer(self.env) 196 182 197 def _set_title(self, req, page, action): 183 198 title = name = WikiSystem(self.env).format_page_name(page.name) 184 199 if action: … … 192 207 req.perm.assert_permission('WIKI_ADMIN') 193 208 else: 194 209 req.perm.assert_permission('WIKI_DELETE') 210 self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_DELETE') 195 211 196 212 if req.args.has_key('cancel'): 197 213 req.redirect(req.href.wiki(page.name)) … … 218 234 req.perm.assert_permission('WIKI_ADMIN') 219 235 elif not page.exists: 220 236 req.perm.assert_permission('WIKI_CREATE') 237 self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_CREATE') 221 238 else: 222 239 req.perm.assert_permission('WIKI_MODIFY') 240 self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_MODIFY') 223 241 224 242 page.text = req.args.get('text') 225 243 if req.perm.has_permission('WIKI_ADMIN'): … … 245 263 req.perm.assert_permission('WIKI_ADMIN') 246 264 else: 247 265 req.perm.assert_permission('WIKI_DELETE') 266 self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_DELETE') 248 267 249 268 version = None 250 269 if req.args.has_key('delete_version'): … … 265 284 266 285 def _render_diff(self, req, db, page): 267 286 req.perm.assert_permission('WIKI_VIEW') 287 self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_VIEW') 268 288 269 289 if not page.exists: 270 290 raise TracError("Version %s of page %s does not exist" % … … 350 370 351 371 def _render_editor(self, req, db, page, preview=False): 352 372 req.perm.assert_permission('WIKI_MODIFY') 373 self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_MODIFY') 353 374 354 375 if req.args.has_key('text'): 355 376 page.text = req.args.get('text') … … 396 417 page. 397 418 """ 398 419 req.perm.assert_permission('WIKI_VIEW') 420 self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_VIEW') 399 421 400 422 if not page.exists: 401 423 raise TracError, "Page %s does not exist" % page.name … … 419 441 420 442 def _render_view(self, req, db, page): 421 443 req.perm.assert_permission('WIKI_VIEW') 444 self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_VIEW') 422 445 423 446 page_name = self._set_title(req, page, '') 424 447 if page.name == 'WikiStart': … … 457 480 'age': pretty_timedelta(page.time) 458 481 } 459 482 else: 460 if not req.perm.has_permission('WIKI_CREATE'): 483 if not req.perm.has_permission('WIKI_CREATE') and\ 484 self.authz.has_authorization(req.perm, req.authname, page.name, 'WIKI_CREATE'): 461 485 raise HTTPNotFound('Page %s not found', page.name) 462 486 req.hdf['wiki.page_html'] = html.P('Describe "%s" here' % page_name) 463 487 464 488 # Show attachments 465 489 req.hdf['wiki.attachments'] = attachments_to_hdf(self.env, req, db, 466 490 'wiki', page.name) 467 if req.perm.has_permission('WIKI_MODIFY'): 491 if req.perm.has_permission('WIKI_MODIFY') and\ 492 self.authz.has_authorization(req.perm, req.authname, page.name, 'WIKI_MODIFY'): 468 493 attach_href = req.href.attachment('wiki', page.name) 469 494 req.hdf['wiki.attach_href'] = attach_href 470 495 … … 488 513 "AND " + sql_query, args) 489 514 490 515 for name, date, author, text in cursor: 491 yield (req.href.wiki(name), '%s: %s' % (name, shorten_line(text)), 492 date, author, shorten_result(text, terms)) 516 if self.authz.has_authorization(req.perm, req.authname, name, 'WIKI_VIEW'): 517 yield (req.href.wiki(name), '%s: %s' % (name, shorten_line(text)), 518 date, author, shorten_result(text, terms))
