Ticket #898: rbac.2.patch

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

Patch for 0.10.1

  • 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 
     
    128132            self._render_history(req, db, page) 
    129133        else: 
    130134            req.perm.assert_permission('WIKI_VIEW')             
     135            self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_VIEW') 
    131136            format = req.args.get('format') 
    132137            if format: 
    133138                Mimeview(self.env).send_converted(req, 'text/x-trac-wiki', 
     
    136141 
    137142        req.hdf['wiki.action'] = action 
    138143        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 
    139151        return 'wiki.cs', None 
    140152 
    141153    # ITimelineEventProvider methods 
     
    155167                           "FROM wiki WHERE time>=%s AND time<=%s", 
    156168                           (start, stop)) 
    157169            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 
    171184 
    172185            # Attachments 
    173186            def display(id): 
     
    180193 
    181194    # Internal methods 
    182195 
     196    def _get_authz(self): 
     197        return WikiAuthorizer(self.env) 
     198 
    183199    def _set_title(self, req, page, action): 
    184200        title = name = WikiSystem(self.env).format_page_name(page.name) 
    185201        if action: 
     
    193209            req.perm.assert_permission('WIKI_ADMIN') 
    194210        else: 
    195211            req.perm.assert_permission('WIKI_DELETE') 
     212            self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_DELETE') 
    196213 
    197214        if req.args.has_key('cancel'): 
    198215            req.redirect(req.href.wiki(page.name)) 
     
    219236            req.perm.assert_permission('WIKI_ADMIN') 
    220237        elif not page.exists: 
    221238            req.perm.assert_permission('WIKI_CREATE') 
     239            self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_CREATE') 
    222240        else: 
    223241            req.perm.assert_permission('WIKI_MODIFY') 
     242            self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_MODIFY') 
    224243 
    225244        page.text = req.args.get('text') 
    226245        if req.perm.has_permission('WIKI_ADMIN'): 
     
    246265            req.perm.assert_permission('WIKI_ADMIN') 
    247266        else: 
    248267            req.perm.assert_permission('WIKI_DELETE') 
     268            self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_DELETE') 
    249269 
    250270        version = None 
    251271        if req.args.has_key('delete_version'): 
     
    266286 
    267287    def _render_diff(self, req, db, page): 
    268288        req.perm.assert_permission('WIKI_VIEW') 
     289        self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_VIEW') 
    269290 
    270291        if not page.exists: 
    271292            raise TracError("Version %s of page %s does not exist" % 
     
    351372 
    352373    def _render_editor(self, req, db, page, preview=False): 
    353374        req.perm.assert_permission('WIKI_MODIFY') 
     375        self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_MODIFY') 
    354376 
    355377        if req.args.has_key('text'): 
    356378            page.text = req.args.get('text') 
     
    397419        page. 
    398420        """ 
    399421        req.perm.assert_permission('WIKI_VIEW') 
     422        self.authz.assert_authorization(req.perm, req.authname, page.name, 'WIKI_VIEW') 
    400423 
    401424        if not page.exists: 
    402425            raise TracError, "Page %s does not exist" % page.name 
     
    456479                    'age': pretty_timedelta(page.time) 
    457480                    } 
    458481        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'): 
    460484                raise HTTPNotFound('Page %s not found', page.name) 
    461485            req.hdf['wiki.page_html'] = html.P('Describe "%s" here' % page_name) 
    462486 
    463487        # Show attachments 
    464488        req.hdf['wiki.attachments'] = attachments_to_hdf(self.env, req, db, 
    465489                                                         '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'): 
    467492            attach_href = req.href.attachment('wiki', page.name) 
    468493            req.hdf['wiki.attach_href'] = attach_href 
    469494 
     
    487512                       "AND " + sql_query, args) 
    488513 
    489514        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))