##// END OF EJS Templates
bookmarks: cache fetching of bookmarks since this is quite expensive query to make with joinedload on repos/repo groups.
marcink -
r4143:d9dc1c76 default
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

@@ -1,762 +1,764 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2016-2019 RhodeCode GmbH
3 # Copyright (C) 2016-2019 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 import logging
21 import logging
22 import datetime
22 import datetime
23 import string
23 import string
24
24
25 import formencode
25 import formencode
26 import formencode.htmlfill
26 import formencode.htmlfill
27 import peppercorn
27 import peppercorn
28 from pyramid.httpexceptions import HTTPFound
28 from pyramid.httpexceptions import HTTPFound
29 from pyramid.view import view_config
29 from pyramid.view import view_config
30
30
31 from rhodecode.apps._base import BaseAppView, DataGridAppView
31 from rhodecode.apps._base import BaseAppView, DataGridAppView
32 from rhodecode import forms
32 from rhodecode import forms
33 from rhodecode.lib import helpers as h
33 from rhodecode.lib import helpers as h
34 from rhodecode.lib import audit_logger
34 from rhodecode.lib import audit_logger
35 from rhodecode.lib.ext_json import json
35 from rhodecode.lib.ext_json import json
36 from rhodecode.lib.auth import LoginRequired, NotAnonymous, CSRFRequired, \
36 from rhodecode.lib.auth import LoginRequired, NotAnonymous, CSRFRequired, \
37 HasRepoPermissionAny, HasRepoGroupPermissionAny
37 HasRepoPermissionAny, HasRepoGroupPermissionAny
38 from rhodecode.lib.channelstream import (
38 from rhodecode.lib.channelstream import (
39 channelstream_request, ChannelstreamException)
39 channelstream_request, ChannelstreamException)
40 from rhodecode.lib.utils2 import safe_int, md5, str2bool
40 from rhodecode.lib.utils2 import safe_int, md5, str2bool
41 from rhodecode.model.auth_token import AuthTokenModel
41 from rhodecode.model.auth_token import AuthTokenModel
42 from rhodecode.model.comment import CommentsModel
42 from rhodecode.model.comment import CommentsModel
43 from rhodecode.model.db import (
43 from rhodecode.model.db import (
44 IntegrityError, joinedload,
44 IntegrityError, joinedload,
45 Repository, UserEmailMap, UserApiKeys, UserFollowing,
45 Repository, UserEmailMap, UserApiKeys, UserFollowing,
46 PullRequest, UserBookmark, RepoGroup)
46 PullRequest, UserBookmark, RepoGroup)
47 from rhodecode.model.meta import Session
47 from rhodecode.model.meta import Session
48 from rhodecode.model.pull_request import PullRequestModel
48 from rhodecode.model.pull_request import PullRequestModel
49 from rhodecode.model.scm import RepoList
49 from rhodecode.model.scm import RepoList
50 from rhodecode.model.user import UserModel
50 from rhodecode.model.user import UserModel
51 from rhodecode.model.repo import RepoModel
51 from rhodecode.model.repo import RepoModel
52 from rhodecode.model.user_group import UserGroupModel
52 from rhodecode.model.user_group import UserGroupModel
53 from rhodecode.model.validation_schema.schemas import user_schema
53 from rhodecode.model.validation_schema.schemas import user_schema
54
54
55 log = logging.getLogger(__name__)
55 log = logging.getLogger(__name__)
56
56
57
57
58 class MyAccountView(BaseAppView, DataGridAppView):
58 class MyAccountView(BaseAppView, DataGridAppView):
59 ALLOW_SCOPED_TOKENS = False
59 ALLOW_SCOPED_TOKENS = False
60 """
60 """
61 This view has alternative version inside EE, if modified please take a look
61 This view has alternative version inside EE, if modified please take a look
62 in there as well.
62 in there as well.
63 """
63 """
64
64
65 def load_default_context(self):
65 def load_default_context(self):
66 c = self._get_local_tmpl_context()
66 c = self._get_local_tmpl_context()
67 c.user = c.auth_user.get_instance()
67 c.user = c.auth_user.get_instance()
68 c.allow_scoped_tokens = self.ALLOW_SCOPED_TOKENS
68 c.allow_scoped_tokens = self.ALLOW_SCOPED_TOKENS
69
69
70 return c
70 return c
71
71
72 @LoginRequired()
72 @LoginRequired()
73 @NotAnonymous()
73 @NotAnonymous()
74 @view_config(
74 @view_config(
75 route_name='my_account_profile', request_method='GET',
75 route_name='my_account_profile', request_method='GET',
76 renderer='rhodecode:templates/admin/my_account/my_account.mako')
76 renderer='rhodecode:templates/admin/my_account/my_account.mako')
77 def my_account_profile(self):
77 def my_account_profile(self):
78 c = self.load_default_context()
78 c = self.load_default_context()
79 c.active = 'profile'
79 c.active = 'profile'
80 return self._get_template_context(c)
80 return self._get_template_context(c)
81
81
82 @LoginRequired()
82 @LoginRequired()
83 @NotAnonymous()
83 @NotAnonymous()
84 @view_config(
84 @view_config(
85 route_name='my_account_password', request_method='GET',
85 route_name='my_account_password', request_method='GET',
86 renderer='rhodecode:templates/admin/my_account/my_account.mako')
86 renderer='rhodecode:templates/admin/my_account/my_account.mako')
87 def my_account_password(self):
87 def my_account_password(self):
88 c = self.load_default_context()
88 c = self.load_default_context()
89 c.active = 'password'
89 c.active = 'password'
90 c.extern_type = c.user.extern_type
90 c.extern_type = c.user.extern_type
91
91
92 schema = user_schema.ChangePasswordSchema().bind(
92 schema = user_schema.ChangePasswordSchema().bind(
93 username=c.user.username)
93 username=c.user.username)
94
94
95 form = forms.Form(
95 form = forms.Form(
96 schema,
96 schema,
97 action=h.route_path('my_account_password_update'),
97 action=h.route_path('my_account_password_update'),
98 buttons=(forms.buttons.save, forms.buttons.reset))
98 buttons=(forms.buttons.save, forms.buttons.reset))
99
99
100 c.form = form
100 c.form = form
101 return self._get_template_context(c)
101 return self._get_template_context(c)
102
102
103 @LoginRequired()
103 @LoginRequired()
104 @NotAnonymous()
104 @NotAnonymous()
105 @CSRFRequired()
105 @CSRFRequired()
106 @view_config(
106 @view_config(
107 route_name='my_account_password_update', request_method='POST',
107 route_name='my_account_password_update', request_method='POST',
108 renderer='rhodecode:templates/admin/my_account/my_account.mako')
108 renderer='rhodecode:templates/admin/my_account/my_account.mako')
109 def my_account_password_update(self):
109 def my_account_password_update(self):
110 _ = self.request.translate
110 _ = self.request.translate
111 c = self.load_default_context()
111 c = self.load_default_context()
112 c.active = 'password'
112 c.active = 'password'
113 c.extern_type = c.user.extern_type
113 c.extern_type = c.user.extern_type
114
114
115 schema = user_schema.ChangePasswordSchema().bind(
115 schema = user_schema.ChangePasswordSchema().bind(
116 username=c.user.username)
116 username=c.user.username)
117
117
118 form = forms.Form(
118 form = forms.Form(
119 schema, buttons=(forms.buttons.save, forms.buttons.reset))
119 schema, buttons=(forms.buttons.save, forms.buttons.reset))
120
120
121 if c.extern_type != 'rhodecode':
121 if c.extern_type != 'rhodecode':
122 raise HTTPFound(self.request.route_path('my_account_password'))
122 raise HTTPFound(self.request.route_path('my_account_password'))
123
123
124 controls = self.request.POST.items()
124 controls = self.request.POST.items()
125 try:
125 try:
126 valid_data = form.validate(controls)
126 valid_data = form.validate(controls)
127 UserModel().update_user(c.user.user_id, **valid_data)
127 UserModel().update_user(c.user.user_id, **valid_data)
128 c.user.update_userdata(force_password_change=False)
128 c.user.update_userdata(force_password_change=False)
129 Session().commit()
129 Session().commit()
130 except forms.ValidationFailure as e:
130 except forms.ValidationFailure as e:
131 c.form = e
131 c.form = e
132 return self._get_template_context(c)
132 return self._get_template_context(c)
133
133
134 except Exception:
134 except Exception:
135 log.exception("Exception updating password")
135 log.exception("Exception updating password")
136 h.flash(_('Error occurred during update of user password'),
136 h.flash(_('Error occurred during update of user password'),
137 category='error')
137 category='error')
138 else:
138 else:
139 instance = c.auth_user.get_instance()
139 instance = c.auth_user.get_instance()
140 self.session.setdefault('rhodecode_user', {}).update(
140 self.session.setdefault('rhodecode_user', {}).update(
141 {'password': md5(instance.password)})
141 {'password': md5(instance.password)})
142 self.session.save()
142 self.session.save()
143 h.flash(_("Successfully updated password"), category='success')
143 h.flash(_("Successfully updated password"), category='success')
144
144
145 raise HTTPFound(self.request.route_path('my_account_password'))
145 raise HTTPFound(self.request.route_path('my_account_password'))
146
146
147 @LoginRequired()
147 @LoginRequired()
148 @NotAnonymous()
148 @NotAnonymous()
149 @view_config(
149 @view_config(
150 route_name='my_account_auth_tokens', request_method='GET',
150 route_name='my_account_auth_tokens', request_method='GET',
151 renderer='rhodecode:templates/admin/my_account/my_account.mako')
151 renderer='rhodecode:templates/admin/my_account/my_account.mako')
152 def my_account_auth_tokens(self):
152 def my_account_auth_tokens(self):
153 _ = self.request.translate
153 _ = self.request.translate
154
154
155 c = self.load_default_context()
155 c = self.load_default_context()
156 c.active = 'auth_tokens'
156 c.active = 'auth_tokens'
157 c.lifetime_values = AuthTokenModel.get_lifetime_values(translator=_)
157 c.lifetime_values = AuthTokenModel.get_lifetime_values(translator=_)
158 c.role_values = [
158 c.role_values = [
159 (x, AuthTokenModel.cls._get_role_name(x))
159 (x, AuthTokenModel.cls._get_role_name(x))
160 for x in AuthTokenModel.cls.ROLES]
160 for x in AuthTokenModel.cls.ROLES]
161 c.role_options = [(c.role_values, _("Role"))]
161 c.role_options = [(c.role_values, _("Role"))]
162 c.user_auth_tokens = AuthTokenModel().get_auth_tokens(
162 c.user_auth_tokens = AuthTokenModel().get_auth_tokens(
163 c.user.user_id, show_expired=True)
163 c.user.user_id, show_expired=True)
164 c.role_vcs = AuthTokenModel.cls.ROLE_VCS
164 c.role_vcs = AuthTokenModel.cls.ROLE_VCS
165 return self._get_template_context(c)
165 return self._get_template_context(c)
166
166
167 def maybe_attach_token_scope(self, token):
167 def maybe_attach_token_scope(self, token):
168 # implemented in EE edition
168 # implemented in EE edition
169 pass
169 pass
170
170
171 @LoginRequired()
171 @LoginRequired()
172 @NotAnonymous()
172 @NotAnonymous()
173 @CSRFRequired()
173 @CSRFRequired()
174 @view_config(
174 @view_config(
175 route_name='my_account_auth_tokens_add', request_method='POST',)
175 route_name='my_account_auth_tokens_add', request_method='POST',)
176 def my_account_auth_tokens_add(self):
176 def my_account_auth_tokens_add(self):
177 _ = self.request.translate
177 _ = self.request.translate
178 c = self.load_default_context()
178 c = self.load_default_context()
179
179
180 lifetime = safe_int(self.request.POST.get('lifetime'), -1)
180 lifetime = safe_int(self.request.POST.get('lifetime'), -1)
181 description = self.request.POST.get('description')
181 description = self.request.POST.get('description')
182 role = self.request.POST.get('role')
182 role = self.request.POST.get('role')
183
183
184 token = UserModel().add_auth_token(
184 token = UserModel().add_auth_token(
185 user=c.user.user_id,
185 user=c.user.user_id,
186 lifetime_minutes=lifetime, role=role, description=description,
186 lifetime_minutes=lifetime, role=role, description=description,
187 scope_callback=self.maybe_attach_token_scope)
187 scope_callback=self.maybe_attach_token_scope)
188 token_data = token.get_api_data()
188 token_data = token.get_api_data()
189
189
190 audit_logger.store_web(
190 audit_logger.store_web(
191 'user.edit.token.add', action_data={
191 'user.edit.token.add', action_data={
192 'data': {'token': token_data, 'user': 'self'}},
192 'data': {'token': token_data, 'user': 'self'}},
193 user=self._rhodecode_user, )
193 user=self._rhodecode_user, )
194 Session().commit()
194 Session().commit()
195
195
196 h.flash(_("Auth token successfully created"), category='success')
196 h.flash(_("Auth token successfully created"), category='success')
197 return HTTPFound(h.route_path('my_account_auth_tokens'))
197 return HTTPFound(h.route_path('my_account_auth_tokens'))
198
198
199 @LoginRequired()
199 @LoginRequired()
200 @NotAnonymous()
200 @NotAnonymous()
201 @CSRFRequired()
201 @CSRFRequired()
202 @view_config(
202 @view_config(
203 route_name='my_account_auth_tokens_delete', request_method='POST')
203 route_name='my_account_auth_tokens_delete', request_method='POST')
204 def my_account_auth_tokens_delete(self):
204 def my_account_auth_tokens_delete(self):
205 _ = self.request.translate
205 _ = self.request.translate
206 c = self.load_default_context()
206 c = self.load_default_context()
207
207
208 del_auth_token = self.request.POST.get('del_auth_token')
208 del_auth_token = self.request.POST.get('del_auth_token')
209
209
210 if del_auth_token:
210 if del_auth_token:
211 token = UserApiKeys.get_or_404(del_auth_token)
211 token = UserApiKeys.get_or_404(del_auth_token)
212 token_data = token.get_api_data()
212 token_data = token.get_api_data()
213
213
214 AuthTokenModel().delete(del_auth_token, c.user.user_id)
214 AuthTokenModel().delete(del_auth_token, c.user.user_id)
215 audit_logger.store_web(
215 audit_logger.store_web(
216 'user.edit.token.delete', action_data={
216 'user.edit.token.delete', action_data={
217 'data': {'token': token_data, 'user': 'self'}},
217 'data': {'token': token_data, 'user': 'self'}},
218 user=self._rhodecode_user,)
218 user=self._rhodecode_user,)
219 Session().commit()
219 Session().commit()
220 h.flash(_("Auth token successfully deleted"), category='success')
220 h.flash(_("Auth token successfully deleted"), category='success')
221
221
222 return HTTPFound(h.route_path('my_account_auth_tokens'))
222 return HTTPFound(h.route_path('my_account_auth_tokens'))
223
223
224 @LoginRequired()
224 @LoginRequired()
225 @NotAnonymous()
225 @NotAnonymous()
226 @view_config(
226 @view_config(
227 route_name='my_account_emails', request_method='GET',
227 route_name='my_account_emails', request_method='GET',
228 renderer='rhodecode:templates/admin/my_account/my_account.mako')
228 renderer='rhodecode:templates/admin/my_account/my_account.mako')
229 def my_account_emails(self):
229 def my_account_emails(self):
230 _ = self.request.translate
230 _ = self.request.translate
231
231
232 c = self.load_default_context()
232 c = self.load_default_context()
233 c.active = 'emails'
233 c.active = 'emails'
234
234
235 c.user_email_map = UserEmailMap.query()\
235 c.user_email_map = UserEmailMap.query()\
236 .filter(UserEmailMap.user == c.user).all()
236 .filter(UserEmailMap.user == c.user).all()
237
237
238 schema = user_schema.AddEmailSchema().bind(
238 schema = user_schema.AddEmailSchema().bind(
239 username=c.user.username, user_emails=c.user.emails)
239 username=c.user.username, user_emails=c.user.emails)
240
240
241 form = forms.RcForm(schema,
241 form = forms.RcForm(schema,
242 action=h.route_path('my_account_emails_add'),
242 action=h.route_path('my_account_emails_add'),
243 buttons=(forms.buttons.save, forms.buttons.reset))
243 buttons=(forms.buttons.save, forms.buttons.reset))
244
244
245 c.form = form
245 c.form = form
246 return self._get_template_context(c)
246 return self._get_template_context(c)
247
247
248 @LoginRequired()
248 @LoginRequired()
249 @NotAnonymous()
249 @NotAnonymous()
250 @CSRFRequired()
250 @CSRFRequired()
251 @view_config(
251 @view_config(
252 route_name='my_account_emails_add', request_method='POST',
252 route_name='my_account_emails_add', request_method='POST',
253 renderer='rhodecode:templates/admin/my_account/my_account.mako')
253 renderer='rhodecode:templates/admin/my_account/my_account.mako')
254 def my_account_emails_add(self):
254 def my_account_emails_add(self):
255 _ = self.request.translate
255 _ = self.request.translate
256 c = self.load_default_context()
256 c = self.load_default_context()
257 c.active = 'emails'
257 c.active = 'emails'
258
258
259 schema = user_schema.AddEmailSchema().bind(
259 schema = user_schema.AddEmailSchema().bind(
260 username=c.user.username, user_emails=c.user.emails)
260 username=c.user.username, user_emails=c.user.emails)
261
261
262 form = forms.RcForm(
262 form = forms.RcForm(
263 schema, action=h.route_path('my_account_emails_add'),
263 schema, action=h.route_path('my_account_emails_add'),
264 buttons=(forms.buttons.save, forms.buttons.reset))
264 buttons=(forms.buttons.save, forms.buttons.reset))
265
265
266 controls = self.request.POST.items()
266 controls = self.request.POST.items()
267 try:
267 try:
268 valid_data = form.validate(controls)
268 valid_data = form.validate(controls)
269 UserModel().add_extra_email(c.user.user_id, valid_data['email'])
269 UserModel().add_extra_email(c.user.user_id, valid_data['email'])
270 audit_logger.store_web(
270 audit_logger.store_web(
271 'user.edit.email.add', action_data={
271 'user.edit.email.add', action_data={
272 'data': {'email': valid_data['email'], 'user': 'self'}},
272 'data': {'email': valid_data['email'], 'user': 'self'}},
273 user=self._rhodecode_user,)
273 user=self._rhodecode_user,)
274 Session().commit()
274 Session().commit()
275 except formencode.Invalid as error:
275 except formencode.Invalid as error:
276 h.flash(h.escape(error.error_dict['email']), category='error')
276 h.flash(h.escape(error.error_dict['email']), category='error')
277 except forms.ValidationFailure as e:
277 except forms.ValidationFailure as e:
278 c.user_email_map = UserEmailMap.query() \
278 c.user_email_map = UserEmailMap.query() \
279 .filter(UserEmailMap.user == c.user).all()
279 .filter(UserEmailMap.user == c.user).all()
280 c.form = e
280 c.form = e
281 return self._get_template_context(c)
281 return self._get_template_context(c)
282 except Exception:
282 except Exception:
283 log.exception("Exception adding email")
283 log.exception("Exception adding email")
284 h.flash(_('Error occurred during adding email'),
284 h.flash(_('Error occurred during adding email'),
285 category='error')
285 category='error')
286 else:
286 else:
287 h.flash(_("Successfully added email"), category='success')
287 h.flash(_("Successfully added email"), category='success')
288
288
289 raise HTTPFound(self.request.route_path('my_account_emails'))
289 raise HTTPFound(self.request.route_path('my_account_emails'))
290
290
291 @LoginRequired()
291 @LoginRequired()
292 @NotAnonymous()
292 @NotAnonymous()
293 @CSRFRequired()
293 @CSRFRequired()
294 @view_config(
294 @view_config(
295 route_name='my_account_emails_delete', request_method='POST')
295 route_name='my_account_emails_delete', request_method='POST')
296 def my_account_emails_delete(self):
296 def my_account_emails_delete(self):
297 _ = self.request.translate
297 _ = self.request.translate
298 c = self.load_default_context()
298 c = self.load_default_context()
299
299
300 del_email_id = self.request.POST.get('del_email_id')
300 del_email_id = self.request.POST.get('del_email_id')
301 if del_email_id:
301 if del_email_id:
302 email = UserEmailMap.get_or_404(del_email_id).email
302 email = UserEmailMap.get_or_404(del_email_id).email
303 UserModel().delete_extra_email(c.user.user_id, del_email_id)
303 UserModel().delete_extra_email(c.user.user_id, del_email_id)
304 audit_logger.store_web(
304 audit_logger.store_web(
305 'user.edit.email.delete', action_data={
305 'user.edit.email.delete', action_data={
306 'data': {'email': email, 'user': 'self'}},
306 'data': {'email': email, 'user': 'self'}},
307 user=self._rhodecode_user,)
307 user=self._rhodecode_user,)
308 Session().commit()
308 Session().commit()
309 h.flash(_("Email successfully deleted"),
309 h.flash(_("Email successfully deleted"),
310 category='success')
310 category='success')
311 return HTTPFound(h.route_path('my_account_emails'))
311 return HTTPFound(h.route_path('my_account_emails'))
312
312
313 @LoginRequired()
313 @LoginRequired()
314 @NotAnonymous()
314 @NotAnonymous()
315 @CSRFRequired()
315 @CSRFRequired()
316 @view_config(
316 @view_config(
317 route_name='my_account_notifications_test_channelstream',
317 route_name='my_account_notifications_test_channelstream',
318 request_method='POST', renderer='json_ext')
318 request_method='POST', renderer='json_ext')
319 def my_account_notifications_test_channelstream(self):
319 def my_account_notifications_test_channelstream(self):
320 message = 'Test message sent via Channelstream by user: {}, on {}'.format(
320 message = 'Test message sent via Channelstream by user: {}, on {}'.format(
321 self._rhodecode_user.username, datetime.datetime.now())
321 self._rhodecode_user.username, datetime.datetime.now())
322 payload = {
322 payload = {
323 # 'channel': 'broadcast',
323 # 'channel': 'broadcast',
324 'type': 'message',
324 'type': 'message',
325 'timestamp': datetime.datetime.utcnow(),
325 'timestamp': datetime.datetime.utcnow(),
326 'user': 'system',
326 'user': 'system',
327 'pm_users': [self._rhodecode_user.username],
327 'pm_users': [self._rhodecode_user.username],
328 'message': {
328 'message': {
329 'message': message,
329 'message': message,
330 'level': 'info',
330 'level': 'info',
331 'topic': '/notifications'
331 'topic': '/notifications'
332 }
332 }
333 }
333 }
334
334
335 registry = self.request.registry
335 registry = self.request.registry
336 rhodecode_plugins = getattr(registry, 'rhodecode_plugins', {})
336 rhodecode_plugins = getattr(registry, 'rhodecode_plugins', {})
337 channelstream_config = rhodecode_plugins.get('channelstream', {})
337 channelstream_config = rhodecode_plugins.get('channelstream', {})
338
338
339 try:
339 try:
340 channelstream_request(channelstream_config, [payload], '/message')
340 channelstream_request(channelstream_config, [payload], '/message')
341 except ChannelstreamException as e:
341 except ChannelstreamException as e:
342 log.exception('Failed to send channelstream data')
342 log.exception('Failed to send channelstream data')
343 return {"response": 'ERROR: {}'.format(e.__class__.__name__)}
343 return {"response": 'ERROR: {}'.format(e.__class__.__name__)}
344 return {"response": 'Channelstream data sent. '
344 return {"response": 'Channelstream data sent. '
345 'You should see a new live message now.'}
345 'You should see a new live message now.'}
346
346
347 def _load_my_repos_data(self, watched=False):
347 def _load_my_repos_data(self, watched=False):
348 if watched:
348 if watched:
349 admin = False
349 admin = False
350 follows_repos = Session().query(UserFollowing)\
350 follows_repos = Session().query(UserFollowing)\
351 .filter(UserFollowing.user_id == self._rhodecode_user.user_id)\
351 .filter(UserFollowing.user_id == self._rhodecode_user.user_id)\
352 .options(joinedload(UserFollowing.follows_repository))\
352 .options(joinedload(UserFollowing.follows_repository))\
353 .all()
353 .all()
354 repo_list = [x.follows_repository for x in follows_repos]
354 repo_list = [x.follows_repository for x in follows_repos]
355 else:
355 else:
356 admin = True
356 admin = True
357 repo_list = Repository.get_all_repos(
357 repo_list = Repository.get_all_repos(
358 user_id=self._rhodecode_user.user_id)
358 user_id=self._rhodecode_user.user_id)
359 repo_list = RepoList(repo_list, perm_set=[
359 repo_list = RepoList(repo_list, perm_set=[
360 'repository.read', 'repository.write', 'repository.admin'])
360 'repository.read', 'repository.write', 'repository.admin'])
361
361
362 repos_data = RepoModel().get_repos_as_dict(
362 repos_data = RepoModel().get_repos_as_dict(
363 repo_list=repo_list, admin=admin, short_name=False)
363 repo_list=repo_list, admin=admin, short_name=False)
364 # json used to render the grid
364 # json used to render the grid
365 return json.dumps(repos_data)
365 return json.dumps(repos_data)
366
366
367 @LoginRequired()
367 @LoginRequired()
368 @NotAnonymous()
368 @NotAnonymous()
369 @view_config(
369 @view_config(
370 route_name='my_account_repos', request_method='GET',
370 route_name='my_account_repos', request_method='GET',
371 renderer='rhodecode:templates/admin/my_account/my_account.mako')
371 renderer='rhodecode:templates/admin/my_account/my_account.mako')
372 def my_account_repos(self):
372 def my_account_repos(self):
373 c = self.load_default_context()
373 c = self.load_default_context()
374 c.active = 'repos'
374 c.active = 'repos'
375
375
376 # json used to render the grid
376 # json used to render the grid
377 c.data = self._load_my_repos_data()
377 c.data = self._load_my_repos_data()
378 return self._get_template_context(c)
378 return self._get_template_context(c)
379
379
380 @LoginRequired()
380 @LoginRequired()
381 @NotAnonymous()
381 @NotAnonymous()
382 @view_config(
382 @view_config(
383 route_name='my_account_watched', request_method='GET',
383 route_name='my_account_watched', request_method='GET',
384 renderer='rhodecode:templates/admin/my_account/my_account.mako')
384 renderer='rhodecode:templates/admin/my_account/my_account.mako')
385 def my_account_watched(self):
385 def my_account_watched(self):
386 c = self.load_default_context()
386 c = self.load_default_context()
387 c.active = 'watched'
387 c.active = 'watched'
388
388
389 # json used to render the grid
389 # json used to render the grid
390 c.data = self._load_my_repos_data(watched=True)
390 c.data = self._load_my_repos_data(watched=True)
391 return self._get_template_context(c)
391 return self._get_template_context(c)
392
392
393 @LoginRequired()
393 @LoginRequired()
394 @NotAnonymous()
394 @NotAnonymous()
395 @view_config(
395 @view_config(
396 route_name='my_account_bookmarks', request_method='GET',
396 route_name='my_account_bookmarks', request_method='GET',
397 renderer='rhodecode:templates/admin/my_account/my_account.mako')
397 renderer='rhodecode:templates/admin/my_account/my_account.mako')
398 def my_account_bookmarks(self):
398 def my_account_bookmarks(self):
399 c = self.load_default_context()
399 c = self.load_default_context()
400 c.active = 'bookmarks'
400 c.active = 'bookmarks'
401 c.bookmark_items = UserBookmark.get_bookmarks_for_user(
402 self._rhodecode_db_user.user_id, cache=False)
401 return self._get_template_context(c)
403 return self._get_template_context(c)
402
404
403 def _process_bookmark_entry(self, entry, user_id):
405 def _process_bookmark_entry(self, entry, user_id):
404 position = safe_int(entry.get('position'))
406 position = safe_int(entry.get('position'))
405 cur_position = safe_int(entry.get('cur_position'))
407 cur_position = safe_int(entry.get('cur_position'))
406 if position is None or cur_position is None:
408 if position is None:
407 return
409 return
408
410
409 # check if this is an existing entry
411 # check if this is an existing entry
410 is_new = False
412 is_new = False
411 db_entry = UserBookmark().get_by_position_for_user(cur_position, user_id)
413 db_entry = UserBookmark().get_by_position_for_user(cur_position, user_id)
412
414
413 if db_entry and str2bool(entry.get('remove')):
415 if db_entry and str2bool(entry.get('remove')):
414 log.debug('Marked bookmark %s for deletion', db_entry)
416 log.debug('Marked bookmark %s for deletion', db_entry)
415 Session().delete(db_entry)
417 Session().delete(db_entry)
416 return
418 return
417
419
418 if not db_entry:
420 if not db_entry:
419 # new
421 # new
420 db_entry = UserBookmark()
422 db_entry = UserBookmark()
421 is_new = True
423 is_new = True
422
424
423 should_save = False
425 should_save = False
424 default_redirect_url = ''
426 default_redirect_url = ''
425
427
426 # save repo
428 # save repo
427 if entry.get('bookmark_repo') and safe_int(entry.get('bookmark_repo')):
429 if entry.get('bookmark_repo') and safe_int(entry.get('bookmark_repo')):
428 repo = Repository.get(entry['bookmark_repo'])
430 repo = Repository.get(entry['bookmark_repo'])
429 perm_check = HasRepoPermissionAny(
431 perm_check = HasRepoPermissionAny(
430 'repository.read', 'repository.write', 'repository.admin')
432 'repository.read', 'repository.write', 'repository.admin')
431 if repo and perm_check(repo_name=repo.repo_name):
433 if repo and perm_check(repo_name=repo.repo_name):
432 db_entry.repository = repo
434 db_entry.repository = repo
433 should_save = True
435 should_save = True
434 default_redirect_url = '${repo_url}'
436 default_redirect_url = '${repo_url}'
435 # save repo group
437 # save repo group
436 elif entry.get('bookmark_repo_group') and safe_int(entry.get('bookmark_repo_group')):
438 elif entry.get('bookmark_repo_group') and safe_int(entry.get('bookmark_repo_group')):
437 repo_group = RepoGroup.get(entry['bookmark_repo_group'])
439 repo_group = RepoGroup.get(entry['bookmark_repo_group'])
438 perm_check = HasRepoGroupPermissionAny(
440 perm_check = HasRepoGroupPermissionAny(
439 'group.read', 'group.write', 'group.admin')
441 'group.read', 'group.write', 'group.admin')
440
442
441 if repo_group and perm_check(group_name=repo_group.group_name):
443 if repo_group and perm_check(group_name=repo_group.group_name):
442 db_entry.repository_group = repo_group
444 db_entry.repository_group = repo_group
443 should_save = True
445 should_save = True
444 default_redirect_url = '${repo_group_url}'
446 default_redirect_url = '${repo_group_url}'
445 # save generic info
447 # save generic info
446 elif entry.get('title') and entry.get('redirect_url'):
448 elif entry.get('title') and entry.get('redirect_url'):
447 should_save = True
449 should_save = True
448
450
449 if should_save:
451 if should_save:
450 # mark user and position
452 # mark user and position
451 db_entry.user_id = user_id
453 db_entry.user_id = user_id
452 db_entry.position = position
454 db_entry.position = position
453 db_entry.title = entry.get('title')
455 db_entry.title = entry.get('title')
454 db_entry.redirect_url = entry.get('redirect_url') or default_redirect_url
456 db_entry.redirect_url = entry.get('redirect_url') or default_redirect_url
455 log.debug('Saving bookmark %s, new:%s', db_entry, is_new)
457 log.debug('Saving bookmark %s, new:%s', db_entry, is_new)
456
458
457 Session().add(db_entry)
459 Session().add(db_entry)
458
460
459 @LoginRequired()
461 @LoginRequired()
460 @NotAnonymous()
462 @NotAnonymous()
461 @CSRFRequired()
463 @CSRFRequired()
462 @view_config(
464 @view_config(
463 route_name='my_account_bookmarks_update', request_method='POST')
465 route_name='my_account_bookmarks_update', request_method='POST')
464 def my_account_bookmarks_update(self):
466 def my_account_bookmarks_update(self):
465 _ = self.request.translate
467 _ = self.request.translate
466 c = self.load_default_context()
468 c = self.load_default_context()
467 c.active = 'bookmarks'
469 c.active = 'bookmarks'
468
470
469 controls = peppercorn.parse(self.request.POST.items())
471 controls = peppercorn.parse(self.request.POST.items())
470 user_id = c.user.user_id
472 user_id = c.user.user_id
471
473
472 # validate positions
474 # validate positions
473 positions = {}
475 positions = {}
474 for entry in controls.get('bookmarks', []):
476 for entry in controls.get('bookmarks', []):
475 position = safe_int(entry['position'])
477 position = safe_int(entry['position'])
476 if position is None:
478 if position is None:
477 continue
479 continue
478
480
479 if position in positions:
481 if position in positions:
480 h.flash(_("Position {} is defined twice. "
482 h.flash(_("Position {} is defined twice. "
481 "Please correct this error.").format(position), category='error')
483 "Please correct this error.").format(position), category='error')
482 return HTTPFound(h.route_path('my_account_bookmarks'))
484 return HTTPFound(h.route_path('my_account_bookmarks'))
483
485
484 entry['position'] = position
486 entry['position'] = position
485 entry['cur_position'] = safe_int(entry.get('cur_position'))
487 entry['cur_position'] = safe_int(entry.get('cur_position'))
486 positions[position] = entry
488 positions[position] = entry
487
489
488 try:
490 try:
489 for entry in positions.values():
491 for entry in positions.values():
490 self._process_bookmark_entry(entry, user_id)
492 self._process_bookmark_entry(entry, user_id)
491
493
492 Session().commit()
494 Session().commit()
493 h.flash(_("Update Bookmarks"), category='success')
495 h.flash(_("Update Bookmarks"), category='success')
494 except IntegrityError:
496 except IntegrityError:
495 h.flash(_("Failed to update bookmarks. "
497 h.flash(_("Failed to update bookmarks. "
496 "Make sure an unique position is used."), category='error')
498 "Make sure an unique position is used."), category='error')
497
499
498 return HTTPFound(h.route_path('my_account_bookmarks'))
500 return HTTPFound(h.route_path('my_account_bookmarks'))
499
501
500 @LoginRequired()
502 @LoginRequired()
501 @NotAnonymous()
503 @NotAnonymous()
502 @view_config(
504 @view_config(
503 route_name='my_account_goto_bookmark', request_method='GET',
505 route_name='my_account_goto_bookmark', request_method='GET',
504 renderer='rhodecode:templates/admin/my_account/my_account.mako')
506 renderer='rhodecode:templates/admin/my_account/my_account.mako')
505 def my_account_goto_bookmark(self):
507 def my_account_goto_bookmark(self):
506
508
507 bookmark_id = self.request.matchdict['bookmark_id']
509 bookmark_id = self.request.matchdict['bookmark_id']
508 user_bookmark = UserBookmark().query()\
510 user_bookmark = UserBookmark().query()\
509 .filter(UserBookmark.user_id == self.request.user.user_id) \
511 .filter(UserBookmark.user_id == self.request.user.user_id) \
510 .filter(UserBookmark.position == bookmark_id).scalar()
512 .filter(UserBookmark.position == bookmark_id).scalar()
511
513
512 redirect_url = h.route_path('my_account_bookmarks')
514 redirect_url = h.route_path('my_account_bookmarks')
513 if not user_bookmark:
515 if not user_bookmark:
514 raise HTTPFound(redirect_url)
516 raise HTTPFound(redirect_url)
515
517
516 # repository set
518 # repository set
517 if user_bookmark.repository:
519 if user_bookmark.repository:
518 repo_name = user_bookmark.repository.repo_name
520 repo_name = user_bookmark.repository.repo_name
519 base_redirect_url = h.route_path(
521 base_redirect_url = h.route_path(
520 'repo_summary', repo_name=repo_name)
522 'repo_summary', repo_name=repo_name)
521 if user_bookmark.redirect_url and \
523 if user_bookmark.redirect_url and \
522 '${repo_url}' in user_bookmark.redirect_url:
524 '${repo_url}' in user_bookmark.redirect_url:
523 redirect_url = string.Template(user_bookmark.redirect_url)\
525 redirect_url = string.Template(user_bookmark.redirect_url)\
524 .safe_substitute({'repo_url': base_redirect_url})
526 .safe_substitute({'repo_url': base_redirect_url})
525 else:
527 else:
526 redirect_url = base_redirect_url
528 redirect_url = base_redirect_url
527 # repository group set
529 # repository group set
528 elif user_bookmark.repository_group:
530 elif user_bookmark.repository_group:
529 repo_group_name = user_bookmark.repository_group.group_name
531 repo_group_name = user_bookmark.repository_group.group_name
530 base_redirect_url = h.route_path(
532 base_redirect_url = h.route_path(
531 'repo_group_home', repo_group_name=repo_group_name)
533 'repo_group_home', repo_group_name=repo_group_name)
532 if user_bookmark.redirect_url and \
534 if user_bookmark.redirect_url and \
533 '${repo_group_url}' in user_bookmark.redirect_url:
535 '${repo_group_url}' in user_bookmark.redirect_url:
534 redirect_url = string.Template(user_bookmark.redirect_url)\
536 redirect_url = string.Template(user_bookmark.redirect_url)\
535 .safe_substitute({'repo_group_url': base_redirect_url})
537 .safe_substitute({'repo_group_url': base_redirect_url})
536 else:
538 else:
537 redirect_url = base_redirect_url
539 redirect_url = base_redirect_url
538 # custom URL set
540 # custom URL set
539 elif user_bookmark.redirect_url:
541 elif user_bookmark.redirect_url:
540 server_url = h.route_url('home').rstrip('/')
542 server_url = h.route_url('home').rstrip('/')
541 redirect_url = string.Template(user_bookmark.redirect_url) \
543 redirect_url = string.Template(user_bookmark.redirect_url) \
542 .safe_substitute({'server_url': server_url})
544 .safe_substitute({'server_url': server_url})
543
545
544 log.debug('Redirecting bookmark %s to %s', user_bookmark, redirect_url)
546 log.debug('Redirecting bookmark %s to %s', user_bookmark, redirect_url)
545 raise HTTPFound(redirect_url)
547 raise HTTPFound(redirect_url)
546
548
547 @LoginRequired()
549 @LoginRequired()
548 @NotAnonymous()
550 @NotAnonymous()
549 @view_config(
551 @view_config(
550 route_name='my_account_perms', request_method='GET',
552 route_name='my_account_perms', request_method='GET',
551 renderer='rhodecode:templates/admin/my_account/my_account.mako')
553 renderer='rhodecode:templates/admin/my_account/my_account.mako')
552 def my_account_perms(self):
554 def my_account_perms(self):
553 c = self.load_default_context()
555 c = self.load_default_context()
554 c.active = 'perms'
556 c.active = 'perms'
555
557
556 c.perm_user = c.auth_user
558 c.perm_user = c.auth_user
557 return self._get_template_context(c)
559 return self._get_template_context(c)
558
560
559 @LoginRequired()
561 @LoginRequired()
560 @NotAnonymous()
562 @NotAnonymous()
561 @view_config(
563 @view_config(
562 route_name='my_account_notifications', request_method='GET',
564 route_name='my_account_notifications', request_method='GET',
563 renderer='rhodecode:templates/admin/my_account/my_account.mako')
565 renderer='rhodecode:templates/admin/my_account/my_account.mako')
564 def my_notifications(self):
566 def my_notifications(self):
565 c = self.load_default_context()
567 c = self.load_default_context()
566 c.active = 'notifications'
568 c.active = 'notifications'
567
569
568 return self._get_template_context(c)
570 return self._get_template_context(c)
569
571
570 @LoginRequired()
572 @LoginRequired()
571 @NotAnonymous()
573 @NotAnonymous()
572 @CSRFRequired()
574 @CSRFRequired()
573 @view_config(
575 @view_config(
574 route_name='my_account_notifications_toggle_visibility',
576 route_name='my_account_notifications_toggle_visibility',
575 request_method='POST', renderer='json_ext')
577 request_method='POST', renderer='json_ext')
576 def my_notifications_toggle_visibility(self):
578 def my_notifications_toggle_visibility(self):
577 user = self._rhodecode_db_user
579 user = self._rhodecode_db_user
578 new_status = not user.user_data.get('notification_status', True)
580 new_status = not user.user_data.get('notification_status', True)
579 user.update_userdata(notification_status=new_status)
581 user.update_userdata(notification_status=new_status)
580 Session().commit()
582 Session().commit()
581 return user.user_data['notification_status']
583 return user.user_data['notification_status']
582
584
583 @LoginRequired()
585 @LoginRequired()
584 @NotAnonymous()
586 @NotAnonymous()
585 @view_config(
587 @view_config(
586 route_name='my_account_edit',
588 route_name='my_account_edit',
587 request_method='GET',
589 request_method='GET',
588 renderer='rhodecode:templates/admin/my_account/my_account.mako')
590 renderer='rhodecode:templates/admin/my_account/my_account.mako')
589 def my_account_edit(self):
591 def my_account_edit(self):
590 c = self.load_default_context()
592 c = self.load_default_context()
591 c.active = 'profile_edit'
593 c.active = 'profile_edit'
592 c.extern_type = c.user.extern_type
594 c.extern_type = c.user.extern_type
593 c.extern_name = c.user.extern_name
595 c.extern_name = c.user.extern_name
594
596
595 schema = user_schema.UserProfileSchema().bind(
597 schema = user_schema.UserProfileSchema().bind(
596 username=c.user.username, user_emails=c.user.emails)
598 username=c.user.username, user_emails=c.user.emails)
597 appstruct = {
599 appstruct = {
598 'username': c.user.username,
600 'username': c.user.username,
599 'email': c.user.email,
601 'email': c.user.email,
600 'firstname': c.user.firstname,
602 'firstname': c.user.firstname,
601 'lastname': c.user.lastname,
603 'lastname': c.user.lastname,
602 'description': c.user.description,
604 'description': c.user.description,
603 }
605 }
604 c.form = forms.RcForm(
606 c.form = forms.RcForm(
605 schema, appstruct=appstruct,
607 schema, appstruct=appstruct,
606 action=h.route_path('my_account_update'),
608 action=h.route_path('my_account_update'),
607 buttons=(forms.buttons.save, forms.buttons.reset))
609 buttons=(forms.buttons.save, forms.buttons.reset))
608
610
609 return self._get_template_context(c)
611 return self._get_template_context(c)
610
612
611 @LoginRequired()
613 @LoginRequired()
612 @NotAnonymous()
614 @NotAnonymous()
613 @CSRFRequired()
615 @CSRFRequired()
614 @view_config(
616 @view_config(
615 route_name='my_account_update',
617 route_name='my_account_update',
616 request_method='POST',
618 request_method='POST',
617 renderer='rhodecode:templates/admin/my_account/my_account.mako')
619 renderer='rhodecode:templates/admin/my_account/my_account.mako')
618 def my_account_update(self):
620 def my_account_update(self):
619 _ = self.request.translate
621 _ = self.request.translate
620 c = self.load_default_context()
622 c = self.load_default_context()
621 c.active = 'profile_edit'
623 c.active = 'profile_edit'
622 c.perm_user = c.auth_user
624 c.perm_user = c.auth_user
623 c.extern_type = c.user.extern_type
625 c.extern_type = c.user.extern_type
624 c.extern_name = c.user.extern_name
626 c.extern_name = c.user.extern_name
625
627
626 schema = user_schema.UserProfileSchema().bind(
628 schema = user_schema.UserProfileSchema().bind(
627 username=c.user.username, user_emails=c.user.emails)
629 username=c.user.username, user_emails=c.user.emails)
628 form = forms.RcForm(
630 form = forms.RcForm(
629 schema, buttons=(forms.buttons.save, forms.buttons.reset))
631 schema, buttons=(forms.buttons.save, forms.buttons.reset))
630
632
631 controls = self.request.POST.items()
633 controls = self.request.POST.items()
632 try:
634 try:
633 valid_data = form.validate(controls)
635 valid_data = form.validate(controls)
634 skip_attrs = ['admin', 'active', 'extern_type', 'extern_name',
636 skip_attrs = ['admin', 'active', 'extern_type', 'extern_name',
635 'new_password', 'password_confirmation']
637 'new_password', 'password_confirmation']
636 if c.extern_type != "rhodecode":
638 if c.extern_type != "rhodecode":
637 # forbid updating username for external accounts
639 # forbid updating username for external accounts
638 skip_attrs.append('username')
640 skip_attrs.append('username')
639 old_email = c.user.email
641 old_email = c.user.email
640 UserModel().update_user(
642 UserModel().update_user(
641 self._rhodecode_user.user_id, skip_attrs=skip_attrs,
643 self._rhodecode_user.user_id, skip_attrs=skip_attrs,
642 **valid_data)
644 **valid_data)
643 if old_email != valid_data['email']:
645 if old_email != valid_data['email']:
644 old = UserEmailMap.query() \
646 old = UserEmailMap.query() \
645 .filter(UserEmailMap.user == c.user).filter(UserEmailMap.email == valid_data['email']).first()
647 .filter(UserEmailMap.user == c.user).filter(UserEmailMap.email == valid_data['email']).first()
646 old.email = old_email
648 old.email = old_email
647 h.flash(_('Your account was updated successfully'), category='success')
649 h.flash(_('Your account was updated successfully'), category='success')
648 Session().commit()
650 Session().commit()
649 except forms.ValidationFailure as e:
651 except forms.ValidationFailure as e:
650 c.form = e
652 c.form = e
651 return self._get_template_context(c)
653 return self._get_template_context(c)
652 except Exception:
654 except Exception:
653 log.exception("Exception updating user")
655 log.exception("Exception updating user")
654 h.flash(_('Error occurred during update of user'),
656 h.flash(_('Error occurred during update of user'),
655 category='error')
657 category='error')
656 raise HTTPFound(h.route_path('my_account_profile'))
658 raise HTTPFound(h.route_path('my_account_profile'))
657
659
658 def _get_pull_requests_list(self, statuses):
660 def _get_pull_requests_list(self, statuses):
659 draw, start, limit = self._extract_chunk(self.request)
661 draw, start, limit = self._extract_chunk(self.request)
660 search_q, order_by, order_dir = self._extract_ordering(self.request)
662 search_q, order_by, order_dir = self._extract_ordering(self.request)
661 _render = self.request.get_partial_renderer(
663 _render = self.request.get_partial_renderer(
662 'rhodecode:templates/data_table/_dt_elements.mako')
664 'rhodecode:templates/data_table/_dt_elements.mako')
663
665
664 pull_requests = PullRequestModel().get_im_participating_in(
666 pull_requests = PullRequestModel().get_im_participating_in(
665 user_id=self._rhodecode_user.user_id,
667 user_id=self._rhodecode_user.user_id,
666 statuses=statuses,
668 statuses=statuses,
667 offset=start, length=limit, order_by=order_by,
669 offset=start, length=limit, order_by=order_by,
668 order_dir=order_dir)
670 order_dir=order_dir)
669
671
670 pull_requests_total_count = PullRequestModel().count_im_participating_in(
672 pull_requests_total_count = PullRequestModel().count_im_participating_in(
671 user_id=self._rhodecode_user.user_id, statuses=statuses)
673 user_id=self._rhodecode_user.user_id, statuses=statuses)
672
674
673 data = []
675 data = []
674 comments_model = CommentsModel()
676 comments_model = CommentsModel()
675 for pr in pull_requests:
677 for pr in pull_requests:
676 repo_id = pr.target_repo_id
678 repo_id = pr.target_repo_id
677 comments = comments_model.get_all_comments(
679 comments = comments_model.get_all_comments(
678 repo_id, pull_request=pr)
680 repo_id, pull_request=pr)
679 owned = pr.user_id == self._rhodecode_user.user_id
681 owned = pr.user_id == self._rhodecode_user.user_id
680
682
681 data.append({
683 data.append({
682 'target_repo': _render('pullrequest_target_repo',
684 'target_repo': _render('pullrequest_target_repo',
683 pr.target_repo.repo_name),
685 pr.target_repo.repo_name),
684 'name': _render('pullrequest_name',
686 'name': _render('pullrequest_name',
685 pr.pull_request_id, pr.pull_request_state,
687 pr.pull_request_id, pr.pull_request_state,
686 pr.work_in_progress, pr.target_repo.repo_name,
688 pr.work_in_progress, pr.target_repo.repo_name,
687 short=True),
689 short=True),
688 'name_raw': pr.pull_request_id,
690 'name_raw': pr.pull_request_id,
689 'status': _render('pullrequest_status',
691 'status': _render('pullrequest_status',
690 pr.calculated_review_status()),
692 pr.calculated_review_status()),
691 'title': _render('pullrequest_title', pr.title, pr.description),
693 'title': _render('pullrequest_title', pr.title, pr.description),
692 'description': h.escape(pr.description),
694 'description': h.escape(pr.description),
693 'updated_on': _render('pullrequest_updated_on',
695 'updated_on': _render('pullrequest_updated_on',
694 h.datetime_to_time(pr.updated_on)),
696 h.datetime_to_time(pr.updated_on)),
695 'updated_on_raw': h.datetime_to_time(pr.updated_on),
697 'updated_on_raw': h.datetime_to_time(pr.updated_on),
696 'created_on': _render('pullrequest_updated_on',
698 'created_on': _render('pullrequest_updated_on',
697 h.datetime_to_time(pr.created_on)),
699 h.datetime_to_time(pr.created_on)),
698 'created_on_raw': h.datetime_to_time(pr.created_on),
700 'created_on_raw': h.datetime_to_time(pr.created_on),
699 'state': pr.pull_request_state,
701 'state': pr.pull_request_state,
700 'author': _render('pullrequest_author',
702 'author': _render('pullrequest_author',
701 pr.author.full_contact, ),
703 pr.author.full_contact, ),
702 'author_raw': pr.author.full_name,
704 'author_raw': pr.author.full_name,
703 'comments': _render('pullrequest_comments', len(comments)),
705 'comments': _render('pullrequest_comments', len(comments)),
704 'comments_raw': len(comments),
706 'comments_raw': len(comments),
705 'closed': pr.is_closed(),
707 'closed': pr.is_closed(),
706 'owned': owned
708 'owned': owned
707 })
709 })
708
710
709 # json used to render the grid
711 # json used to render the grid
710 data = ({
712 data = ({
711 'draw': draw,
713 'draw': draw,
712 'data': data,
714 'data': data,
713 'recordsTotal': pull_requests_total_count,
715 'recordsTotal': pull_requests_total_count,
714 'recordsFiltered': pull_requests_total_count,
716 'recordsFiltered': pull_requests_total_count,
715 })
717 })
716 return data
718 return data
717
719
718 @LoginRequired()
720 @LoginRequired()
719 @NotAnonymous()
721 @NotAnonymous()
720 @view_config(
722 @view_config(
721 route_name='my_account_pullrequests',
723 route_name='my_account_pullrequests',
722 request_method='GET',
724 request_method='GET',
723 renderer='rhodecode:templates/admin/my_account/my_account.mako')
725 renderer='rhodecode:templates/admin/my_account/my_account.mako')
724 def my_account_pullrequests(self):
726 def my_account_pullrequests(self):
725 c = self.load_default_context()
727 c = self.load_default_context()
726 c.active = 'pullrequests'
728 c.active = 'pullrequests'
727 req_get = self.request.GET
729 req_get = self.request.GET
728
730
729 c.closed = str2bool(req_get.get('pr_show_closed'))
731 c.closed = str2bool(req_get.get('pr_show_closed'))
730
732
731 return self._get_template_context(c)
733 return self._get_template_context(c)
732
734
733 @LoginRequired()
735 @LoginRequired()
734 @NotAnonymous()
736 @NotAnonymous()
735 @view_config(
737 @view_config(
736 route_name='my_account_pullrequests_data',
738 route_name='my_account_pullrequests_data',
737 request_method='GET', renderer='json_ext')
739 request_method='GET', renderer='json_ext')
738 def my_account_pullrequests_data(self):
740 def my_account_pullrequests_data(self):
739 self.load_default_context()
741 self.load_default_context()
740 req_get = self.request.GET
742 req_get = self.request.GET
741 closed = str2bool(req_get.get('closed'))
743 closed = str2bool(req_get.get('closed'))
742
744
743 statuses = [PullRequest.STATUS_NEW, PullRequest.STATUS_OPEN]
745 statuses = [PullRequest.STATUS_NEW, PullRequest.STATUS_OPEN]
744 if closed:
746 if closed:
745 statuses += [PullRequest.STATUS_CLOSED]
747 statuses += [PullRequest.STATUS_CLOSED]
746
748
747 data = self._get_pull_requests_list(statuses=statuses)
749 data = self._get_pull_requests_list(statuses=statuses)
748 return data
750 return data
749
751
750 @LoginRequired()
752 @LoginRequired()
751 @NotAnonymous()
753 @NotAnonymous()
752 @view_config(
754 @view_config(
753 route_name='my_account_user_group_membership',
755 route_name='my_account_user_group_membership',
754 request_method='GET',
756 request_method='GET',
755 renderer='rhodecode:templates/admin/my_account/my_account.mako')
757 renderer='rhodecode:templates/admin/my_account/my_account.mako')
756 def my_account_user_group_membership(self):
758 def my_account_user_group_membership(self):
757 c = self.load_default_context()
759 c = self.load_default_context()
758 c.active = 'user_group_membership'
760 c.active = 'user_group_membership'
759 groups = [UserGroupModel.get_user_groups_as_dict(group.users_group)
761 groups = [UserGroupModel.get_user_groups_as_dict(group.users_group)
760 for group in self._rhodecode_db_user.group_member]
762 for group in self._rhodecode_db_user.group_member]
761 c.user_groups = json.dumps(groups)
763 c.user_groups = json.dumps(groups)
762 return self._get_template_context(c)
764 return self._get_template_context(c)
1 NO CONTENT: modified file
NO CONTENT: modified file
The requested commit or file is too big and content was truncated. Show full diff
General Comments 0
You need to be logged in to leave comments. Login now