Edgewall Software
Modify

Opened 13 years ago

Last modified 13 years ago

#725 new enhancement

[PATCH] Per-configuration permissioning

Reported by: Roland Wilczek <r.wilczek@…> Owned by:
Priority: major Milestone: 0.6.2
Component: Build master Version: 0.6
Keywords: Cc:
Operating System:

Description

The following patch and tutorials allows to permit users to

  • access build configurations read-only
  • modify configurations on a per-configuration-base

Creating and deleting configurations is left unchanged, and requires the general permissions BUILD_CREATE and BUILD_DELETE.

BUILD_MODIFY permits to

  • modify all configurations.
  • create, delete and update target platforms

The permission to modify a build configuration named foobar to a single user is granted by:

  • granting BUILD_LIST to the user
  • granting BUILD_MODIFY_foobar to the user

I can think of much nicer (and more capable) solutions, but Bitten's permissioning strategy seems not to really comply with trac's idea. So the capabilities of plugins like Authz Policy? and Extra Permissions Provider? cannot be completely used.

Tutorial

Install package configobj. Maybe easy_install configobj does the job.

In the [components] section of trac.ini add:

[components]
tracopt.perm.authz_policy.authzpolicy = enabled
tracopt.perm.config_perm_provider.extrapermissionsprovider = enabled

Create a new section [extra-permissions] in trac.ini if necessary and add:

[extra-permissions]
_perms = BUILD_LIST

Create a section [authz_policy] in trac.ini and define:

[authz_policy]
authz_file = conf/authz.policy

Create a new file authz.policy in /path/to/trac/conf/. (Path and name must comply with that given as authz_file in authz_policy in your trac.ini, of course:

[*]
# To permit a user to administer a build configuration, 
# grant BUILD_LIST to him and permit him to BUILD_MODIFY_configname:
# bob  = BUILD_LIST, BUILD_MODIFY_configurationName
# The user is then able to manage the build configuration's metadata 
# (name, label, description, recipe and repository-mapping).
# Managing target-platforms as well as creating, deleting, activating/deacivating 
# a configuration requires the global permission BUILD_MODIFY.
Tom = BUILD_LIST
Bob = BUILD_LIST, BUILD_MODIFY_BobsConfig
Tim = BUILD_MODIFY_TimsConfig, BUILD_MODIFY_BobsConfig
Max = BUILD_MODIFY

Invoke the patch below.

Restart Apache.

Result:

  • Tom has read-only access to all build-configurations within the Admin-panel.
  • Bob has read-only access to all build-configurations and is able to modify BobsConfig
  • Tim lacks the permission BUILD_LIST. Thus his permission to modify TimsConfig and BobsConfig is revoked. As soon as he is permitted to BUILD_LIST, the permissions will be activated again.
  • Max is able to view and modify all build configurations. He is the only one permitted to
    • create new build configurations
    • delete existing build configurations
    • set existing build configurations active|inactive
    • create, modify and delete target platforms
  • SCM/Bitten/bitten/admin.py

     
    8989
    9090
    9191class BuildConfigurationsAdminPageProvider(Component):
    9292    """Web administration panel for configuring the build master."""
    9393
    9494    implements(IAdminPanelProvider)
    9595
    9696    # IAdminPanelProvider methods
    9797
    9898    def get_admin_panels(self, req):
    99         if req.perm.has_permission('BUILD_MODIFY'):
     99        if req.perm.has_permission('BUILD_LIST') or req.perm.has_permission('BUILD_MODIFY'):
    100100            yield ('bitten', 'Builds', 'configs', 'Configurations')
    101101
    102102    def render_admin_panel(self, req, cat, page, path_info):
    103103        data = {}
    104104
    105105        # Analyze url
    106106        try:
    107107            config_name, platform_id = path_info.split('/', 1)
    108108        except:
    109109            config_name = path_info
     
    257257        db = self.env.get_db_cnx()
    258258        for name in sel:
    259259            config = BuildConfig.fetch(self.env, name, db=db)
    260260            if not config:
    261261                raise TracError('Configuration %r not found' % name)
    262262            config.delete(db=db)
    263263        db.commit()
    264264
    265265    def _update_config(self, req, config):
    266266        warnings = []
    267         req.perm.assert_permission('BUILD_MODIFY')
     267        if not req.perm.has_permission('BUILD_MODIFY_' + req.args.get('name')):
     268            req.perm.assert_permission('BUILD_MODIFY')
    268269
    269270        name = req.args.get('name')
    270271        if not name:
    271272            warnings.append('Missing required field "name".')
    272273        if name and not re.match(r'^[\w.-]+$', name):
    273274            warnings.append('The field "name" may only contain letters, '
    274275                            'digits, periods, or dashes.')
    275276
    276277        repos = self.env.get_repository(authname=req.authname)
    277278        if not repos:
     
    342343
    343344        db = self.env.get_db_cnx()
    344345        for platform_id in sel:
    345346            platform = TargetPlatform.fetch(self.env, platform_id, db=db)
    346347            if not platform:
    347348                raise TracError('Target platform %r not found' % platform_id)
    348349            platform.delete(db=db)
    349350        db.commit()
    350351
    351352    def _update_platform(self, req, platform):
     353        req.perm.assert_permission('BUILD_MODIFY')
    352354        platform.name = req.args.get('name')
    353355
    354356        properties = [int(key[9:]) for key in req.args.keys()
    355357                      if key.startswith('property_')]
    356358        properties.sort()
    357359        patterns = [int(key[8:]) for key in req.args.keys()
    358360                    if key.startswith('pattern_')]
    359361        patterns.sort()
    360362        platform.rules = [(req.args.get('property_%d' % property).strip(),
    361363                           req.args.get('pattern_%d' % pattern).strip())

Attachments (0)

Change History (2)

comment:1 Changed 13 years ago by osimons

What we really should do is support the resource system fully, and not just partially. I added resource support to Bitten as it was required for attachment support, but I have not yet pushed it into the permission checks.

Supporting permissions properly would mean that we should strive to do checks like:

... 'BUILD_VIEW' in perm(resource) ...

and

... perm(resource).assert_permission('BUILD_MODIFY') ...

That way any permission check in Bitten can be subject to manipulation by regular permission policy plugin - like AuthzPolicy.

It would not require much effort to make sure all checks referred to a resource (where applicable) + change/add some unit tests to verify this. There are only ~40 occurrences of BUILD_* in the repository (all code + tests + documentation), but need to review to make sure we loop all resources in the various views.

I'd rather go that way than change the permission structure itself.

comment:2 Changed 13 years ago by Roland Wilczek <r.wilczek@…>

I'd appreciate a better integration of Bitten into trac's resource system a lot!

Add Comment

Modify Ticket

Change Properties
Set your email in Preferences
Action
as new The ticket will remain with no owner.
Author


E-mail address and user name can be saved in the Preferences.

 
Note: See TracTickets for help on using tickets.