Ticket #898: rbac.2.patch
| File rbac.2.patch, 10.7 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 … … 128 132 self._render_history(req, db, page) 129 133 else: 130 134 req.perm.assert_permission('WIKI_VIEW') 135 self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_VIEW') 131 136 format = req.args.get('format') 132 137 if format: 133 138 Mimeview(self.env).send_converted(req, 'text/x-trac-wiki', … … 136 141 137 142 req.hdf['wiki.action'] = action 138 143 req.hdf['wiki.current_href'] = req.href.wiki(page.name) 144 for permission in self.get_permission_actions(): 145 if isinstance(permission, (list, tuple)): 146 permission = permission[0] 147 self.log.debug("PERMISSION: %s", permission) 148 req.hdf['trac.acl.' + permission] =\ 149 self.authz.has_authorization(req.perm, req.authname, page.name, permission) 150 139 151 return 'wiki.cs', None 140 152 141 153 # ITimelineEventProvider methods … … 155 167 "FROM wiki WHERE time>=%s AND time<=%s", 156 168 (start, stop)) 157 169 for t,name,comment,author,version in cursor: 158 title = Markup('<em>%s</em> edited by %s', 159 wiki.format_page_name(name), author) 160 diff_link = html.A('diff', href=href.wiki(name, action='diff', 161 version=version)) 162 if format == 'rss': 163 comment = wiki_to_html(comment or '--', self.env, req, db, 164 absurls=True) 165 else: 166 comment = wiki_to_oneliner(comment, self.env, db, 167 shorten=True) 168 if version > 1: 169 comment = Markup('%s (%s)', comment, diff_link) 170 yield 'wiki', href.wiki(name), title, t, author, comment 170 if self.authz.has_authorization(req.perm, req.authname, name, 'WIKI_VIEW'): 171 title = Markup('<em>%s</em> edited by %s', 172 wiki.format_page_name(name), author) 173 diff_link = html.A('diff', href=href.wiki(name, action='diff', 174 version=version)) 175 if format == 'rss': 176 comment = wiki_to_html(comment or '--', self.env, req, db, 177 absurls=True) 178 else: 179 comment = wiki_to_oneliner(comment, self.env, db, 180 shorten=True) 181 if version > 1: 182 comment = Markup('%s (%s)', comment, diff_link) 183 yield 'wiki', href.wiki(name), title, t, author, comment 171 184 172 185 # Attachments 173 186 def display(id): … … 180 193 181 194 # Internal methods 182 195 196 def _get_authz(self): 197 return WikiAuthorizer(self.env) 198 183 199 def _set_title(self, req, page, action): 184 200 title = name = WikiSystem(self.env).format_page_name(page.name) 185 201 if action: … … 193 209 req.perm.assert_permission('WIKI_ADMIN') 194 210 else: 195 211 req.perm.assert_permission('WIKI_DELETE') 212 self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_DELETE') 196 213 197 214 if req.args.has_key('cancel'): 198 215 req.redirect(req.href.wiki(page.name)) … … 219 236 req.perm.assert_permission('WIKI_ADMIN') 220 237 elif not page.exists: 221 238 req.perm.assert_permission('WIKI_CREATE') 239 self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_CREATE') 222 240 else: 223 241 req.perm.assert_permission('WIKI_MODIFY') 242 self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_MODIFY') 224 243 225 244 page.text = req.args.get('text') 226 245 if req.perm.has_permission('WIKI_ADMIN'): … … 246 265 req.perm.assert_permission('WIKI_ADMIN') 247 266 else: 248 267 req.perm.assert_permission('WIKI_DELETE') 268 self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_DELETE') 249 269 250 270 version = None 251 271 if req.args.has_key('delete_version'): … … 266 286 267 287 def _render_diff(self, req, db, page): 268 288 req.perm.assert_permission('WIKI_VIEW') 289 self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_VIEW') 269 290 270 291 if not page.exists: 271 292 raise TracError("Version %s of page %s does not exist" % … … 351 372 352 373 def _render_editor(self, req, db, page, preview=False): 353 374 req.perm.assert_permission('WIKI_MODIFY') 375 self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_MODIFY') 354 376 355 377 if req.args.has_key('text'): 356 378 page.text = req.args.get('text') … … 397 419 page. 398 420 """ 399 421 req.perm.assert_permission('WIKI_VIEW') 422 self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_VIEW') 400 423 401 424 if not page.exists: 402 425 raise TracError, "Page %s does not exist" % page.name … … 456 479 'age': pretty_timedelta(page.time) 457 480 } 458 481 else: 459 if not req.perm.has_permission('WIKI_CREATE'): 482 if not req.perm.has_permission('WIKI_CREATE') and\ 483 self.authz.has_authorization(req.perm, req.authname, page.name, 'WIKI_CREATE'): 460 484 raise HTTPNotFound('Page %s not found', page.name) 461 485 req.hdf['wiki.page_html'] = html.P('Describe "%s" here' % page_name) 462 486 463 487 # Show attachments 464 488 req.hdf['wiki.attachments'] = attachments_to_hdf(self.env, req, db, 465 489 'wiki', page.name) 466 if req.perm.has_permission('WIKI_MODIFY'): 490 if req.perm.has_permission('WIKI_MODIFY') and\ 491 self.authz.has_authorization(req.perm, req.authname, page.name, 'WIKI_MODIFY'): 467 492 attach_href = req.href.attachment('wiki', page.name) 468 493 req.hdf['wiki.attach_href'] = attach_href 469 494 … … 487 512 "AND " + sql_query, args) 488 513 489 514 for name, date, author, text in cursor: 490 yield (req.href.wiki(name), '%s: %s' % (name, shorten_line(text)), 491 date, author, shorten_result(text, terms)) 515 if self.authz.has_authorization(req.perm, req.authname, name, 'WIKI_VIEW'): 516 yield (req.href.wiki(name), '%s: %s' % (name, shorten_line(text)), 517 date, author, shorten_result(text, terms))
