##// END OF EJS Templates
auth: disable password change when not using internal auth
Mads Kiilerich -
r5345:de9a3152 default
parent child Browse files
Show More
@@ -1,274 +1,278 b''
1 1 # -*- coding: utf-8 -*-
2 2 # This program is free software: you can redistribute it and/or modify
3 3 # it under the terms of the GNU General Public License as published by
4 4 # the Free Software Foundation, either version 3 of the License, or
5 5 # (at your option) any later version.
6 6 #
7 7 # This program is distributed in the hope that it will be useful,
8 8 # but WITHOUT ANY WARRANTY; without even the implied warranty of
9 9 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 10 # GNU General Public License for more details.
11 11 #
12 12 # You should have received a copy of the GNU General Public License
13 13 # along with this program. If not, see <http://www.gnu.org/licenses/>.
14 14 """
15 15 kallithea.controllers.admin.my_account
16 16 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
17 17
18 18 my account controller for Kallithea admin
19 19
20 20 This file was forked by the Kallithea project in July 2014.
21 21 Original author and date, and relevant copyright and licensing information is below:
22 22 :created_on: August 20, 2013
23 23 :author: marcink
24 24 :copyright: (c) 2013 RhodeCode GmbH, and others.
25 25 :license: GPLv3, see LICENSE.md for more details.
26 26 """
27 27
28 28 import logging
29 29 import traceback
30 30 import formencode
31 31
32 32 from sqlalchemy import func
33 33 from formencode import htmlfill
34 34 from pylons import request, tmpl_context as c, url
35 35 from pylons.controllers.util import redirect
36 36 from pylons.i18n.translation import _
37 37
38 38 from kallithea import EXTERN_TYPE_INTERNAL
39 39 from kallithea.lib import helpers as h
40 40 from kallithea.lib import auth_modules
41 41 from kallithea.lib.auth import LoginRequired, NotAnonymous, AuthUser
42 42 from kallithea.lib.base import BaseController, render
43 43 from kallithea.lib.utils2 import generate_api_key, safe_int
44 44 from kallithea.lib.compat import json
45 45 from kallithea.model.db import Repository, \
46 46 UserEmailMap, UserApiKeys, User, UserFollowing
47 47 from kallithea.model.forms import UserForm, PasswordChangeForm
48 48 from kallithea.model.user import UserModel
49 49 from kallithea.model.repo import RepoModel
50 50 from kallithea.model.api_key import ApiKeyModel
51 51 from kallithea.model.meta import Session
52 52
53 53 log = logging.getLogger(__name__)
54 54
55 55
56 56 class MyAccountController(BaseController):
57 57 """REST Controller styled on the Atom Publishing Protocol"""
58 58 # To properly map this controller, ensure your config/routing.py
59 59 # file has a resource setup:
60 60 # map.resource('setting', 'settings', controller='admin/settings',
61 61 # path_prefix='/admin', name_prefix='admin_')
62 62
63 63 @LoginRequired()
64 64 @NotAnonymous()
65 65 def __before__(self):
66 66 super(MyAccountController, self).__before__()
67 67
68 68 def __load_data(self):
69 69 c.user = User.get(self.authuser.user_id)
70 70 if c.user.username == User.DEFAULT_USER:
71 71 h.flash(_("You can't edit this user since it's"
72 72 " crucial for entire application"), category='warning')
73 73 return redirect(url('users'))
74 74 c.EXTERN_TYPE_INTERNAL = EXTERN_TYPE_INTERNAL
75 75
76 76 def _load_my_repos_data(self, watched=False):
77 77 if watched:
78 78 admin = False
79 79 repos_list = [x.follows_repository for x in
80 80 Session().query(UserFollowing).filter(
81 81 UserFollowing.user_id ==
82 82 self.authuser.user_id).all()]
83 83 else:
84 84 admin = True
85 85 repos_list = Session().query(Repository)\
86 86 .filter(Repository.user_id ==
87 87 self.authuser.user_id)\
88 88 .order_by(func.lower(Repository.repo_name)).all()
89 89
90 90 repos_data = RepoModel().get_repos_as_dict(repos_list=repos_list,
91 91 admin=admin)
92 92 #json used to render the grid
93 93 return json.dumps(repos_data)
94 94
95 95 def my_account(self):
96 96 """
97 97 GET /_admin/my_account Displays info about my account
98 98 """
99 99 # url('my_account')
100 100 c.active = 'profile'
101 101 self.__load_data()
102 102 c.perm_user = AuthUser(user_id=self.authuser.user_id)
103 103 c.ip_addr = self.ip_addr
104 104 managed_fields = auth_modules.get_managed_fields(c.user)
105 105 def_user_perms = User.get_default_user().AuthUser.permissions['global']
106 106 if 'hg.register.none' in def_user_perms:
107 107 managed_fields.extend(['username', 'firstname', 'lastname', 'email'])
108 108
109 109 c.readonly = lambda n: 'readonly' if n in managed_fields else None
110 110
111 111 defaults = c.user.get_dict()
112 112 update = False
113 113 if request.POST:
114 114 _form = UserForm(edit=True,
115 115 old_data={'user_id': self.authuser.user_id,
116 116 'email': self.authuser.email})()
117 117 form_result = {}
118 118 try:
119 119 post_data = dict(request.POST)
120 120 post_data['new_password'] = ''
121 121 post_data['password_confirmation'] = ''
122 122 form_result = _form.to_python(post_data)
123 123 # skip updating those attrs for my account
124 124 skip_attrs = ['admin', 'active', 'extern_type', 'extern_name',
125 125 'new_password', 'password_confirmation',
126 126 ] + managed_fields
127 127
128 128 UserModel().update(self.authuser.user_id, form_result,
129 129 skip_attrs=skip_attrs)
130 130 h.flash(_('Your account was updated successfully'),
131 131 category='success')
132 132 Session().commit()
133 133 update = True
134 134
135 135 except formencode.Invalid, errors:
136 136 return htmlfill.render(
137 137 render('admin/my_account/my_account.html'),
138 138 defaults=errors.value,
139 139 errors=errors.error_dict or {},
140 140 prefix_error=False,
141 141 encoding="UTF-8",
142 142 force_defaults=False)
143 143 except Exception:
144 144 log.error(traceback.format_exc())
145 145 h.flash(_('Error occurred during update of user %s') \
146 146 % form_result.get('username'), category='error')
147 147 if update:
148 148 return redirect('my_account')
149 149 return htmlfill.render(
150 150 render('admin/my_account/my_account.html'),
151 151 defaults=defaults,
152 152 encoding="UTF-8",
153 153 force_defaults=False)
154 154
155 155 def my_account_password(self):
156 156 c.active = 'password'
157 157 self.__load_data()
158 if request.POST:
158
159 managed_fields = auth_modules.get_managed_fields(c.user)
160 c.can_change_password = 'password' not in managed_fields
161
162 if request.POST and c.can_change_password:
159 163 _form = PasswordChangeForm(self.authuser.username)()
160 164 try:
161 165 form_result = _form.to_python(request.POST)
162 166 UserModel().update(self.authuser.user_id, form_result)
163 167 Session().commit()
164 168 h.flash(_("Successfully updated password"), category='success')
165 169 except formencode.Invalid as errors:
166 170 return htmlfill.render(
167 171 render('admin/my_account/my_account.html'),
168 172 defaults=errors.value,
169 173 errors=errors.error_dict or {},
170 174 prefix_error=False,
171 175 encoding="UTF-8",
172 176 force_defaults=False)
173 177 except Exception:
174 178 log.error(traceback.format_exc())
175 179 h.flash(_('Error occurred during update of user password'),
176 180 category='error')
177 181 return render('admin/my_account/my_account.html')
178 182
179 183 def my_account_repos(self):
180 184 c.active = 'repos'
181 185 self.__load_data()
182 186
183 187 #json used to render the grid
184 188 c.data = self._load_my_repos_data()
185 189 return render('admin/my_account/my_account.html')
186 190
187 191 def my_account_watched(self):
188 192 c.active = 'watched'
189 193 self.__load_data()
190 194
191 195 #json used to render the grid
192 196 c.data = self._load_my_repos_data(watched=True)
193 197 return render('admin/my_account/my_account.html')
194 198
195 199 def my_account_perms(self):
196 200 c.active = 'perms'
197 201 self.__load_data()
198 202 c.perm_user = AuthUser(user_id=self.authuser.user_id)
199 203 c.ip_addr = self.ip_addr
200 204
201 205 return render('admin/my_account/my_account.html')
202 206
203 207 def my_account_emails(self):
204 208 c.active = 'emails'
205 209 self.__load_data()
206 210
207 211 c.user_email_map = UserEmailMap.query()\
208 212 .filter(UserEmailMap.user == c.user).all()
209 213 return render('admin/my_account/my_account.html')
210 214
211 215 def my_account_emails_add(self):
212 216 email = request.POST.get('new_email')
213 217
214 218 try:
215 219 UserModel().add_extra_email(self.authuser.user_id, email)
216 220 Session().commit()
217 221 h.flash(_("Added email %s to user") % email, category='success')
218 222 except formencode.Invalid, error:
219 223 msg = error.error_dict['email']
220 224 h.flash(msg, category='error')
221 225 except Exception:
222 226 log.error(traceback.format_exc())
223 227 h.flash(_('An error occurred during email saving'),
224 228 category='error')
225 229 return redirect(url('my_account_emails'))
226 230
227 231 def my_account_emails_delete(self):
228 232 email_id = request.POST.get('del_email_id')
229 233 user_model = UserModel()
230 234 user_model.delete_extra_email(self.authuser.user_id, email_id)
231 235 Session().commit()
232 236 h.flash(_("Removed email from user"), category='success')
233 237 return redirect(url('my_account_emails'))
234 238
235 239 def my_account_api_keys(self):
236 240 c.active = 'api_keys'
237 241 self.__load_data()
238 242 show_expired = True
239 243 c.lifetime_values = [
240 244 (str(-1), _('Forever')),
241 245 (str(5), _('5 minutes')),
242 246 (str(60), _('1 hour')),
243 247 (str(60 * 24), _('1 day')),
244 248 (str(60 * 24 * 30), _('1 month')),
245 249 ]
246 250 c.lifetime_options = [(c.lifetime_values, _("Lifetime"))]
247 251 c.user_api_keys = ApiKeyModel().get_api_keys(self.authuser.user_id,
248 252 show_expired=show_expired)
249 253 return render('admin/my_account/my_account.html')
250 254
251 255 def my_account_api_keys_add(self):
252 256 lifetime = safe_int(request.POST.get('lifetime'), -1)
253 257 description = request.POST.get('description')
254 258 ApiKeyModel().create(self.authuser.user_id, description, lifetime)
255 259 Session().commit()
256 260 h.flash(_("API key successfully created"), category='success')
257 261 return redirect(url('my_account_api_keys'))
258 262
259 263 def my_account_api_keys_delete(self):
260 264 api_key = request.POST.get('del_api_key')
261 265 user_id = self.authuser.user_id
262 266 if request.POST.get('del_api_key_builtin'):
263 267 user = User.get(user_id)
264 268 if user is not None:
265 269 user.api_key = generate_api_key()
266 270 Session().add(user)
267 271 Session().commit()
268 272 h.flash(_("API key successfully reset"), category='success')
269 273 elif api_key:
270 274 ApiKeyModel().delete(api_key, self.authuser.user_id)
271 275 Session().commit()
272 276 h.flash(_("API key successfully deleted"), category='success')
273 277
274 278 return redirect(url('my_account_api_keys'))
@@ -1,38 +1,47 b''
1 1 <div style="font-size: 20px; color: #666666; padding: 0px 0px 10px 0px">${_('Change Your Account Password')}</div>
2
3 %if c.can_change_password:
4
2 5 ${h.form(url('my_account_password'), method='post')}
3 6 <div class="form">
4 7 <div class="fields">
5 8 <div class="field">
6 9 <div class="label">
7 10 <label for="current_password">${_('Current password')}:</label>
8 11 </div>
9 12 <div class="input">
10 13 ${h.password('current_password',class_='medium')}
11 14 </div>
12 15 </div>
13 16
14 17 <div class="field">
15 18 <div class="label">
16 19 <label for="new_password">${_('New password')}:</label>
17 20 </div>
18 21 <div class="input">
19 22 ${h.password('new_password',class_='medium')}
20 23 </div>
21 24 </div>
22 25
23 26 <div class="field">
24 27 <div class="label">
25 28 <label for="new_password_confirmation">${_('Confirm new password')}:</label>
26 29 </div>
27 30 <div class="input">
28 31 ${h.password('new_password_confirmation',class_='medium')}
29 32 </div>
30 33 </div>
31 34
32 35 <div class="buttons">
33 36 ${h.submit('save',_('Save'),class_="btn")}
34 37 ${h.reset('reset',_('Reset'),class_="btn")}
35 38 </div>
36 39 </div>
37 40 </div>
38 41 ${h.end_form()}
42
43 %else:
44
45 ${_('This account is managed with %s and the password cannot be changed here') % c.user.extern_type}
46
47 %endif
General Comments 0
You need to be logged in to leave comments. Login now