Ticket #898: rbac.patch

File rbac.patch, 10.6 kB (added by mnencia, 2 years ago)

Patch for 0.10

  • trac/wiki/rbac.py

    old new  
     1from trac.core import * 
     2from trac.perm import PermissionError 
     3from trac.versioncontrol.svn_authz import RealSubversionAuthorizer 
     4from trac.versioncontrol import Authorizer, PermissionDenied 
     5 
     6def 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 
     16class 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 
     25class 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 
     53class 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 
     62class 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  
    3636from trac.wiki.model import WikiPage 
    3737from trac.wiki.formatter import wiki_to_html, wiki_to_oneliner 
    3838from trac.mimeview.api import Mimeview, IContentConverter 
     39from trac.wiki.rbac import WikiAuthorizer 
    3940 
    4041 
    4142class InvalidWikiPage(TracError): 
     
    4748    implements(INavigationContributor, IPermissionRequestor, IRequestHandler, 
    4849               ITimelineEventProvider, ISearchSource, IContentConverter) 
    4950 
     51    authz = property(fget=lambda self: self._get_authz()) 
     52 
    5053    page_manipulators = ExtensionPoint(IWikiPageManipulator) 
    5154 
    5255    # IContentConverter methods 
     
    9396        if pagename.endswith('/'): 
    9497            req.redirect(req.href.wiki(pagename.strip('/'))) 
    9598 
     99        self.authz.assert_authorization(req.perm, req.authname, pagename, 'WIKI_VIEW') 
    96100        db = self.env.get_db_cnx() 
    97101        page = WikiPage(self.env, pagename, version, db) 
    98102 
     
    135139 
    136140        req.hdf['wiki.action'] = action 
    137141        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 
    138149        return 'wiki.cs', None 
    139150 
    140151    # ITimelineEventProvider methods 
     
    154165                           "FROM wiki WHERE time>=%s AND time<=%s", 
    155166                           (start, stop)) 
    156167            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 
    170182 
    171183            # Attachments 
    172184            def display(id): 
     
    179191 
    180192    # Internal methods 
    181193 
     194    def _get_authz(self): 
     195        return WikiAuthorizer(self.env) 
     196 
    182197    def _set_title(self, req, page, action): 
    183198        title = name = WikiSystem(self.env).format_page_name(page.name) 
    184199        if action: 
     
    192207            req.perm.assert_permission('WIKI_ADMIN') 
    193208        else: 
    194209            req.perm.assert_permission('WIKI_DELETE') 
     210            self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_DELETE') 
    195211 
    196212        if req.args.has_key('cancel'): 
    197213            req.redirect(req.href.wiki(page.name)) 
     
    218234            req.perm.assert_permission('WIKI_ADMIN') 
    219235        elif not page.exists: 
    220236            req.perm.assert_permission('WIKI_CREATE') 
     237            self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_CREATE') 
    221238        else: 
    222239            req.perm.assert_permission('WIKI_MODIFY') 
     240            self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_MODIFY') 
    223241 
    224242        page.text = req.args.get('text') 
    225243        if req.perm.has_permission('WIKI_ADMIN'): 
     
    245263            req.perm.assert_permission('WIKI_ADMIN') 
    246264        else: 
    247265            req.perm.assert_permission('WIKI_DELETE') 
     266            self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_DELETE') 
    248267 
    249268        version = None 
    250269        if req.args.has_key('delete_version'): 
     
    265284 
    266285    def _render_diff(self, req, db, page): 
    267286        req.perm.assert_permission('WIKI_VIEW') 
     287        self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_VIEW') 
    268288 
    269289        if not page.exists: 
    270290            raise TracError("Version %s of page %s does not exist" % 
     
    350370 
    351371    def _render_editor(self, req, db, page, preview=False): 
    352372        req.perm.assert_permission('WIKI_MODIFY') 
     373        self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_MODIFY') 
    353374 
    354375        if req.args.has_key('text'): 
    355376            page.text = req.args.get('text') 
     
    396417        page. 
    397418        """ 
    398419        req.perm.assert_permission('WIKI_VIEW') 
     420        self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_VIEW') 
    399421 
    400422        if not page.exists: 
    401423            raise TracError, "Page %s does not exist" % page.name 
     
    419441 
    420442    def _render_view(self, req, db, page): 
    421443        req.perm.assert_permission('WIKI_VIEW') 
     444        self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_VIEW') 
    422445 
    423446        page_name = self._set_title(req, page, '') 
    424447        if page.name == 'WikiStart': 
     
    457480                    'age': pretty_timedelta(page.time) 
    458481                    } 
    459482        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'): 
    461485                raise HTTPNotFound('Page %s not found', page.name) 
    462486            req.hdf['wiki.page_html'] = html.P('Describe "%s" here' % page_name) 
    463487 
    464488        # Show attachments 
    465489        req.hdf['wiki.attachments'] = attachments_to_hdf(self.env, req, db, 
    466490                                                         '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'): 
    468493            attach_href = req.href.attachment('wiki', page.name) 
    469494            req.hdf['wiki.attach_href'] = attach_href 
    470495 
     
    488513                       "AND " + sql_query, args) 
    489514 
    490515        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))