permissions: expose new view that lists all available views for usage in whitelist access.

This commit is contained in:
Marcin Kuzminski 2017-07-21 04:54:36 +02:00
parent 8bfe9e6306
commit dc2af71072
7 changed files with 147 additions and 21 deletions

View file

@ -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

View file

@ -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

View file

@ -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',

View file

@ -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 BaseAppView
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)

View file

@ -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', []);

View file

@ -41,6 +41,9 @@
<li class="${'active' if c.active=='ips' else ''}">
<a href="${h.route_path('admin_permissions_ips')}">${_('IP Whitelist')}</a>
</li>
<li class="${'active' if c.active=='auth_token_access' else ''}">
<a href="${h.route_path('admin_permissions_auth_token_access')}">${_('AuthToken Access')}</a>
</li>
<li class="${'active' if c.active=='perms' else ''}">
<a href="${h.route_path('admin_permissions_overview')}">${_('Overview')}</a>
</li>

View file

@ -0,0 +1,61 @@
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">${_('View whitelist')}</h3>
</div>
<div class="panel-body">
<div class="">
<p class="pr-description">
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:
</p>
<pre>
% for entry in c.whitelist_views:
${entry}
% endfor
</pre>
</div>
</div>
</div>
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">${_('List of views available for usage in whitelist access')}</h3>
</div>
<div class="panel-body">
<div class="">
<table class="rctable ip-whitelist">
<tr>
<th>Active</th>
<th>View FQN</th>
<th>URL pattern</th>
</tr>
% for route_name, view_fqn, view_url, active in c.view_data:
<tr>
<td class="td-x">${h.bool2icon(active)}</td>
<td class="td-x">${view_fqn}</td>
<td class="td-x" title="${route_name}">${view_url}</td>
</tr>
% endfor
</table>
</div>
</div>
</div>