diff --git a/configs/development.ini b/configs/development.ini --- a/configs/development.ini +++ b/configs/development.ini @@ -201,22 +201,21 @@ rss_include_diff = false ## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/{gistid} gist_alias_url = -## List of controllers (using glob pattern syntax) that AUTH TOKENS could be +## List of views (using glob pattern syntax) that AUTH TOKENS could be ## used for access. ## Adding ?auth_token=TOKEN_HASH to the url authenticates this request as if it ## came from the the logged in user who own this authentication token. ## -## Syntax is ControllerClass:function_pattern. -## To enable access to raw_files put `FilesController:raw`. -## To enable access to patches add `ChangesetController:changeset_patch`. +## list of all views can be found under `_admin/permissions/auth_token_access` ## The list should be "," separated and on a single line. ## -## Recommended controllers to enable: -# ChangesetController:changeset_patch, -# ChangesetController:changeset_raw, -# FilesController:raw, -# FilesController:archivefile, -# GistsController:*, +## Most common views to enable: +# ChangesetController:changeset_patch +# ChangesetController:changeset_raw +# RepoFilesView.repo_files_diff +# RepoFilesView.repo_archivefile +# RepoFilesView.repo_file_raw +# GistView:* api_access_controllers_whitelist = ## default encoding used to convert from and to unicode diff --git a/configs/production.ini b/configs/production.ini --- a/configs/production.ini +++ b/configs/production.ini @@ -175,22 +175,21 @@ rss_include_diff = false ## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/{gistid} gist_alias_url = -## List of controllers (using glob pattern syntax) that AUTH TOKENS could be +## List of views (using glob pattern syntax) that AUTH TOKENS could be ## used for access. ## Adding ?auth_token=TOKEN_HASH to the url authenticates this request as if it ## came from the the logged in user who own this authentication token. ## -## Syntax is ControllerClass:function_pattern. -## To enable access to raw_files put `FilesController:raw`. -## To enable access to patches add `ChangesetController:changeset_patch`. +## list of all views can be found under `_admin/permissions/auth_token_access` ## The list should be "," separated and on a single line. ## -## Recommended controllers to enable: -# ChangesetController:changeset_patch, -# ChangesetController:changeset_raw, -# FilesController:raw, -# FilesController:archivefile, -# GistsController:*, +## Most common views to enable: +# ChangesetController:changeset_patch +# ChangesetController:changeset_raw +# RepoFilesView.repo_files_diff +# RepoFilesView.repo_archivefile +# RepoFilesView.repo_file_raw +# GistView:* api_access_controllers_whitelist = ## default encoding used to convert from and to unicode diff --git a/rhodecode/apps/admin/__init__.py b/rhodecode/apps/admin/__init__.py --- a/rhodecode/apps/admin/__init__.py +++ b/rhodecode/apps/admin/__init__.py @@ -102,6 +102,10 @@ def admin_routes(config): name='admin_permissions_overview', pattern='/permissions/overview') + config.add_route( + name='admin_permissions_auth_token_access', + pattern='/permissions/auth_token_access') + # users admin config.add_route( name='users', diff --git a/rhodecode/apps/admin/views/permissions.py b/rhodecode/apps/admin/views/permissions.py --- a/rhodecode/apps/admin/views/permissions.py +++ b/rhodecode/apps/admin/views/permissions.py @@ -18,8 +18,10 @@ # RhodeCode Enterprise Edition, including its added features, Support services, # and proprietary license terms, please see https://rhodecode.com/licenses/ +import re import logging import formencode +from pyramid.interfaces import IRoutesMapper from pyramid.view import view_config from pyramid.httpexceptions import HTTPFound @@ -31,6 +33,7 @@ from rhodecode.apps._base import BaseApp from rhodecode.lib import helpers as h from rhodecode.lib.auth import ( LoginRequired, HasPermissionAllDecorator, CSRFRequired) +from rhodecode.lib.utils2 import aslist from rhodecode.model.db import User, UserIpMap from rhodecode.model.forms import ( ApplicationPermissionsForm, ObjectPermissionsForm, UserPermissionsForm) @@ -308,3 +311,59 @@ class AdminPermissionsView(BaseAppView): c.user = User.get_default_user(refresh=True) c.perm_user = c.user.AuthUser return self._get_template_context(c) + + @LoginRequired() + @HasPermissionAllDecorator('hg.admin') + @view_config( + route_name='admin_permissions_auth_token_access', request_method='GET', + renderer='rhodecode:templates/admin/permissions/permissions.mako') + def auth_token_access(self): + from rhodecode import CONFIG + + c = self.load_default_context() + c.active = 'auth_token_access' + + c.user = User.get_default_user(refresh=True) + c.perm_user = c.user.AuthUser + + mapper = self.request.registry.queryUtility(IRoutesMapper) + c.view_data = [] + + _argument_prog = re.compile('\{(.*?)\}|:\((.*)\)') + introspector = self.request.registry.introspector + + view_intr = {} + for view_data in introspector.get_category('views'): + intr = view_data['introspectable'] + + if 'route_name' in intr and intr['attr']: + view_intr[intr['route_name']] = '{}.{}'.format( + str(intr['derived_callable'].func_name), intr['attr'] + ) + + c.whitelist_key = 'api_access_controllers_whitelist' + c.whitelist_file = CONFIG.get('__file__') + whitelist_views = aslist( + CONFIG.get(c.whitelist_key), sep=',') + + for route_info in mapper.get_routes(): + if not route_info.name.startswith('__'): + routepath = route_info.pattern + + def replace(matchobj): + if matchobj.group(1): + return "{%s}" % matchobj.group(1).split(':')[0] + else: + return "{%s}" % matchobj.group(2) + + routepath = _argument_prog.sub(replace, routepath) + + if not routepath.startswith('/'): + routepath = '/' + routepath + + view_fqn = view_intr.get(route_info.name, 'NOT AVAILABLE') + active = view_fqn in whitelist_views + c.view_data.append((route_info.name, view_fqn, routepath, active)) + + c.whitelist_views = whitelist_views + return self._get_template_context(c) diff --git a/rhodecode/public/js/rhodecode/routes.js b/rhodecode/public/js/rhodecode/routes.js --- a/rhodecode/public/js/rhodecode/routes.js +++ b/rhodecode/public/js/rhodecode/routes.js @@ -71,6 +71,7 @@ function registerRCRoutes() { pyroutes.register('admin_permissions_object_update', '/_admin/permissions/object/update', []); pyroutes.register('admin_permissions_ips', '/_admin/permissions/ips', []); pyroutes.register('admin_permissions_overview', '/_admin/permissions/overview', []); + pyroutes.register('admin_permissions_auth_token_access', '/_admin/permissions/auth_token_access', []); pyroutes.register('users', '/_admin/users', []); pyroutes.register('users_data', '/_admin/users_data', []); pyroutes.register('edit_user_auth_tokens', '/_admin/users/%(user_id)s/edit/auth_tokens', ['user_id']); @@ -176,7 +177,7 @@ function registerRCRoutes() { pyroutes.register('my_account_edit', '/_admin/my_account/edit', []); pyroutes.register('my_account_update', '/_admin/my_account/update', []); pyroutes.register('my_account_password', '/_admin/my_account/password', []); - pyroutes.register('my_account_password_update', '/_admin/my_account/password', []); + pyroutes.register('my_account_password_update', '/_admin/my_account/password/update', []); pyroutes.register('my_account_auth_tokens', '/_admin/my_account/auth_tokens', []); pyroutes.register('my_account_auth_tokens_add', '/_admin/my_account/auth_tokens/new', []); pyroutes.register('my_account_auth_tokens_delete', '/_admin/my_account/auth_tokens/delete', []); diff --git a/rhodecode/templates/admin/permissions/permissions.mako b/rhodecode/templates/admin/permissions/permissions.mako --- a/rhodecode/templates/admin/permissions/permissions.mako +++ b/rhodecode/templates/admin/permissions/permissions.mako @@ -41,6 +41,9 @@
  • ${_('IP Whitelist')}
  • +
  • + ${_('AuthToken Access')} +
  • ${_('Overview')}
  • diff --git a/rhodecode/templates/admin/permissions/permissions_auth_token_access.mako b/rhodecode/templates/admin/permissions/permissions_auth_token_access.mako new file mode 100644 --- /dev/null +++ b/rhodecode/templates/admin/permissions/permissions_auth_token_access.mako @@ -0,0 +1,61 @@ + + +
    +
    +

    ${_('View whitelist')}

    +
    +
    +
    + +

    +View white list defines a set of views that can be accessed using auth token without the need to login. +Adding ?auth_token = SECRET_TOKEN to the url authenticates this request as if it +came from the the logged in user who owns this authentication token. + +E.g. adding `RepoFilesView.repo_file_raw` allows to access a raw diff using such url: + http[s]://server.com/{repo_name}/raw/{commit_id}/{file_path}?auth_token=SECRET_TOKEN + +White list can be defined inside `${c.whitelist_file}` under `${c.whitelist_key}=` setting + +Currently under this settings following views are set: +

    + +
    +% for entry in c.whitelist_views:
    +${entry}
    +% endfor
    +    
    + +
    + +
    +
    + + +
    +
    +

    ${_('List of views available for usage in whitelist access')}

    +
    +
    +
    + + + + + + + + + + % for route_name, view_fqn, view_url, active in c.view_data: + + + + + + % endfor +
    ActiveView FQNURL pattern
    ${h.bool2icon(active)}${view_fqn}${view_url}
    +
    + +
    +