Show More
@@ -162,6 +162,14 b' def admin_routes(config):' | |||||
162 | name='edit_user_ips_delete', |
|
162 | name='edit_user_ips_delete', | |
163 | pattern='/users/{user_id:\d+}/edit/ips/delete') |
|
163 | pattern='/users/{user_id:\d+}/edit/ips/delete') | |
164 |
|
164 | |||
|
165 | # user perms | |||
|
166 | config.add_route( | |||
|
167 | name='edit_user_perms_summary', | |||
|
168 | pattern='/users/{user_id:\d+}/edit/permissions_summary') | |||
|
169 | config.add_route( | |||
|
170 | name='edit_user_perms_summary_json', | |||
|
171 | pattern='/users/{user_id:\d+}/edit/permissions_summary/json') | |||
|
172 | ||||
165 | # user groups management |
|
173 | # user groups management | |
166 | config.add_route( |
|
174 | config.add_route( | |
167 | name='edit_user_groups_management', |
|
175 | name='edit_user_groups_management', | |
@@ -189,6 +197,14 b' def admin_routes(config):' | |||||
189 | name='user_group_members_data', |
|
197 | name='user_group_members_data', | |
190 | pattern='/user_groups/{user_group_id:\d+}/members') |
|
198 | pattern='/user_groups/{user_group_id:\d+}/members') | |
191 |
|
199 | |||
|
200 | # user groups perms | |||
|
201 | config.add_route( | |||
|
202 | name='edit_user_group_perms_summary', | |||
|
203 | pattern='/user_groups/{user_group_id:\d+}/edit/permissions_summary') | |||
|
204 | config.add_route( | |||
|
205 | name='edit_user_group_perms_summary_json', | |||
|
206 | pattern='/user_groups/{user_group_id:\d+}/edit/permissions_summary/json') | |||
|
207 | ||||
192 |
|
208 | |||
193 | def includeme(config): |
|
209 | def includeme(config): | |
194 | settings = config.get_settings() |
|
210 | settings = config.get_settings() |
@@ -24,9 +24,7 b' import datetime' | |||||
24 | from pyramid.httpexceptions import HTTPFound |
|
24 | from pyramid.httpexceptions import HTTPFound | |
25 | from pyramid.view import view_config |
|
25 | from pyramid.view import view_config | |
26 |
|
26 | |||
27 | from rhodecode.lib.helpers import Page |
|
|||
28 | from rhodecode.model.scm import UserGroupList |
|
27 | from rhodecode.model.scm import UserGroupList | |
29 | from rhodecode_tools.lib.ext_json import json |
|
|||
30 |
|
28 | |||
31 | from rhodecode.apps._base import BaseAppView, DataGridAppView |
|
29 | from rhodecode.apps._base import BaseAppView, DataGridAppView | |
32 | from rhodecode.lib.auth import ( |
|
30 | from rhodecode.lib.auth import ( | |
@@ -35,10 +33,10 b' from rhodecode.lib.auth import (' | |||||
35 | from rhodecode.lib import helpers as h |
|
33 | from rhodecode.lib import helpers as h | |
36 | from rhodecode.lib.utils import PartialRenderer |
|
34 | from rhodecode.lib.utils import PartialRenderer | |
37 | from rhodecode.lib.utils2 import safe_int, safe_unicode |
|
35 | from rhodecode.lib.utils2 import safe_int, safe_unicode | |
38 | from rhodecode.model.auth_token import AuthTokenModel |
|
|||
39 | from rhodecode.model.user import UserModel |
|
|||
40 | from rhodecode.model.user_group import UserGroupModel |
|
36 | from rhodecode.model.user_group import UserGroupModel | |
41 | from rhodecode.model.db import User, UserGroup, UserGroupMember, or_, count |
|
37 | from rhodecode.model.db import ( | |
|
38 | joinedload, or_, count, User, UserGroup, UserGroupMember, | |||
|
39 | UserGroupRepoToPerm, UserGroupRepoGroupToPerm) | |||
42 | from rhodecode.model.meta import Session |
|
40 | from rhodecode.model.meta import Session | |
43 |
|
41 | |||
44 | log = logging.getLogger(__name__) |
|
42 | log = logging.getLogger(__name__) | |
@@ -201,3 +199,58 b' class AdminUserGroupsView(BaseAppView, D' | |||||
201 | return { |
|
199 | return { | |
202 | 'members': group_members |
|
200 | 'members': group_members | |
203 | } |
|
201 | } | |
|
202 | ||||
|
203 | def _get_perms_summary(self, user_group_id): | |||
|
204 | permissions = { | |||
|
205 | 'repositories': {}, | |||
|
206 | 'repositories_groups': {}, | |||
|
207 | } | |||
|
208 | ugroup_repo_perms = UserGroupRepoToPerm.query()\ | |||
|
209 | .options(joinedload(UserGroupRepoToPerm.permission))\ | |||
|
210 | .options(joinedload(UserGroupRepoToPerm.repository))\ | |||
|
211 | .filter(UserGroupRepoToPerm.users_group_id == user_group_id)\ | |||
|
212 | .all() | |||
|
213 | ||||
|
214 | for gr in ugroup_repo_perms: | |||
|
215 | permissions['repositories'][gr.repository.repo_name] \ | |||
|
216 | = gr.permission.permission_name | |||
|
217 | ||||
|
218 | ugroup_group_perms = UserGroupRepoGroupToPerm.query()\ | |||
|
219 | .options(joinedload(UserGroupRepoGroupToPerm.permission))\ | |||
|
220 | .options(joinedload(UserGroupRepoGroupToPerm.group))\ | |||
|
221 | .filter(UserGroupRepoGroupToPerm.users_group_id == user_group_id)\ | |||
|
222 | .all() | |||
|
223 | ||||
|
224 | for gr in ugroup_group_perms: | |||
|
225 | permissions['repositories_groups'][gr.group.group_name] \ | |||
|
226 | = gr.permission.permission_name | |||
|
227 | return permissions | |||
|
228 | ||||
|
229 | @LoginRequired() | |||
|
230 | @HasUserGroupPermissionAnyDecorator('usergroup.admin') | |||
|
231 | @view_config( | |||
|
232 | route_name='edit_user_group_perms_summary', request_method='GET', | |||
|
233 | renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako') | |||
|
234 | def user_group_perms_summary(self): | |||
|
235 | c = self.load_default_context() | |||
|
236 | ||||
|
237 | user_group_id = self.request.matchdict.get('user_group_id') | |||
|
238 | c.user_group = UserGroup.get_or_404(user_group_id) | |||
|
239 | ||||
|
240 | c.active = 'perms_summary' | |||
|
241 | ||||
|
242 | c.permissions = self._get_perms_summary(c.user_group.users_group_id) | |||
|
243 | return self._get_template_context(c) | |||
|
244 | ||||
|
245 | @LoginRequired() | |||
|
246 | @HasUserGroupPermissionAnyDecorator('usergroup.admin') | |||
|
247 | @view_config( | |||
|
248 | route_name='edit_user_group_perms_summary_json', request_method='GET', | |||
|
249 | renderer='json_ext') | |||
|
250 | def user_group_perms_summary(self): | |||
|
251 | self.load_default_context() | |||
|
252 | ||||
|
253 | user_group_id = self.request.matchdict.get('user_group_id') | |||
|
254 | user_group = UserGroup.get_or_404(user_group_id) | |||
|
255 | ||||
|
256 | return self._get_perms_summary(user_group.users_group_id) |
@@ -635,3 +635,36 b' class AdminUsersView(BaseAppView, DataGr' | |||||
635 | c.filter_term = filter_term |
|
635 | c.filter_term = filter_term | |
636 | return self._get_template_context(c) |
|
636 | return self._get_template_context(c) | |
637 |
|
637 | |||
|
638 | @LoginRequired() | |||
|
639 | @HasPermissionAllDecorator('hg.admin') | |||
|
640 | @view_config( | |||
|
641 | route_name='edit_user_perms_summary', request_method='GET', | |||
|
642 | renderer='rhodecode:templates/admin/users/user_edit.mako') | |||
|
643 | def user_perms_summary(self): | |||
|
644 | _ = self.request.translate | |||
|
645 | c = self.load_default_context() | |||
|
646 | ||||
|
647 | user_id = self.request.matchdict.get('user_id') | |||
|
648 | c.user = User.get_or_404(user_id) | |||
|
649 | self._redirect_for_default_user(c.user.username) | |||
|
650 | ||||
|
651 | c.active = 'perms_summary' | |||
|
652 | c.perm_user = c.user.AuthUser(ip_addr=self.request.remote_addr) | |||
|
653 | ||||
|
654 | return self._get_template_context(c) | |||
|
655 | ||||
|
656 | @LoginRequired() | |||
|
657 | @HasPermissionAllDecorator('hg.admin') | |||
|
658 | @view_config( | |||
|
659 | route_name='edit_user_perms_summary_json', request_method='GET', | |||
|
660 | renderer='json_ext') | |||
|
661 | def user_perms_summary_json(self): | |||
|
662 | self.load_default_context() | |||
|
663 | ||||
|
664 | user_id = self.request.matchdict.get('user_id') | |||
|
665 | user = User.get_or_404(user_id) | |||
|
666 | self._redirect_for_default_user(user.username) | |||
|
667 | ||||
|
668 | perm_user = user.AuthUser(ip_addr=self.request.remote_addr) | |||
|
669 | ||||
|
670 | return perm_user.permissions |
@@ -271,9 +271,6 b' def make_map(config):' | |||||
271 | m.connect('edit_user_global_perms', '/users/{user_id}/edit/global_permissions', |
|
271 | m.connect('edit_user_global_perms', '/users/{user_id}/edit/global_permissions', | |
272 | action='update_global_perms', conditions={'method': ['PUT']}) |
|
272 | action='update_global_perms', conditions={'method': ['PUT']}) | |
273 |
|
273 | |||
274 | m.connect('edit_user_perms_summary', '/users/{user_id}/edit/permissions_summary', |
|
|||
275 | action='edit_perms_summary', conditions={'method': ['GET']}) |
|
|||
276 |
|
||||
277 | # ADMIN USER GROUPS REST ROUTES |
|
274 | # ADMIN USER GROUPS REST ROUTES | |
278 | with rmap.submapper(path_prefix=ADMIN_PREFIX, |
|
275 | with rmap.submapper(path_prefix=ADMIN_PREFIX, | |
279 | controller='admin/user_groups') as m: |
|
276 | controller='admin/user_groups') as m: | |
@@ -296,9 +293,6 b' def make_map(config):' | |||||
296 | m.connect('edit_user_group_global_perms', |
|
293 | m.connect('edit_user_group_global_perms', | |
297 | '/user_groups/{user_group_id}/edit/global_permissions', |
|
294 | '/user_groups/{user_group_id}/edit/global_permissions', | |
298 | action='update_global_perms', conditions={'method': ['PUT']}) |
|
295 | action='update_global_perms', conditions={'method': ['PUT']}) | |
299 | m.connect('edit_user_group_perms_summary', |
|
|||
300 | '/user_groups/{user_group_id}/edit/permissions_summary', |
|
|||
301 | action='edit_perms_summary', conditions={'method': ['GET']}) |
|
|||
302 |
|
296 | |||
303 | m.connect('edit_user_group_perms', |
|
297 | m.connect('edit_user_group_perms', | |
304 | '/user_groups/{user_group_id}/edit/permissions', |
|
298 | '/user_groups/{user_group_id}/edit/permissions', |
@@ -297,36 +297,7 b' class UserGroupsController(BaseControlle' | |||||
297 | h.flash(_('User Group permissions updated'), category='success') |
|
297 | h.flash(_('User Group permissions updated'), category='success') | |
298 | return redirect(url('edit_user_group_perms', user_group_id=user_group_id)) |
|
298 | return redirect(url('edit_user_group_perms', user_group_id=user_group_id)) | |
299 |
|
299 | |||
300 | @HasUserGroupPermissionAnyDecorator('usergroup.admin') |
|
|||
301 | def edit_perms_summary(self, user_group_id): |
|
|||
302 | user_group_id = safe_int(user_group_id) |
|
|||
303 | c.user_group = UserGroup.get_or_404(user_group_id) |
|
|||
304 | c.active = 'perms_summary' |
|
|||
305 | permissions = { |
|
|||
306 | 'repositories': {}, |
|
|||
307 | 'repositories_groups': {}, |
|
|||
308 | } |
|
|||
309 | ugroup_repo_perms = UserGroupRepoToPerm.query()\ |
|
|||
310 | .options(joinedload(UserGroupRepoToPerm.permission))\ |
|
|||
311 | .options(joinedload(UserGroupRepoToPerm.repository))\ |
|
|||
312 | .filter(UserGroupRepoToPerm.users_group_id == user_group_id)\ |
|
|||
313 | .all() |
|
|||
314 |
|
300 | |||
315 | for gr in ugroup_repo_perms: |
|
|||
316 | permissions['repositories'][gr.repository.repo_name] \ |
|
|||
317 | = gr.permission.permission_name |
|
|||
318 |
|
||||
319 | ugroup_group_perms = UserGroupRepoGroupToPerm.query()\ |
|
|||
320 | .options(joinedload(UserGroupRepoGroupToPerm.permission))\ |
|
|||
321 | .options(joinedload(UserGroupRepoGroupToPerm.group))\ |
|
|||
322 | .filter(UserGroupRepoGroupToPerm.users_group_id == user_group_id)\ |
|
|||
323 | .all() |
|
|||
324 |
|
||||
325 | for gr in ugroup_group_perms: |
|
|||
326 | permissions['repositories_groups'][gr.group.group_name] \ |
|
|||
327 | = gr.permission.permission_name |
|
|||
328 | c.permissions = permissions |
|
|||
329 | return render('admin/user_groups/user_group_edit.mako') |
|
|||
330 |
|
301 | |||
331 | @HasUserGroupPermissionAnyDecorator('usergroup.admin') |
|
302 | @HasUserGroupPermissionAnyDecorator('usergroup.admin') | |
332 | def edit_global_perms(self, user_group_id): |
|
303 | def edit_global_perms(self, user_group_id): |
@@ -488,16 +488,4 b' class UsersController(BaseController):' | |||||
488 | category='error') |
|
488 | category='error') | |
489 | return redirect(url('edit_user_global_perms', user_id=user_id)) |
|
489 | return redirect(url('edit_user_global_perms', user_id=user_id)) | |
490 |
|
490 | |||
491 | @HasPermissionAllDecorator('hg.admin') |
|
|||
492 | def edit_perms_summary(self, user_id): |
|
|||
493 | user_id = safe_int(user_id) |
|
|||
494 | c.user = User.get_or_404(user_id) |
|
|||
495 | if c.user.username == User.DEFAULT_USER: |
|
|||
496 | h.flash(_("You can't edit this user"), category='warning') |
|
|||
497 | return redirect(h.route_path('users')) |
|
|||
498 |
|
491 | |||
499 | c.active = 'perms_summary' |
|
|||
500 | c.perm_user = AuthUser(user_id=user_id, ip_addr=self.ip_addr) |
|
|||
501 |
|
||||
502 | return render('admin/users/user_edit.mako') |
|
|||
503 |
|
@@ -72,12 +72,16 b' function registerRCRoutes() {' | |||||
72 | pyroutes.register('edit_user_ips', '/_admin/users/%(user_id)s/edit/ips', ['user_id']); |
|
72 | pyroutes.register('edit_user_ips', '/_admin/users/%(user_id)s/edit/ips', ['user_id']); | |
73 | pyroutes.register('edit_user_ips_add', '/_admin/users/%(user_id)s/edit/ips/new', ['user_id']); |
|
73 | pyroutes.register('edit_user_ips_add', '/_admin/users/%(user_id)s/edit/ips/new', ['user_id']); | |
74 | pyroutes.register('edit_user_ips_delete', '/_admin/users/%(user_id)s/edit/ips/delete', ['user_id']); |
|
74 | pyroutes.register('edit_user_ips_delete', '/_admin/users/%(user_id)s/edit/ips/delete', ['user_id']); | |
|
75 | pyroutes.register('edit_user_perms_summary', '/_admin/users/%(user_id)s/edit/permissions_summary', ['user_id']); | |||
|
76 | pyroutes.register('edit_user_perms_summary_json', '/_admin/users/%(user_id)s/edit/permissions_summary/json', ['user_id']); | |||
75 | pyroutes.register('edit_user_groups_management', '/_admin/users/%(user_id)s/edit/groups_management', ['user_id']); |
|
77 | pyroutes.register('edit_user_groups_management', '/_admin/users/%(user_id)s/edit/groups_management', ['user_id']); | |
76 | pyroutes.register('edit_user_groups_management_updates', '/_admin/users/%(user_id)s/edit/edit_user_groups_management/updates', ['user_id']); |
|
78 | pyroutes.register('edit_user_groups_management_updates', '/_admin/users/%(user_id)s/edit/edit_user_groups_management/updates', ['user_id']); | |
77 | pyroutes.register('edit_user_audit_logs', '/_admin/users/%(user_id)s/edit/audit', ['user_id']); |
|
79 | pyroutes.register('edit_user_audit_logs', '/_admin/users/%(user_id)s/edit/audit', ['user_id']); | |
78 | pyroutes.register('user_groups', '/_admin/user_groups', []); |
|
80 | pyroutes.register('user_groups', '/_admin/user_groups', []); | |
79 | pyroutes.register('user_groups_data', '/_admin/user_groups_data', []); |
|
81 | pyroutes.register('user_groups_data', '/_admin/user_groups_data', []); | |
80 | pyroutes.register('user_group_members_data', '/_admin/user_groups/%(user_group_id)s/members', ['user_group_id']); |
|
82 | pyroutes.register('user_group_members_data', '/_admin/user_groups/%(user_group_id)s/members', ['user_group_id']); | |
|
83 | pyroutes.register('edit_user_group_perms_summary', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary', ['user_group_id']); | |||
|
84 | pyroutes.register('edit_user_group_perms_summary_json', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary/json', ['user_group_id']); | |||
81 | pyroutes.register('channelstream_connect', '/_admin/channelstream/connect', []); |
|
85 | pyroutes.register('channelstream_connect', '/_admin/channelstream/connect', []); | |
82 | pyroutes.register('channelstream_subscribe', '/_admin/channelstream/subscribe', []); |
|
86 | pyroutes.register('channelstream_subscribe', '/_admin/channelstream/subscribe', []); | |
83 | pyroutes.register('channelstream_proxy', '/_channelstream', []); |
|
87 | pyroutes.register('channelstream_proxy', '/_channelstream', []); |
@@ -34,7 +34,7 b'' | |||||
34 | <li class="${'active' if c.active=='perms' else ''}"><a href="${h.url('edit_user_group_perms', user_group_id=c.user_group.users_group_id)}">${_('Permissions')}</a></li> |
|
34 | <li class="${'active' if c.active=='perms' else ''}"><a href="${h.url('edit_user_group_perms', user_group_id=c.user_group.users_group_id)}">${_('Permissions')}</a></li> | |
35 | <li class="${'active' if c.active=='advanced' else ''}"><a href="${h.url('edit_user_group_advanced', user_group_id=c.user_group.users_group_id)}">${_('Advanced')}</a></li> |
|
35 | <li class="${'active' if c.active=='advanced' else ''}"><a href="${h.url('edit_user_group_advanced', user_group_id=c.user_group.users_group_id)}">${_('Advanced')}</a></li> | |
36 | <li class="${'active' if c.active=='global_perms' else ''}"><a href="${h.url('edit_user_group_global_perms', user_group_id=c.user_group.users_group_id)}">${_('Global permissions')}</a></li> |
|
36 | <li class="${'active' if c.active=='global_perms' else ''}"><a href="${h.url('edit_user_group_global_perms', user_group_id=c.user_group.users_group_id)}">${_('Global permissions')}</a></li> | |
37 |
<li class="${'active' if c.active=='perms_summary' else ''}"><a href="${h. |
|
37 | <li class="${'active' if c.active=='perms_summary' else ''}"><a href="${h.route_path('edit_user_group_perms_summary', user_group_id=c.user_group.users_group_id)}">${_('Permissions summary')}</a></li> | |
38 | </ul> |
|
38 | </ul> | |
39 | </div> |
|
39 | </div> | |
40 |
|
40 |
@@ -1,3 +1,3 b'' | |||||
1 | ## permissions overview |
|
1 | ## permissions overview | |
2 | <%namespace name="p" file="/base/perms_summary.mako"/> |
|
2 | <%namespace name="p" file="/base/perms_summary.mako"/> | |
3 | ${p.perms_summary(c.permissions)} |
|
3 | ${p.perms_summary(c.permissions, side_link=h.route_path('edit_user_group_perms_summary_json', user_group_id=c.user_group.users_group_id))} |
@@ -40,7 +40,7 b'' | |||||
40 | <li class="${'active' if c.active in ['ssh_keys','ssh_keys_generate'] else ''}"><a href="${h.route_path('edit_user_ssh_keys', user_id=c.user.user_id)}">${_('SSH Keys')}</a></li> |
|
40 | <li class="${'active' if c.active in ['ssh_keys','ssh_keys_generate'] else ''}"><a href="${h.route_path('edit_user_ssh_keys', user_id=c.user.user_id)}">${_('SSH Keys')}</a></li> | |
41 | <li class="${'active' if c.active=='advanced' else ''}"><a href="${h.url('edit_user_advanced', user_id=c.user.user_id)}">${_('Advanced')}</a></li> |
|
41 | <li class="${'active' if c.active=='advanced' else ''}"><a href="${h.url('edit_user_advanced', user_id=c.user.user_id)}">${_('Advanced')}</a></li> | |
42 | <li class="${'active' if c.active=='global_perms' else ''}"><a href="${h.url('edit_user_global_perms', user_id=c.user.user_id)}">${_('Global permissions')}</a></li> |
|
42 | <li class="${'active' if c.active=='global_perms' else ''}"><a href="${h.url('edit_user_global_perms', user_id=c.user.user_id)}">${_('Global permissions')}</a></li> | |
43 |
<li class="${'active' if c.active=='perms_summary' else ''}"><a href="${h. |
|
43 | <li class="${'active' if c.active=='perms_summary' else ''}"><a href="${h.route_path('edit_user_perms_summary', user_id=c.user.user_id)}">${_('Permissions summary')}</a></li> | |
44 | <li class="${'active' if c.active=='emails' else ''}"><a href="${h.route_path('edit_user_emails', user_id=c.user.user_id)}">${_('Emails')}</a></li> |
|
44 | <li class="${'active' if c.active=='emails' else ''}"><a href="${h.route_path('edit_user_emails', user_id=c.user.user_id)}">${_('Emails')}</a></li> | |
45 | <li class="${'active' if c.active=='ips' else ''}"><a href="${h.route_path('edit_user_ips', user_id=c.user.user_id)}">${_('Ip Whitelist')}</a></li> |
|
45 | <li class="${'active' if c.active=='ips' else ''}"><a href="${h.route_path('edit_user_ips', user_id=c.user.user_id)}">${_('Ip Whitelist')}</a></li> | |
46 | <li class="${'active' if c.active=='groups' else ''}"><a href="${h.route_path('edit_user_groups_management', user_id=c.user.user_id)}">${_('User Groups Management')}</a></li> |
|
46 | <li class="${'active' if c.active=='groups' else ''}"><a href="${h.route_path('edit_user_groups_management', user_id=c.user.user_id)}">${_('User Groups Management')}</a></li> |
@@ -1,3 +1,3 b'' | |||||
1 | ## permissions overview |
|
1 | ## permissions overview | |
2 | <%namespace name="p" file="/base/perms_summary.mako"/> |
|
2 | <%namespace name="p" file="/base/perms_summary.mako"/> | |
3 | ${p.perms_summary(c.perm_user.permissions, show_all=True)} |
|
3 | ${p.perms_summary(c.perm_user.permissions, show_all=True, side_link=h.route_path('edit_user_perms_summary_json', user_id=c.user.user_id))} |
@@ -3,12 +3,17 b'' | |||||
3 | ## <%namespace name="p" file="/base/perms_summary.mako"/> |
|
3 | ## <%namespace name="p" file="/base/perms_summary.mako"/> | |
4 | ## ${p.perms_summary(c.perm_user.permissions)} |
|
4 | ## ${p.perms_summary(c.perm_user.permissions)} | |
5 |
|
5 | |||
6 | <%def name="perms_summary(permissions, show_all=False, actions=True)"> |
|
6 | <%def name="perms_summary(permissions, show_all=False, actions=True, side_link=None)"> | |
7 | <div id="perms" class="table fields"> |
|
7 | <div id="perms" class="table fields"> | |
8 | %for section in sorted(permissions.keys()): |
|
8 | %for section in sorted(permissions.keys()): | |
9 | <div class="panel panel-default"> |
|
9 | <div class="panel panel-default"> | |
10 | <div class="panel-heading"> |
|
10 | <div class="panel-heading"> | |
11 | <h3 class="panel-title">${section.replace("_"," ").capitalize()}</h3> |
|
11 | <h3 class="panel-title">${section.replace("_"," ").capitalize()}</h3> | |
|
12 | % if side_link: | |||
|
13 | <div class="pull-right"> | |||
|
14 | <a href="${side_link}">${_('in JSON format')}</a> | |||
|
15 | </div> | |||
|
16 | % endif | |||
12 | </div> |
|
17 | </div> | |
13 | <div class="panel-body"> |
|
18 | <div class="panel-body"> | |
14 | <div class="perms_section_head field"> |
|
19 | <div class="perms_section_head field"> |
General Comments 0
You need to be logged in to leave comments.
Login now