Show More
@@ -0,0 +1,85 b'' | |||
|
1 | <div> | |
|
2 | ${h.form(url('admin_settings_my_account_update'),method='put')} | |
|
3 | <div class="form"> | |
|
4 | ||
|
5 | <div class="field"> | |
|
6 | <div class="gravatar_box"> | |
|
7 | <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(c.user.email)}"/></div> | |
|
8 | <p> | |
|
9 | %if c.use_gravatar: | |
|
10 | <strong>${_('Change your avatar at')} <a href="http://gravatar.com">gravatar.com</a></strong> | |
|
11 | <br/>${_('Using')} ${c.user.email} | |
|
12 | %else: | |
|
13 | <br/>${c.user.email} | |
|
14 | %endif | |
|
15 | </p> | |
|
16 | </div> | |
|
17 | </div> | |
|
18 | <div class="field"> | |
|
19 | <div class="label"> | |
|
20 | <label>${_('API key')}</label> ${c.user.api_key} | |
|
21 | </div> | |
|
22 | </div> | |
|
23 | <div class="fields"> | |
|
24 | <div class="field"> | |
|
25 | <div class="label"> | |
|
26 | <label for="username">${_('Username')}:</label> | |
|
27 | </div> | |
|
28 | <div class="input"> | |
|
29 | ${h.text('username',class_="medium")} | |
|
30 | </div> | |
|
31 | </div> | |
|
32 | ||
|
33 | <div class="field"> | |
|
34 | <div class="label"> | |
|
35 | <label for="new_password">${_('New password')}:</label> | |
|
36 | </div> | |
|
37 | <div class="input"> | |
|
38 | ${h.password('new_password',class_="medium",autocomplete="off")} | |
|
39 | </div> | |
|
40 | </div> | |
|
41 | ||
|
42 | <div class="field"> | |
|
43 | <div class="label"> | |
|
44 | <label for="password_confirmation">${_('New password confirmation')}:</label> | |
|
45 | </div> | |
|
46 | <div class="input"> | |
|
47 | ${h.password('password_confirmation',class_="medium",autocomplete="off")} | |
|
48 | </div> | |
|
49 | </div> | |
|
50 | ||
|
51 | <div class="field"> | |
|
52 | <div class="label"> | |
|
53 | <label for="name">${_('First Name')}:</label> | |
|
54 | </div> | |
|
55 | <div class="input"> | |
|
56 | ${h.text('name',class_="medium")} | |
|
57 | </div> | |
|
58 | </div> | |
|
59 | ||
|
60 | <div class="field"> | |
|
61 | <div class="label"> | |
|
62 | <label for="lastname">${_('Last Name')}:</label> | |
|
63 | </div> | |
|
64 | <div class="input"> | |
|
65 | ${h.text('lastname',class_="medium")} | |
|
66 | </div> | |
|
67 | </div> | |
|
68 | ||
|
69 | <div class="field"> | |
|
70 | <div class="label"> | |
|
71 | <label for="email">${_('Email')}:</label> | |
|
72 | </div> | |
|
73 | <div class="input"> | |
|
74 | ${h.text('email',class_="medium")} | |
|
75 | </div> | |
|
76 | </div> | |
|
77 | ||
|
78 | <div class="buttons"> | |
|
79 | ${h.submit('save',_('Save'),class_="ui-button")} | |
|
80 | ${h.reset('reset',_('Reset'),class_="ui-button")} | |
|
81 | </div> | |
|
82 | </div> | |
|
83 | </div> | |
|
84 | ${h.end_form()} | |
|
85 | </div> No newline at end of file |
@@ -25,7 +25,7 b' Or::' | |||
|
25 | 25 | pip install rhodecode |
|
26 | 26 | |
|
27 | 27 | If you prefer to install RhodeCode manually simply grab latest release from |
|
28 |
http://pypi.python.org/pypi/ |
|
|
28 | http://pypi.python.org/pypi/RhodeCode, decompress the archive and run:: | |
|
29 | 29 | |
|
30 | 30 | python setup.py install |
|
31 | 31 |
@@ -338,12 +338,14 b' class SettingsController(BaseController)' | |||
|
338 | 338 | return redirect(url('users')) |
|
339 | 339 | |
|
340 | 340 | defaults = c.user.get_dict() |
|
341 | return htmlfill.render( | |
|
342 | render('admin/users/user_edit_my_account.html'), | |
|
341 | ||
|
342 | c.form = htmlfill.render( | |
|
343 | render('admin/users/user_edit_my_account_form.html'), | |
|
343 | 344 | defaults=defaults, |
|
344 | 345 | encoding="UTF-8", |
|
345 | 346 | force_defaults=False |
|
346 | 347 | ) |
|
348 | return render('admin/users/user_edit_my_account.html') | |
|
347 | 349 | |
|
348 | 350 | def my_account_update(self): |
|
349 | 351 | """PUT /_admin/my_account_update: Update an existing item""" |
@@ -373,12 +375,13 b' class SettingsController(BaseController)' | |||
|
373 | 375 | .all() |
|
374 | 376 | c.user_repos = ScmModel().get_repos(all_repos) |
|
375 | 377 | |
|
376 |
|
|
|
377 | render('admin/users/user_edit_my_account.html'), | |
|
378 | c.form = htmlfill.render( | |
|
379 | render('admin/users/user_edit_my_account_form.html'), | |
|
378 | 380 | defaults=errors.value, |
|
379 | 381 | errors=errors.error_dict or {}, |
|
380 | 382 | prefix_error=False, |
|
381 | 383 | encoding="UTF-8") |
|
384 | return render('admin/users/user_edit_my_account.html') | |
|
382 | 385 | except Exception: |
|
383 | 386 | log.error(traceback.format_exc()) |
|
384 | 387 | h.flash(_('error occurred during update of user %s') \ |
@@ -27,11 +27,13 b' import os' | |||
|
27 | 27 | import logging |
|
28 | 28 | import datetime |
|
29 | 29 | import traceback |
|
30 | import hashlib | |
|
30 | 31 | from collections import defaultdict |
|
31 | 32 | |
|
32 | 33 | from sqlalchemy import * |
|
33 | 34 | from sqlalchemy.ext.hybrid import hybrid_property |
|
34 | 35 | from sqlalchemy.orm import relationship, joinedload, class_mapper, validates |
|
36 | from sqlalchemy.exc import DatabaseError | |
|
35 | 37 | from beaker.cache import cache_region, region_invalidate |
|
36 | 38 | |
|
37 | 39 | from pylons.i18n.translation import lazy_ugettext as _ |
@@ -47,8 +49,7 b' from rhodecode.lib.compat import json' | |||
|
47 | 49 | from rhodecode.lib.caching_query import FromCache |
|
48 | 50 | |
|
49 | 51 | from rhodecode.model.meta import Base, Session |
|
50 | import hashlib | |
|
51 | from sqlalchemy.exc import DatabaseError | |
|
52 | ||
|
52 | 53 | |
|
53 | 54 | URL_SEP = '/' |
|
54 | 55 | log = logging.getLogger(__name__) |
@@ -155,6 +156,7 b' class BaseModel(object):' | |||
|
155 | 156 | return safe_str(self.__unicode__()) |
|
156 | 157 | return '<DB:%s>' % (self.__class__.__name__) |
|
157 | 158 | |
|
159 | ||
|
158 | 160 | class RhodeCodeSetting(Base, BaseModel): |
|
159 | 161 | __tablename__ = 'rhodecode_settings' |
|
160 | 162 | __table_args__ = ( |
@@ -225,7 +227,7 b' class RhodeCodeSetting(Base, BaseModel):' | |||
|
225 | 227 | .filter(cls.app_settings_name.startswith('ldap_')).all() |
|
226 | 228 | fd = {} |
|
227 | 229 | for row in ret: |
|
228 | fd.update({row.app_settings_name:row.app_settings_value}) | |
|
230 | fd.update({row.app_settings_name: row.app_settings_value}) | |
|
229 | 231 | |
|
230 | 232 | return fd |
|
231 | 233 | |
@@ -761,18 +763,27 b' class Repository(Base, BaseModel):' | |||
|
761 | 763 | def scm_instance(self): |
|
762 | 764 | return self.__get_instance() |
|
763 | 765 | |
|
764 | @property | |
|
765 | def scm_instance_cached(self): | |
|
766 | def scm_instance_cached(self, cache_map=None): | |
|
766 | 767 | @cache_region('long_term') |
|
767 | 768 | def _c(repo_name): |
|
768 | 769 | return self.__get_instance() |
|
769 | 770 | rn = self.repo_name |
|
770 | 771 | log.debug('Getting cached instance of repo') |
|
771 | inv = self.invalidate | |
|
772 | if inv is not None: | |
|
772 | ||
|
773 | if cache_map: | |
|
774 | # get using prefilled cache_map | |
|
775 | invalidate_repo = cache_map[self.repo_name] | |
|
776 | if invalidate_repo: | |
|
777 | invalidate_repo = (None if invalidate_repo.cache_active | |
|
778 | else invalidate_repo) | |
|
779 | else: | |
|
780 | # get from invalidate | |
|
781 | invalidate_repo = self.invalidate | |
|
782 | ||
|
783 | if invalidate_repo is not None: | |
|
773 | 784 | region_invalidate(_c, None, rn) |
|
774 | 785 | # update our cache |
|
775 | CacheInvalidation.set_valid(inv.cache_key) | |
|
786 | CacheInvalidation.set_valid(invalidate_repo.cache_key) | |
|
776 | 787 | return _c(rn) |
|
777 | 788 | |
|
778 | 789 | def __get_instance(self): |
@@ -1140,6 +1151,7 b' class CacheInvalidation(Base, BaseModel)' | |||
|
1140 | 1151 | __tablename__ = 'cache_invalidation' |
|
1141 | 1152 | __table_args__ = ( |
|
1142 | 1153 | UniqueConstraint('cache_key'), |
|
1154 | Index('key_idx', 'cache_key'), | |
|
1143 | 1155 | {'extend_existing': True, 'mysql_engine': 'InnoDB', |
|
1144 | 1156 | 'mysql_charset': 'utf8'}, |
|
1145 | 1157 | ) |
@@ -1156,6 +1168,7 b' class CacheInvalidation(Base, BaseModel)' | |||
|
1156 | 1168 | def __unicode__(self): |
|
1157 | 1169 | return u"<%s('%s:%s')>" % (self.__class__.__name__, |
|
1158 | 1170 | self.cache_id, self.cache_key) |
|
1171 | ||
|
1159 | 1172 | @classmethod |
|
1160 | 1173 | def clear_cache(cls): |
|
1161 | 1174 | cls.query().delete() |
@@ -1242,6 +1255,40 b' class CacheInvalidation(Base, BaseModel)' | |||
|
1242 | 1255 | Session.add(inv_obj) |
|
1243 | 1256 | Session.commit() |
|
1244 | 1257 | |
|
1258 | @classmethod | |
|
1259 | def get_cache_map(cls): | |
|
1260 | ||
|
1261 | class cachemapdict(dict): | |
|
1262 | ||
|
1263 | def __init__(self, *args, **kwargs): | |
|
1264 | fixkey = kwargs.get('fixkey') | |
|
1265 | if fixkey: | |
|
1266 | del kwargs['fixkey'] | |
|
1267 | self.fixkey = fixkey | |
|
1268 | super(cachemapdict, self).__init__(*args, **kwargs) | |
|
1269 | ||
|
1270 | def __getattr__(self, name): | |
|
1271 | key = name | |
|
1272 | if self.fixkey: | |
|
1273 | key, _prefix, _org_key = cls._get_key(key) | |
|
1274 | if key in self.__dict__: | |
|
1275 | return self.__dict__[key] | |
|
1276 | else: | |
|
1277 | return self[key] | |
|
1278 | ||
|
1279 | def __getitem__(self, key): | |
|
1280 | if self.fixkey: | |
|
1281 | key, _prefix, _org_key = cls._get_key(key) | |
|
1282 | try: | |
|
1283 | return super(cachemapdict, self).__getitem__(key) | |
|
1284 | except KeyError: | |
|
1285 | return | |
|
1286 | ||
|
1287 | cache_map = cachemapdict(fixkey=True) | |
|
1288 | for obj in cls.query().all(): | |
|
1289 | cache_map[obj.cache_key] = cachemapdict(obj.get_dict()) | |
|
1290 | return cache_map | |
|
1291 | ||
|
1245 | 1292 | |
|
1246 | 1293 | class ChangesetComment(Base, BaseModel): |
|
1247 | 1294 | __tablename__ = 'changeset_comments' |
@@ -28,6 +28,8 b' import traceback' | |||
|
28 | 28 | import logging |
|
29 | 29 | import cStringIO |
|
30 | 30 | |
|
31 | from sqlalchemy import func | |
|
32 | ||
|
31 | 33 | from rhodecode.lib.vcs import get_backend |
|
32 | 34 | from rhodecode.lib.vcs.exceptions import RepositoryError |
|
33 | 35 | from rhodecode.lib.vcs.utils.lazy import LazyProperty |
@@ -77,8 +79,12 b' class CachedRepoList(object):' | |||
|
77 | 79 | return '<%s (%s)>' % (self.__class__.__name__, self.__len__()) |
|
78 | 80 | |
|
79 | 81 | def __iter__(self): |
|
82 | # pre-propagated cache_map to save executing select statements | |
|
83 | # for each repo | |
|
84 | cache_map = CacheInvalidation.get_cache_map() | |
|
85 | ||
|
80 | 86 | for dbr in self.db_repo_list: |
|
81 | scmr = dbr.scm_instance_cached | |
|
87 | scmr = dbr.scm_instance_cached(cache_map) | |
|
82 | 88 | # check permission at this level |
|
83 | 89 | if not HasRepoPermissionAny( |
|
84 | 90 | 'repository.read', 'repository.write', 'repository.admin' |
@@ -219,7 +225,7 b' class ScmModel(BaseModel):' | |||
|
219 | 225 | if all_repos is None: |
|
220 | 226 | all_repos = self.sa.query(Repository)\ |
|
221 | 227 | .filter(Repository.group_id == None)\ |
|
222 | .order_by(Repository.repo_name).all() | |
|
228 | .order_by(func.lower(Repository.repo_name)).all() | |
|
223 | 229 | |
|
224 | 230 | repo_iter = CachedRepoList(all_repos, repos_path=self.repos_path, |
|
225 | 231 | order_by=sort_key) |
@@ -21,91 +21,7 b'' | |||
|
21 | 21 | ${self.breadcrumbs()} |
|
22 | 22 | </div> |
|
23 | 23 | <!-- end box / title --> |
|
24 | <div> | |
|
25 | ${h.form(url('admin_settings_my_account_update'),method='put')} | |
|
26 | <div class="form"> | |
|
27 | ||
|
28 | <div class="field"> | |
|
29 | <div class="gravatar_box"> | |
|
30 | <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(c.user.email)}"/></div> | |
|
31 | <p> | |
|
32 | %if c.use_gravatar: | |
|
33 | <strong>${_('Change your avatar at')} <a href="http://gravatar.com">gravatar.com</a></strong> | |
|
34 | <br/>${_('Using')} ${c.user.email} | |
|
35 | %else: | |
|
36 | <br/>${c.user.email} | |
|
37 | %endif | |
|
38 | </p> | |
|
39 | </div> | |
|
40 | </div> | |
|
41 | <div class="field"> | |
|
42 | <div class="label"> | |
|
43 | <label>${_('API key')}</label> ${c.user.api_key} | |
|
44 | </div> | |
|
45 | </div> | |
|
46 | <div class="fields"> | |
|
47 | <div class="field"> | |
|
48 | <div class="label"> | |
|
49 | <label for="username">${_('Username')}:</label> | |
|
50 | </div> | |
|
51 | <div class="input"> | |
|
52 | ${h.text('username',class_="medium")} | |
|
53 | </div> | |
|
54 | </div> | |
|
55 | ||
|
56 | <div class="field"> | |
|
57 | <div class="label"> | |
|
58 | <label for="new_password">${_('New password')}:</label> | |
|
59 | </div> | |
|
60 | <div class="input"> | |
|
61 | ${h.password('new_password',class_="medium",autocomplete="off")} | |
|
62 | </div> | |
|
63 | </div> | |
|
64 | ||
|
65 | <div class="field"> | |
|
66 | <div class="label"> | |
|
67 | <label for="password_confirmation">${_('New password confirmation')}:</label> | |
|
68 | </div> | |
|
69 | <div class="input"> | |
|
70 | ${h.password('password_confirmation',class_="medium",autocomplete="off")} | |
|
71 | </div> | |
|
72 | </div> | |
|
73 | ||
|
74 | <div class="field"> | |
|
75 | <div class="label"> | |
|
76 | <label for="name">${_('First Name')}:</label> | |
|
77 | </div> | |
|
78 | <div class="input"> | |
|
79 | ${h.text('name',class_="medium")} | |
|
80 | </div> | |
|
81 | </div> | |
|
82 | ||
|
83 | <div class="field"> | |
|
84 | <div class="label"> | |
|
85 | <label for="lastname">${_('Last Name')}:</label> | |
|
86 | </div> | |
|
87 | <div class="input"> | |
|
88 | ${h.text('lastname',class_="medium")} | |
|
89 | </div> | |
|
90 | </div> | |
|
91 | ||
|
92 | <div class="field"> | |
|
93 | <div class="label"> | |
|
94 | <label for="email">${_('Email')}:</label> | |
|
95 | </div> | |
|
96 | <div class="input"> | |
|
97 | ${h.text('email',class_="medium")} | |
|
98 | </div> | |
|
99 | </div> | |
|
100 | ||
|
101 | <div class="buttons"> | |
|
102 | ${h.submit('save',_('Save'),class_="ui-button")} | |
|
103 | ${h.reset('reset',_('Reset'),class_="ui-button")} | |
|
104 | </div> | |
|
105 | </div> | |
|
106 | </div> | |
|
107 | ${h.end_form()} | |
|
108 | </div> | |
|
24 | ${c.form|n} | |
|
109 | 25 | </div> |
|
110 | 26 | |
|
111 | 27 | <div class="box box-right"> |
General Comments 0
You need to be logged in to leave comments.
Login now