##// END OF EJS Templates
auth: added @LoginRequired() decorators for user/user_group views....
marcink -
r2001:844b6602 default
parent child Browse files
Show More
@@ -1,256 +1,258 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import logging
22 22 import datetime
23 23
24 24 from pyramid.httpexceptions import HTTPFound
25 25 from pyramid.view import view_config
26 26
27 27 from rhodecode.model.scm import UserGroupList
28 28
29 29 from rhodecode.apps._base import BaseAppView, DataGridAppView
30 30 from rhodecode.lib.auth import (
31 31 LoginRequired, HasPermissionAllDecorator, CSRFRequired, NotAnonymous,
32 32 HasUserGroupPermissionAnyDecorator)
33 33 from rhodecode.lib import helpers as h
34 34 from rhodecode.lib.utils import PartialRenderer
35 35 from rhodecode.lib.utils2 import safe_int, safe_unicode
36 36 from rhodecode.model.user_group import UserGroupModel
37 37 from rhodecode.model.db import (
38 38 joinedload, or_, count, User, UserGroup, UserGroupMember,
39 39 UserGroupRepoToPerm, UserGroupRepoGroupToPerm)
40 40 from rhodecode.model.meta import Session
41 41
42 42 log = logging.getLogger(__name__)
43 43
44 44
45 45 class AdminUserGroupsView(BaseAppView, DataGridAppView):
46 46
47 47 def load_default_context(self):
48 48 c = self._get_local_tmpl_context()
49 49 self._register_global_c(c)
50 50 return c
51 51
52 52 # permission check in data loading of
53 53 # `user_groups_list_data` via UserGroupList
54 @LoginRequired()
54 55 @NotAnonymous()
55 56 @view_config(
56 57 route_name='user_groups', request_method='GET',
57 58 renderer='rhodecode:templates/admin/user_groups/user_groups.mako')
58 59 def user_groups_list(self):
59 60 c = self.load_default_context()
60 61 return self._get_template_context(c)
61 62
62 63 # permission check inside
64 @LoginRequired()
63 65 @NotAnonymous()
64 66 @view_config(
65 67 route_name='user_groups_data', request_method='GET',
66 68 renderer='json_ext', xhr=True)
67 69 def user_groups_list_data(self):
68 70 column_map = {
69 71 'active': 'users_group_active',
70 72 'description': 'user_group_description',
71 73 'members': 'members_total',
72 74 'owner': 'user_username',
73 75 'sync': 'group_data'
74 76 }
75 77 draw, start, limit = self._extract_chunk(self.request)
76 78 search_q, order_by, order_dir = self._extract_ordering(
77 79 self.request, column_map=column_map)
78 80
79 81 _render = PartialRenderer('data_table/_dt_elements.mako')
80 82
81 83 def user_group_name(user_group_id, user_group_name):
82 84 return _render("user_group_name", user_group_id, user_group_name)
83 85
84 86 def user_group_actions(user_group_id, user_group_name):
85 87 return _render("user_group_actions", user_group_id, user_group_name)
86 88
87 89 def user_profile(username):
88 90 return _render('user_profile', username)
89 91
90 92 auth_user_group_list = UserGroupList(
91 93 UserGroup.query().all(), perm_set=['usergroup.admin'])
92 94
93 95 allowed_ids = []
94 96 for user_group in auth_user_group_list:
95 97 allowed_ids.append(user_group.users_group_id)
96 98
97 99 user_groups_data_total_count = UserGroup.query()\
98 100 .filter(UserGroup.users_group_id.in_(allowed_ids))\
99 101 .count()
100 102
101 103 member_count = count(UserGroupMember.user_id)
102 104 base_q = Session.query(
103 105 UserGroup.users_group_name,
104 106 UserGroup.user_group_description,
105 107 UserGroup.users_group_active,
106 108 UserGroup.users_group_id,
107 109 UserGroup.group_data,
108 110 User,
109 111 member_count.label('member_count')
110 112 ) \
111 113 .filter(UserGroup.users_group_id.in_(allowed_ids)) \
112 114 .outerjoin(UserGroupMember) \
113 115 .join(User, User.user_id == UserGroup.user_id) \
114 116 .group_by(UserGroup, User)
115 117
116 118 if search_q:
117 119 like_expression = u'%{}%'.format(safe_unicode(search_q))
118 120 base_q = base_q.filter(or_(
119 121 UserGroup.users_group_name.ilike(like_expression),
120 122 ))
121 123
122 124 user_groups_data_total_filtered_count = base_q.count()
123 125
124 126 if order_by == 'members_total':
125 127 sort_col = member_count
126 128 elif order_by == 'user_username':
127 129 sort_col = User.username
128 130 else:
129 131 sort_col = getattr(UserGroup, order_by, None)
130 132
131 133 if isinstance(sort_col, count) or sort_col:
132 134 if order_dir == 'asc':
133 135 sort_col = sort_col.asc()
134 136 else:
135 137 sort_col = sort_col.desc()
136 138
137 139 base_q = base_q.order_by(sort_col)
138 140 base_q = base_q.offset(start).limit(limit)
139 141
140 142 # authenticated access to user groups
141 143 auth_user_group_list = base_q.all()
142 144
143 145 user_groups_data = []
144 146 for user_gr in auth_user_group_list:
145 147 user_groups_data.append({
146 148 "users_group_name": user_group_name(
147 149 user_gr.users_group_id, h.escape(user_gr.users_group_name)),
148 150 "name_raw": h.escape(user_gr.users_group_name),
149 151 "description": h.escape(user_gr.user_group_description),
150 152 "members": user_gr.member_count,
151 153 # NOTE(marcink): because of advanced query we
152 154 # need to load it like that
153 155 "sync": UserGroup._load_group_data(
154 156 user_gr.group_data).get('extern_type'),
155 157 "active": h.bool2icon(user_gr.users_group_active),
156 158 "owner": user_profile(user_gr.User.username),
157 159 "action": user_group_actions(
158 160 user_gr.users_group_id, user_gr.users_group_name)
159 161 })
160 162
161 163 data = ({
162 164 'draw': draw,
163 165 'data': user_groups_data,
164 166 'recordsTotal': user_groups_data_total_count,
165 167 'recordsFiltered': user_groups_data_total_filtered_count,
166 168 })
167 169
168 170 return data
169 171
170 172 @LoginRequired()
171 173 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
172 174 @view_config(
173 175 route_name='user_group_members_data', request_method='GET',
174 176 renderer='json_ext', xhr=True)
175 177 def user_group_members(self):
176 178 """
177 179 Return members of given user group
178 180 """
179 181 user_group_id = self.request.matchdict['user_group_id']
180 182 user_group = UserGroup.get_or_404(user_group_id)
181 183 group_members_obj = sorted((x.user for x in user_group.members),
182 184 key=lambda u: u.username.lower())
183 185
184 186 group_members = [
185 187 {
186 188 'id': user.user_id,
187 189 'first_name': user.first_name,
188 190 'last_name': user.last_name,
189 191 'username': user.username,
190 192 'icon_link': h.gravatar_url(user.email, 30),
191 193 'value_display': h.person(user.email),
192 194 'value': user.username,
193 195 'value_type': 'user',
194 196 'active': user.active,
195 197 }
196 198 for user in group_members_obj
197 199 ]
198 200
199 201 return {
200 202 'members': group_members
201 203 }
202 204
203 205 def _get_perms_summary(self, user_group_id):
204 206 permissions = {
205 207 'repositories': {},
206 208 'repositories_groups': {},
207 209 }
208 210 ugroup_repo_perms = UserGroupRepoToPerm.query()\
209 211 .options(joinedload(UserGroupRepoToPerm.permission))\
210 212 .options(joinedload(UserGroupRepoToPerm.repository))\
211 213 .filter(UserGroupRepoToPerm.users_group_id == user_group_id)\
212 214 .all()
213 215
214 216 for gr in ugroup_repo_perms:
215 217 permissions['repositories'][gr.repository.repo_name] \
216 218 = gr.permission.permission_name
217 219
218 220 ugroup_group_perms = UserGroupRepoGroupToPerm.query()\
219 221 .options(joinedload(UserGroupRepoGroupToPerm.permission))\
220 222 .options(joinedload(UserGroupRepoGroupToPerm.group))\
221 223 .filter(UserGroupRepoGroupToPerm.users_group_id == user_group_id)\
222 224 .all()
223 225
224 226 for gr in ugroup_group_perms:
225 227 permissions['repositories_groups'][gr.group.group_name] \
226 228 = gr.permission.permission_name
227 229 return permissions
228 230
229 231 @LoginRequired()
230 232 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
231 233 @view_config(
232 234 route_name='edit_user_group_perms_summary', request_method='GET',
233 235 renderer='rhodecode:templates/admin/user_groups/user_group_edit.mako')
234 236 def user_group_perms_summary(self):
235 237 c = self.load_default_context()
236 238
237 239 user_group_id = self.request.matchdict.get('user_group_id')
238 240 c.user_group = UserGroup.get_or_404(user_group_id)
239 241
240 242 c.active = 'perms_summary'
241 243
242 244 c.permissions = self._get_perms_summary(c.user_group.users_group_id)
243 245 return self._get_template_context(c)
244 246
245 247 @LoginRequired()
246 248 @HasUserGroupPermissionAnyDecorator('usergroup.admin')
247 249 @view_config(
248 250 route_name='edit_user_group_perms_summary_json', request_method='GET',
249 251 renderer='json_ext')
250 252 def user_group_perms_summary(self):
251 253 self.load_default_context()
252 254
253 255 user_group_id = self.request.matchdict.get('user_group_id')
254 256 user_group = UserGroup.get_or_404(user_group_id)
255 257
256 258 return self._get_perms_summary(user_group.users_group_id)
@@ -1,670 +1,672 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2016-2017 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 import logging
22 22 import datetime
23 23 import formencode
24 24
25 25 from pyramid.httpexceptions import HTTPFound
26 26 from pyramid.view import view_config
27 27 from sqlalchemy.sql.functions import coalesce
28 28 from sqlalchemy.exc import IntegrityError
29 29
30 30 from rhodecode.apps._base import BaseAppView, DataGridAppView
31 31 from rhodecode.apps.ssh_support import SshKeyFileChangeEvent
32 32 from rhodecode.events import trigger
33 33
34 34 from rhodecode.lib import audit_logger
35 35 from rhodecode.lib.ext_json import json
36 36 from rhodecode.lib.auth import (
37 37 LoginRequired, HasPermissionAllDecorator, CSRFRequired)
38 38 from rhodecode.lib import helpers as h
39 39 from rhodecode.lib.utils2 import safe_int, safe_unicode
40 40 from rhodecode.model.auth_token import AuthTokenModel
41 41 from rhodecode.model.ssh_key import SshKeyModel
42 42 from rhodecode.model.user import UserModel
43 43 from rhodecode.model.user_group import UserGroupModel
44 44 from rhodecode.model.db import (
45 45 or_, User, UserIpMap, UserEmailMap, UserApiKeys, UserSshKeys)
46 46 from rhodecode.model.meta import Session
47 47
48 48 log = logging.getLogger(__name__)
49 49
50 50
51 51 class AdminUsersView(BaseAppView, DataGridAppView):
52 52 ALLOW_SCOPED_TOKENS = False
53 53 """
54 54 This view has alternative version inside EE, if modified please take a look
55 55 in there as well.
56 56 """
57 57
58 58 def load_default_context(self):
59 59 c = self._get_local_tmpl_context()
60 60 c.allow_scoped_tokens = self.ALLOW_SCOPED_TOKENS
61 61 self._register_global_c(c)
62 62 return c
63 63
64 64 def _redirect_for_default_user(self, username):
65 65 _ = self.request.translate
66 66 if username == User.DEFAULT_USER:
67 67 h.flash(_("You can't edit this user"), category='warning')
68 68 # TODO(marcink): redirect to 'users' admin panel once this
69 69 # is a pyramid view
70 70 raise HTTPFound('/')
71 71
72 @LoginRequired()
72 73 @HasPermissionAllDecorator('hg.admin')
73 74 @view_config(
74 75 route_name='users', request_method='GET',
75 76 renderer='rhodecode:templates/admin/users/users.mako')
76 77 def users_list(self):
77 78 c = self.load_default_context()
78 79 return self._get_template_context(c)
79 80
81 @LoginRequired()
80 82 @HasPermissionAllDecorator('hg.admin')
81 83 @view_config(
82 84 # renderer defined below
83 85 route_name='users_data', request_method='GET',
84 86 renderer='json_ext', xhr=True)
85 87 def users_list_data(self):
86 88 column_map = {
87 89 'first_name': 'name',
88 90 'last_name': 'lastname',
89 91 }
90 92 draw, start, limit = self._extract_chunk(self.request)
91 93 search_q, order_by, order_dir = self._extract_ordering(
92 94 self.request, column_map=column_map)
93 95
94 96 _render = self.request.get_partial_renderer(
95 97 'data_table/_dt_elements.mako')
96 98
97 99 def user_actions(user_id, username):
98 100 return _render("user_actions", user_id, username)
99 101
100 102 users_data_total_count = User.query()\
101 103 .filter(User.username != User.DEFAULT_USER) \
102 104 .count()
103 105
104 106 # json generate
105 107 base_q = User.query().filter(User.username != User.DEFAULT_USER)
106 108
107 109 if search_q:
108 110 like_expression = u'%{}%'.format(safe_unicode(search_q))
109 111 base_q = base_q.filter(or_(
110 112 User.username.ilike(like_expression),
111 113 User._email.ilike(like_expression),
112 114 User.name.ilike(like_expression),
113 115 User.lastname.ilike(like_expression),
114 116 ))
115 117
116 118 users_data_total_filtered_count = base_q.count()
117 119
118 120 sort_col = getattr(User, order_by, None)
119 121 if sort_col:
120 122 if order_dir == 'asc':
121 123 # handle null values properly to order by NULL last
122 124 if order_by in ['last_activity']:
123 125 sort_col = coalesce(sort_col, datetime.date.max)
124 126 sort_col = sort_col.asc()
125 127 else:
126 128 # handle null values properly to order by NULL last
127 129 if order_by in ['last_activity']:
128 130 sort_col = coalesce(sort_col, datetime.date.min)
129 131 sort_col = sort_col.desc()
130 132
131 133 base_q = base_q.order_by(sort_col)
132 134 base_q = base_q.offset(start).limit(limit)
133 135
134 136 users_list = base_q.all()
135 137
136 138 users_data = []
137 139 for user in users_list:
138 140 users_data.append({
139 141 "username": h.gravatar_with_user(self.request, user.username),
140 142 "email": user.email,
141 143 "first_name": user.first_name,
142 144 "last_name": user.last_name,
143 145 "last_login": h.format_date(user.last_login),
144 146 "last_activity": h.format_date(user.last_activity),
145 147 "active": h.bool2icon(user.active),
146 148 "active_raw": user.active,
147 149 "admin": h.bool2icon(user.admin),
148 150 "extern_type": user.extern_type,
149 151 "extern_name": user.extern_name,
150 152 "action": user_actions(user.user_id, user.username),
151 153 })
152 154
153 155 data = ({
154 156 'draw': draw,
155 157 'data': users_data,
156 158 'recordsTotal': users_data_total_count,
157 159 'recordsFiltered': users_data_total_filtered_count,
158 160 })
159 161
160 162 return data
161 163
162 164 @LoginRequired()
163 165 @HasPermissionAllDecorator('hg.admin')
164 166 @view_config(
165 167 route_name='edit_user_auth_tokens', request_method='GET',
166 168 renderer='rhodecode:templates/admin/users/user_edit.mako')
167 169 def auth_tokens(self):
168 170 _ = self.request.translate
169 171 c = self.load_default_context()
170 172
171 173 user_id = self.request.matchdict.get('user_id')
172 174 c.user = User.get_or_404(user_id)
173 175 self._redirect_for_default_user(c.user.username)
174 176
175 177 c.active = 'auth_tokens'
176 178
177 179 c.lifetime_values = [
178 180 (str(-1), _('forever')),
179 181 (str(5), _('5 minutes')),
180 182 (str(60), _('1 hour')),
181 183 (str(60 * 24), _('1 day')),
182 184 (str(60 * 24 * 30), _('1 month')),
183 185 ]
184 186 c.lifetime_options = [(c.lifetime_values, _("Lifetime"))]
185 187 c.role_values = [
186 188 (x, AuthTokenModel.cls._get_role_name(x))
187 189 for x in AuthTokenModel.cls.ROLES]
188 190 c.role_options = [(c.role_values, _("Role"))]
189 191 c.user_auth_tokens = AuthTokenModel().get_auth_tokens(
190 192 c.user.user_id, show_expired=True)
191 193 return self._get_template_context(c)
192 194
193 195 def maybe_attach_token_scope(self, token):
194 196 # implemented in EE edition
195 197 pass
196 198
197 199 @LoginRequired()
198 200 @HasPermissionAllDecorator('hg.admin')
199 201 @CSRFRequired()
200 202 @view_config(
201 203 route_name='edit_user_auth_tokens_add', request_method='POST')
202 204 def auth_tokens_add(self):
203 205 _ = self.request.translate
204 206 c = self.load_default_context()
205 207
206 208 user_id = self.request.matchdict.get('user_id')
207 209 c.user = User.get_or_404(user_id)
208 210
209 211 self._redirect_for_default_user(c.user.username)
210 212
211 213 user_data = c.user.get_api_data()
212 214 lifetime = safe_int(self.request.POST.get('lifetime'), -1)
213 215 description = self.request.POST.get('description')
214 216 role = self.request.POST.get('role')
215 217
216 218 token = AuthTokenModel().create(
217 219 c.user.user_id, description, lifetime, role)
218 220 token_data = token.get_api_data()
219 221
220 222 self.maybe_attach_token_scope(token)
221 223 audit_logger.store_web(
222 224 'user.edit.token.add', action_data={
223 225 'data': {'token': token_data, 'user': user_data}},
224 226 user=self._rhodecode_user, )
225 227 Session().commit()
226 228
227 229 h.flash(_("Auth token successfully created"), category='success')
228 230 return HTTPFound(h.route_path('edit_user_auth_tokens', user_id=user_id))
229 231
230 232 @LoginRequired()
231 233 @HasPermissionAllDecorator('hg.admin')
232 234 @CSRFRequired()
233 235 @view_config(
234 236 route_name='edit_user_auth_tokens_delete', request_method='POST')
235 237 def auth_tokens_delete(self):
236 238 _ = self.request.translate
237 239 c = self.load_default_context()
238 240
239 241 user_id = self.request.matchdict.get('user_id')
240 242 c.user = User.get_or_404(user_id)
241 243 self._redirect_for_default_user(c.user.username)
242 244 user_data = c.user.get_api_data()
243 245
244 246 del_auth_token = self.request.POST.get('del_auth_token')
245 247
246 248 if del_auth_token:
247 249 token = UserApiKeys.get_or_404(del_auth_token)
248 250 token_data = token.get_api_data()
249 251
250 252 AuthTokenModel().delete(del_auth_token, c.user.user_id)
251 253 audit_logger.store_web(
252 254 'user.edit.token.delete', action_data={
253 255 'data': {'token': token_data, 'user': user_data}},
254 256 user=self._rhodecode_user,)
255 257 Session().commit()
256 258 h.flash(_("Auth token successfully deleted"), category='success')
257 259
258 260 return HTTPFound(h.route_path('edit_user_auth_tokens', user_id=user_id))
259 261
260 262 @LoginRequired()
261 263 @HasPermissionAllDecorator('hg.admin')
262 264 @view_config(
263 265 route_name='edit_user_ssh_keys', request_method='GET',
264 266 renderer='rhodecode:templates/admin/users/user_edit.mako')
265 267 def ssh_keys(self):
266 268 _ = self.request.translate
267 269 c = self.load_default_context()
268 270
269 271 user_id = self.request.matchdict.get('user_id')
270 272 c.user = User.get_or_404(user_id)
271 273 self._redirect_for_default_user(c.user.username)
272 274
273 275 c.active = 'ssh_keys'
274 276 c.default_key = self.request.GET.get('default_key')
275 277 c.user_ssh_keys = SshKeyModel().get_ssh_keys(c.user.user_id)
276 278 return self._get_template_context(c)
277 279
278 280 @LoginRequired()
279 281 @HasPermissionAllDecorator('hg.admin')
280 282 @view_config(
281 283 route_name='edit_user_ssh_keys_generate_keypair', request_method='GET',
282 284 renderer='rhodecode:templates/admin/users/user_edit.mako')
283 285 def ssh_keys_generate_keypair(self):
284 286 _ = self.request.translate
285 287 c = self.load_default_context()
286 288
287 289 user_id = self.request.matchdict.get('user_id')
288 290 c.user = User.get_or_404(user_id)
289 291 self._redirect_for_default_user(c.user.username)
290 292
291 293 c.active = 'ssh_keys_generate'
292 294 comment = 'RhodeCode-SSH {}'.format(c.user.email or '')
293 295 c.private, c.public = SshKeyModel().generate_keypair(comment=comment)
294 296
295 297 return self._get_template_context(c)
296 298
297 299 @LoginRequired()
298 300 @HasPermissionAllDecorator('hg.admin')
299 301 @CSRFRequired()
300 302 @view_config(
301 303 route_name='edit_user_ssh_keys_add', request_method='POST')
302 304 def ssh_keys_add(self):
303 305 _ = self.request.translate
304 306 c = self.load_default_context()
305 307
306 308 user_id = self.request.matchdict.get('user_id')
307 309 c.user = User.get_or_404(user_id)
308 310
309 311 self._redirect_for_default_user(c.user.username)
310 312
311 313 user_data = c.user.get_api_data()
312 314 key_data = self.request.POST.get('key_data')
313 315 description = self.request.POST.get('description')
314 316
315 317 try:
316 318 if not key_data:
317 319 raise ValueError('Please add a valid public key')
318 320
319 321 key = SshKeyModel().parse_key(key_data.strip())
320 322 fingerprint = key.hash_md5()
321 323
322 324 ssh_key = SshKeyModel().create(
323 325 c.user.user_id, fingerprint, key_data, description)
324 326 ssh_key_data = ssh_key.get_api_data()
325 327
326 328 audit_logger.store_web(
327 329 'user.edit.ssh_key.add', action_data={
328 330 'data': {'ssh_key': ssh_key_data, 'user': user_data}},
329 331 user=self._rhodecode_user, )
330 332 Session().commit()
331 333
332 334 # Trigger an event on change of keys.
333 335 trigger(SshKeyFileChangeEvent(), self.request.registry)
334 336
335 337 h.flash(_("Ssh Key successfully created"), category='success')
336 338
337 339 except IntegrityError:
338 340 log.exception("Exception during ssh key saving")
339 341 h.flash(_('An error occurred during ssh key saving: {}').format(
340 342 'Such key already exists, please use a different one'),
341 343 category='error')
342 344 except Exception as e:
343 345 log.exception("Exception during ssh key saving")
344 346 h.flash(_('An error occurred during ssh key saving: {}').format(e),
345 347 category='error')
346 348
347 349 return HTTPFound(
348 350 h.route_path('edit_user_ssh_keys', user_id=user_id))
349 351
350 352 @LoginRequired()
351 353 @HasPermissionAllDecorator('hg.admin')
352 354 @CSRFRequired()
353 355 @view_config(
354 356 route_name='edit_user_ssh_keys_delete', request_method='POST')
355 357 def ssh_keys_delete(self):
356 358 _ = self.request.translate
357 359 c = self.load_default_context()
358 360
359 361 user_id = self.request.matchdict.get('user_id')
360 362 c.user = User.get_or_404(user_id)
361 363 self._redirect_for_default_user(c.user.username)
362 364 user_data = c.user.get_api_data()
363 365
364 366 del_ssh_key = self.request.POST.get('del_ssh_key')
365 367
366 368 if del_ssh_key:
367 369 ssh_key = UserSshKeys.get_or_404(del_ssh_key)
368 370 ssh_key_data = ssh_key.get_api_data()
369 371
370 372 SshKeyModel().delete(del_ssh_key, c.user.user_id)
371 373 audit_logger.store_web(
372 374 'user.edit.ssh_key.delete', action_data={
373 375 'data': {'ssh_key': ssh_key_data, 'user': user_data}},
374 376 user=self._rhodecode_user,)
375 377 Session().commit()
376 378 # Trigger an event on change of keys.
377 379 trigger(SshKeyFileChangeEvent(), self.request.registry)
378 380 h.flash(_("Ssh key successfully deleted"), category='success')
379 381
380 382 return HTTPFound(h.route_path('edit_user_ssh_keys', user_id=user_id))
381 383
382 384 @LoginRequired()
383 385 @HasPermissionAllDecorator('hg.admin')
384 386 @view_config(
385 387 route_name='edit_user_emails', request_method='GET',
386 388 renderer='rhodecode:templates/admin/users/user_edit.mako')
387 389 def emails(self):
388 390 _ = self.request.translate
389 391 c = self.load_default_context()
390 392
391 393 user_id = self.request.matchdict.get('user_id')
392 394 c.user = User.get_or_404(user_id)
393 395 self._redirect_for_default_user(c.user.username)
394 396
395 397 c.active = 'emails'
396 398 c.user_email_map = UserEmailMap.query() \
397 399 .filter(UserEmailMap.user == c.user).all()
398 400
399 401 return self._get_template_context(c)
400 402
401 403 @LoginRequired()
402 404 @HasPermissionAllDecorator('hg.admin')
403 405 @CSRFRequired()
404 406 @view_config(
405 407 route_name='edit_user_emails_add', request_method='POST')
406 408 def emails_add(self):
407 409 _ = self.request.translate
408 410 c = self.load_default_context()
409 411
410 412 user_id = self.request.matchdict.get('user_id')
411 413 c.user = User.get_or_404(user_id)
412 414 self._redirect_for_default_user(c.user.username)
413 415
414 416 email = self.request.POST.get('new_email')
415 417 user_data = c.user.get_api_data()
416 418 try:
417 419 UserModel().add_extra_email(c.user.user_id, email)
418 420 audit_logger.store_web(
419 421 'user.edit.email.add', action_data={'email': email, 'user': user_data},
420 422 user=self._rhodecode_user)
421 423 Session().commit()
422 424 h.flash(_("Added new email address `%s` for user account") % email,
423 425 category='success')
424 426 except formencode.Invalid as error:
425 427 h.flash(h.escape(error.error_dict['email']), category='error')
426 428 except Exception:
427 429 log.exception("Exception during email saving")
428 430 h.flash(_('An error occurred during email saving'),
429 431 category='error')
430 432 raise HTTPFound(h.route_path('edit_user_emails', user_id=user_id))
431 433
432 434 @LoginRequired()
433 435 @HasPermissionAllDecorator('hg.admin')
434 436 @CSRFRequired()
435 437 @view_config(
436 438 route_name='edit_user_emails_delete', request_method='POST')
437 439 def emails_delete(self):
438 440 _ = self.request.translate
439 441 c = self.load_default_context()
440 442
441 443 user_id = self.request.matchdict.get('user_id')
442 444 c.user = User.get_or_404(user_id)
443 445 self._redirect_for_default_user(c.user.username)
444 446
445 447 email_id = self.request.POST.get('del_email_id')
446 448 user_model = UserModel()
447 449
448 450 email = UserEmailMap.query().get(email_id).email
449 451 user_data = c.user.get_api_data()
450 452 user_model.delete_extra_email(c.user.user_id, email_id)
451 453 audit_logger.store_web(
452 454 'user.edit.email.delete', action_data={'email': email, 'user': user_data},
453 455 user=self._rhodecode_user)
454 456 Session().commit()
455 457 h.flash(_("Removed email address from user account"),
456 458 category='success')
457 459 raise HTTPFound(h.route_path('edit_user_emails', user_id=user_id))
458 460
459 461 @LoginRequired()
460 462 @HasPermissionAllDecorator('hg.admin')
461 463 @view_config(
462 464 route_name='edit_user_ips', request_method='GET',
463 465 renderer='rhodecode:templates/admin/users/user_edit.mako')
464 466 def ips(self):
465 467 _ = self.request.translate
466 468 c = self.load_default_context()
467 469
468 470 user_id = self.request.matchdict.get('user_id')
469 471 c.user = User.get_or_404(user_id)
470 472 self._redirect_for_default_user(c.user.username)
471 473
472 474 c.active = 'ips'
473 475 c.user_ip_map = UserIpMap.query() \
474 476 .filter(UserIpMap.user == c.user).all()
475 477
476 478 c.inherit_default_ips = c.user.inherit_default_permissions
477 479 c.default_user_ip_map = UserIpMap.query() \
478 480 .filter(UserIpMap.user == User.get_default_user()).all()
479 481
480 482 return self._get_template_context(c)
481 483
482 484 @LoginRequired()
483 485 @HasPermissionAllDecorator('hg.admin')
484 486 @CSRFRequired()
485 487 @view_config(
486 488 route_name='edit_user_ips_add', request_method='POST')
487 489 def ips_add(self):
488 490 _ = self.request.translate
489 491 c = self.load_default_context()
490 492
491 493 user_id = self.request.matchdict.get('user_id')
492 494 c.user = User.get_or_404(user_id)
493 495 # NOTE(marcink): this view is allowed for default users, as we can
494 496 # edit their IP white list
495 497
496 498 user_model = UserModel()
497 499 desc = self.request.POST.get('description')
498 500 try:
499 501 ip_list = user_model.parse_ip_range(
500 502 self.request.POST.get('new_ip'))
501 503 except Exception as e:
502 504 ip_list = []
503 505 log.exception("Exception during ip saving")
504 506 h.flash(_('An error occurred during ip saving:%s' % (e,)),
505 507 category='error')
506 508 added = []
507 509 user_data = c.user.get_api_data()
508 510 for ip in ip_list:
509 511 try:
510 512 user_model.add_extra_ip(c.user.user_id, ip, desc)
511 513 audit_logger.store_web(
512 514 'user.edit.ip.add', action_data={'ip': ip, 'user': user_data},
513 515 user=self._rhodecode_user)
514 516 Session().commit()
515 517 added.append(ip)
516 518 except formencode.Invalid as error:
517 519 msg = error.error_dict['ip']
518 520 h.flash(msg, category='error')
519 521 except Exception:
520 522 log.exception("Exception during ip saving")
521 523 h.flash(_('An error occurred during ip saving'),
522 524 category='error')
523 525 if added:
524 526 h.flash(
525 527 _("Added ips %s to user whitelist") % (', '.join(ip_list), ),
526 528 category='success')
527 529 if 'default_user' in self.request.POST:
528 530 # case for editing global IP list we do it for 'DEFAULT' user
529 531 raise HTTPFound(h.route_path('admin_permissions_ips'))
530 532 raise HTTPFound(h.route_path('edit_user_ips', user_id=user_id))
531 533
532 534 @LoginRequired()
533 535 @HasPermissionAllDecorator('hg.admin')
534 536 @CSRFRequired()
535 537 @view_config(
536 538 route_name='edit_user_ips_delete', request_method='POST')
537 539 def ips_delete(self):
538 540 _ = self.request.translate
539 541 c = self.load_default_context()
540 542
541 543 user_id = self.request.matchdict.get('user_id')
542 544 c.user = User.get_or_404(user_id)
543 545 # NOTE(marcink): this view is allowed for default users, as we can
544 546 # edit their IP white list
545 547
546 548 ip_id = self.request.POST.get('del_ip_id')
547 549 user_model = UserModel()
548 550 user_data = c.user.get_api_data()
549 551 ip = UserIpMap.query().get(ip_id).ip_addr
550 552 user_model.delete_extra_ip(c.user.user_id, ip_id)
551 553 audit_logger.store_web(
552 554 'user.edit.ip.delete', action_data={'ip': ip, 'user': user_data},
553 555 user=self._rhodecode_user)
554 556 Session().commit()
555 557 h.flash(_("Removed ip address from user whitelist"), category='success')
556 558
557 559 if 'default_user' in self.request.POST:
558 560 # case for editing global IP list we do it for 'DEFAULT' user
559 561 raise HTTPFound(h.route_path('admin_permissions_ips'))
560 562 raise HTTPFound(h.route_path('edit_user_ips', user_id=user_id))
561 563
562 564 @LoginRequired()
563 565 @HasPermissionAllDecorator('hg.admin')
564 566 @view_config(
565 567 route_name='edit_user_groups_management', request_method='GET',
566 568 renderer='rhodecode:templates/admin/users/user_edit.mako')
567 569 def groups_management(self):
568 570 c = self.load_default_context()
569 571
570 572 user_id = self.request.matchdict.get('user_id')
571 573 c.user = User.get_or_404(user_id)
572 574 c.data = c.user.group_member
573 575 self._redirect_for_default_user(c.user.username)
574 576 groups = [UserGroupModel.get_user_groups_as_dict(group.users_group)
575 577 for group in c.user.group_member]
576 578 c.groups = json.dumps(groups)
577 579 c.active = 'groups'
578 580
579 581 return self._get_template_context(c)
580 582
581 583 @LoginRequired()
582 584 @HasPermissionAllDecorator('hg.admin')
583 585 @CSRFRequired()
584 586 @view_config(
585 587 route_name='edit_user_groups_management_updates', request_method='POST')
586 588 def groups_management_updates(self):
587 589 _ = self.request.translate
588 590 c = self.load_default_context()
589 591
590 592 user_id = self.request.matchdict.get('user_id')
591 593 c.user = User.get_or_404(user_id)
592 594 self._redirect_for_default_user(c.user.username)
593 595
594 596 users_groups = set(self.request.POST.getall('users_group_id'))
595 597 users_groups_model = []
596 598
597 599 for ugid in users_groups:
598 600 users_groups_model.append(UserGroupModel().get_group(safe_int(ugid)))
599 601 user_group_model = UserGroupModel()
600 602 user_group_model.change_groups(c.user, users_groups_model)
601 603
602 604 Session().commit()
603 605 c.active = 'user_groups_management'
604 606 h.flash(_("Groups successfully changed"), category='success')
605 607
606 608 return HTTPFound(h.route_path(
607 609 'edit_user_groups_management', user_id=user_id))
608 610
609 611 @LoginRequired()
610 612 @HasPermissionAllDecorator('hg.admin')
611 613 @view_config(
612 614 route_name='edit_user_audit_logs', request_method='GET',
613 615 renderer='rhodecode:templates/admin/users/user_edit.mako')
614 616 def user_audit_logs(self):
615 617 _ = self.request.translate
616 618 c = self.load_default_context()
617 619
618 620 user_id = self.request.matchdict.get('user_id')
619 621 c.user = User.get_or_404(user_id)
620 622 self._redirect_for_default_user(c.user.username)
621 623 c.active = 'audit'
622 624
623 625 p = safe_int(self.request.GET.get('page', 1), 1)
624 626
625 627 filter_term = self.request.GET.get('filter')
626 628 user_log = UserModel().get_user_log(c.user, filter_term)
627 629
628 630 def url_generator(**kw):
629 631 if filter_term:
630 632 kw['filter'] = filter_term
631 633 return self.request.current_route_path(_query=kw)
632 634
633 635 c.audit_logs = h.Page(
634 636 user_log, page=p, items_per_page=10, url=url_generator)
635 637 c.filter_term = filter_term
636 638 return self._get_template_context(c)
637 639
638 640 @LoginRequired()
639 641 @HasPermissionAllDecorator('hg.admin')
640 642 @view_config(
641 643 route_name='edit_user_perms_summary', request_method='GET',
642 644 renderer='rhodecode:templates/admin/users/user_edit.mako')
643 645 def user_perms_summary(self):
644 646 _ = self.request.translate
645 647 c = self.load_default_context()
646 648
647 649 user_id = self.request.matchdict.get('user_id')
648 650 c.user = User.get_or_404(user_id)
649 651 self._redirect_for_default_user(c.user.username)
650 652
651 653 c.active = 'perms_summary'
652 654 c.perm_user = c.user.AuthUser(ip_addr=self.request.remote_addr)
653 655
654 656 return self._get_template_context(c)
655 657
656 658 @LoginRequired()
657 659 @HasPermissionAllDecorator('hg.admin')
658 660 @view_config(
659 661 route_name='edit_user_perms_summary_json', request_method='GET',
660 662 renderer='json_ext')
661 663 def user_perms_summary_json(self):
662 664 self.load_default_context()
663 665
664 666 user_id = self.request.matchdict.get('user_id')
665 667 user = User.get_or_404(user_id)
666 668 self._redirect_for_default_user(user.username)
667 669
668 670 perm_user = user.AuthUser(ip_addr=self.request.remote_addr)
669 671
670 672 return perm_user.permissions
General Comments 0
You need to be logged in to leave comments. Login now