Show More
@@ -32,7 +32,7 b' threadpool_workers = 5' | |||||
32 | threadpool_max_requests = 6 |
|
32 | threadpool_max_requests = 6 | |
33 |
|
33 | |||
34 | ##option to use threads of process |
|
34 | ##option to use threads of process | |
35 |
use_threadpool = |
|
35 | use_threadpool = true | |
36 |
|
36 | |||
37 | use = egg:Paste#http |
|
37 | use = egg:Paste#http | |
38 | host = 0.0.0.0 |
|
38 | host = 0.0.0.0 |
@@ -29,7 +29,7 b' debug = true' | |||||
29 | threadpool_workers = 5 |
|
29 | threadpool_workers = 5 | |
30 |
|
30 | |||
31 | ##max request before thread respawn |
|
31 | ##max request before thread respawn | |
32 |
threadpool_max_requests = |
|
32 | threadpool_max_requests = 6 | |
33 |
|
33 | |||
34 | ##option to use threads of process |
|
34 | ##option to use threads of process | |
35 | use_threadpool = true |
|
35 | use_threadpool = true | |
@@ -47,7 +47,7 b' cache_dir = %(here)s/data' | |||||
47 | index_dir = %(here)s/data/index |
|
47 | index_dir = %(here)s/data/index | |
48 | cut_off_limit = 256000 |
|
48 | cut_off_limit = 256000 | |
49 | force_https = false |
|
49 | force_https = false | |
50 |
commit_parse_limit = 25 |
|
50 | commit_parse_limit = 25 | |
51 | use_gravatar = true |
|
51 | use_gravatar = true | |
52 |
|
52 | |||
53 | #################################### |
|
53 | #################################### | |
@@ -94,7 +94,6 b' beaker.cache.short_term.expire=60' | |||||
94 | beaker.cache.long_term.type=memory |
|
94 | beaker.cache.long_term.type=memory | |
95 | beaker.cache.long_term.expire=36000 |
|
95 | beaker.cache.long_term.expire=36000 | |
96 |
|
96 | |||
97 |
|
||||
98 | beaker.cache.sql_cache_short.type=memory |
|
97 | beaker.cache.sql_cache_short.type=memory | |
99 | beaker.cache.sql_cache_short.expire=10 |
|
98 | beaker.cache.sql_cache_short.expire=10 | |
100 |
|
99 | |||
@@ -141,7 +140,8 b' logview.pylons.util = #eee' | |||||
141 | ######################################################### |
|
140 | ######################################################### | |
142 | ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ### |
|
141 | ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ### | |
143 | ######################################################### |
|
142 | ######################################################### | |
144 | sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db |
|
143 | #sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db | |
|
144 | sqlalchemy.db1.url = postgresql://postgres:qwe@localhost/rhodecode | |||
145 | #sqlalchemy.db1.echo = False |
|
145 | #sqlalchemy.db1.echo = False | |
146 | #sqlalchemy.db1.pool_recycle = 3600 |
|
146 | #sqlalchemy.db1.pool_recycle = 3600 | |
147 | sqlalchemy.convert_unicode = true |
|
147 | sqlalchemy.convert_unicode = true |
@@ -27,3 +27,12 b'' | |||||
27 |
|
27 | |||
28 | def str2bool(v): |
|
28 | def str2bool(v): | |
29 | return v.lower() in ["yes", "true", "t", "1"] if v else None |
|
29 | return v.lower() in ["yes", "true", "t", "1"] if v else None | |
|
30 | ||||
|
31 | def generate_api_key(username, salt=None): | |||
|
32 | from tempfile import _RandomNameSequence | |||
|
33 | import hashlib | |||
|
34 | ||||
|
35 | if salt is None: | |||
|
36 | salt = _RandomNameSequence().next() | |||
|
37 | ||||
|
38 | return hashlib.sha1(username + salt).hexdigest() |
@@ -28,7 +28,8 b' import bcrypt' | |||||
28 | import random |
|
28 | import random | |
29 | import logging |
|
29 | import logging | |
30 | import traceback |
|
30 | import traceback | |
31 |
|
31 | import hashlib | ||
|
32 | from tempfile import _RandomNameSequence | |||
32 | from decorator import decorator |
|
33 | from decorator import decorator | |
33 |
|
34 | |||
34 | from pylons import config, session, url, request |
|
35 | from pylons import config, session, url, request | |
@@ -87,6 +88,12 b' def get_crypt_password(password):' | |||||
87 | """ |
|
88 | """ | |
88 | return bcrypt.hashpw(password, bcrypt.gensalt(10)) |
|
89 | return bcrypt.hashpw(password, bcrypt.gensalt(10)) | |
89 |
|
90 | |||
|
91 | def generate_api_key(username, salt=None): | |||
|
92 | if salt is None: | |||
|
93 | salt = _RandomNameSequence().next() | |||
|
94 | ||||
|
95 | return hashlib.sha1(username + salt).hexdigest() | |||
|
96 | ||||
90 | def check_password(password, hashed): |
|
97 | def check_password(password, hashed): | |
91 | return bcrypt.hashpw(password, hashed) == hashed |
|
98 | return bcrypt.hashpw(password, hashed) == hashed | |
92 |
|
99 |
@@ -245,6 +245,7 b' def reset_user_password(user_email):' | |||||
245 | auth.PasswordGenerator.ALPHABETS_BIG_SMALL) |
|
245 | auth.PasswordGenerator.ALPHABETS_BIG_SMALL) | |
246 | if user: |
|
246 | if user: | |
247 | user.password = auth.get_crypt_password(new_passwd) |
|
247 | user.password = auth.get_crypt_password(new_passwd) | |
|
248 | user.api_key = auth.generate_api_key(user.username) | |||
248 | sa.add(user) |
|
249 | sa.add(user) | |
249 | sa.commit() |
|
250 | sa.commit() | |
250 | log.info('change password for %s', user_email) |
|
251 | log.info('change password for %s', user_email) |
@@ -35,7 +35,7 b' from os.path import dirname as dn, join ' | |||||
35 | from rhodecode import __dbversion__ |
|
35 | from rhodecode import __dbversion__ | |
36 | from rhodecode.model import meta |
|
36 | from rhodecode.model import meta | |
37 |
|
37 | |||
38 | from rhodecode.lib.auth import get_crypt_password |
|
38 | from rhodecode.lib.auth import get_crypt_password, generate_api_key | |
39 | from rhodecode.lib.utils import ask_ok |
|
39 | from rhodecode.lib.utils import ask_ok | |
40 | from rhodecode.model import init_model |
|
40 | from rhodecode.model import init_model | |
41 | from rhodecode.model.db import User, Permission, RhodeCodeUi, RhodeCodeSettings, \ |
|
41 | from rhodecode.model.db import User, Permission, RhodeCodeUi, RhodeCodeSettings, \ | |
@@ -442,6 +442,7 b' class DbManage(object):' | |||||
442 | new_user = User() |
|
442 | new_user = User() | |
443 | new_user.username = username |
|
443 | new_user.username = username | |
444 | new_user.password = get_crypt_password(password) |
|
444 | new_user.password = get_crypt_password(password) | |
|
445 | new_user.api_key = generate_api_key(username) | |||
445 | new_user.name = 'RhodeCode' |
|
446 | new_user.name = 'RhodeCode' | |
446 | new_user.lastname = 'Admin' |
|
447 | new_user.lastname = 'Admin' | |
447 | new_user.email = email |
|
448 | new_user.email = email | |
@@ -461,6 +462,7 b' class DbManage(object):' | |||||
461 | def_user = User() |
|
462 | def_user = User() | |
462 | def_user.username = 'default' |
|
463 | def_user.username = 'default' | |
463 | def_user.password = get_crypt_password(str(uuid.uuid1())[:8]) |
|
464 | def_user.password = get_crypt_password(str(uuid.uuid1())[:8]) | |
|
465 | def_user.api_key = generate_api_key('default') | |||
464 | def_user.name = 'Anonymous' |
|
466 | def_user.name = 'Anonymous' | |
465 | def_user.lastname = 'User' |
|
467 | def_user.lastname = 'User' | |
466 | def_user.email = 'anonymous@rhodecode.org' |
|
468 | def_user.email = 'anonymous@rhodecode.org' | |
@@ -484,8 +486,8 b' class DbManage(object):' | |||||
484 | ('hg.create.repository', 'Repository create'), |
|
486 | ('hg.create.repository', 'Repository create'), | |
485 | ('hg.create.none', 'Repository creation disabled'), |
|
487 | ('hg.create.none', 'Repository creation disabled'), | |
486 | ('hg.register.none', 'Register disabled'), |
|
488 | ('hg.register.none', 'Register disabled'), | |
487 |
('hg.register.manual_activate', 'Register new user with |
|
489 | ('hg.register.manual_activate', 'Register new user with RhodeCode without manual activation'), | |
488 |
('hg.register.auto_activate', 'Register new user with |
|
490 | ('hg.register.auto_activate', 'Register new user with RhodeCode without auto activation'), | |
489 | ] |
|
491 | ] | |
490 |
|
492 | |||
491 | for p in perms: |
|
493 | for p in perms: |
@@ -37,6 +37,7 b' from rhodecode.model.db import User' | |||||
37 | from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException |
|
37 | from rhodecode.lib.exceptions import DefaultUserException, UserOwnsReposException | |
38 |
|
38 | |||
39 | from sqlalchemy.exc import DatabaseError |
|
39 | from sqlalchemy.exc import DatabaseError | |
|
40 | from rhodecode.lib import generate_api_key | |||
40 |
|
41 | |||
41 | log = logging.getLogger(__name__) |
|
42 | log = logging.getLogger(__name__) | |
42 |
|
43 | |||
@@ -68,6 +69,7 b' class UserModel(BaseModel):' | |||||
68 | for k, v in form_data.items(): |
|
69 | for k, v in form_data.items(): | |
69 | setattr(new_user, k, v) |
|
70 | setattr(new_user, k, v) | |
70 |
|
71 | |||
|
72 | new_user.api_key = generate_api_key(form_data['username']) | |||
71 | self.sa.add(new_user) |
|
73 | self.sa.add(new_user) | |
72 | self.sa.commit() |
|
74 | self.sa.commit() | |
73 | except: |
|
75 | except: | |
@@ -91,6 +93,7 b' class UserModel(BaseModel):' | |||||
91 | new_user = User() |
|
93 | new_user = User() | |
92 | new_user.username = username.lower() # add ldap account always lowercase |
|
94 | new_user.username = username.lower() # add ldap account always lowercase | |
93 | new_user.password = get_crypt_password(password) |
|
95 | new_user.password = get_crypt_password(password) | |
|
96 | new_user.api_key = generate_api_key(username) | |||
94 | new_user.email = attrs['email'] |
|
97 | new_user.email = attrs['email'] | |
95 | new_user.active = True |
|
98 | new_user.active = True | |
96 | new_user.ldap_dn = user_dn |
|
99 | new_user.ldap_dn = user_dn | |
@@ -134,19 +137,20 b' class UserModel(BaseModel):' | |||||
134 |
|
137 | |||
135 | def update(self, user_id, form_data): |
|
138 | def update(self, user_id, form_data): | |
136 | try: |
|
139 | try: | |
137 |
|
|
140 | user = self.get(user_id, cache=False) | |
138 |
if |
|
141 | if user.username == 'default': | |
139 | raise DefaultUserException( |
|
142 | raise DefaultUserException( | |
140 | _("You can't Edit this user since it's" |
|
143 | _("You can't Edit this user since it's" | |
141 | " crucial for entire application")) |
|
144 | " crucial for entire application")) | |
142 |
|
145 | |||
143 | for k, v in form_data.items(): |
|
146 | for k, v in form_data.items(): | |
144 | if k == 'new_password' and v != '': |
|
147 | if k == 'new_password' and v != '': | |
145 |
|
|
148 | user.password = v | |
|
149 | user.api_key = generate_api_key(user.username) | |||
146 | else: |
|
150 | else: | |
147 |
setattr( |
|
151 | setattr(user, k, v) | |
148 |
|
152 | |||
149 |
self.sa.add( |
|
153 | self.sa.add(user) | |
150 | self.sa.commit() |
|
154 | self.sa.commit() | |
151 | except: |
|
155 | except: | |
152 | log.error(traceback.format_exc()) |
|
156 | log.error(traceback.format_exc()) | |
@@ -155,19 +159,20 b' class UserModel(BaseModel):' | |||||
155 |
|
159 | |||
156 | def update_my_account(self, user_id, form_data): |
|
160 | def update_my_account(self, user_id, form_data): | |
157 | try: |
|
161 | try: | |
158 |
|
|
162 | user = self.get(user_id, cache=False) | |
159 |
if |
|
163 | if user.username == 'default': | |
160 | raise DefaultUserException( |
|
164 | raise DefaultUserException( | |
161 | _("You can't Edit this user since it's" |
|
165 | _("You can't Edit this user since it's" | |
162 | " crucial for entire application")) |
|
166 | " crucial for entire application")) | |
163 | for k, v in form_data.items(): |
|
167 | for k, v in form_data.items(): | |
164 | if k == 'new_password' and v != '': |
|
168 | if k == 'new_password' and v != '': | |
165 |
|
|
169 | user.password = v | |
|
170 | user.api_key = generate_api_key(user.username) | |||
166 | else: |
|
171 | else: | |
167 | if k not in ['admin', 'active']: |
|
172 | if k not in ['admin', 'active']: | |
168 |
setattr( |
|
173 | setattr(user, k, v) | |
169 |
|
174 | |||
170 |
self.sa.add( |
|
175 | self.sa.add(user) | |
171 | self.sa.commit() |
|
176 | self.sa.commit() | |
172 | except: |
|
177 | except: | |
173 | log.error(traceback.format_exc()) |
|
178 | log.error(traceback.format_exc()) |
@@ -858,7 +858,7 b' padding:0 0 8px;' | |||||
858 | padding:0 0 8px !important; |
|
858 | padding:0 0 8px !important; | |
859 | } |
|
859 | } | |
860 |
|
860 | |||
861 | #content div.box div.form div.fields div.field div.label label { |
|
861 | #content div.box div.form div.fields div.field div.label label, div.label label{ | |
862 | color:#393939; |
|
862 | color:#393939; | |
863 | font-weight:700; |
|
863 | font-weight:700; | |
864 | } |
|
864 | } |
@@ -26,19 +26,23 b'' | |||||
26 | <!-- end box / title --> |
|
26 | <!-- end box / title --> | |
27 | ${h.form(url('user', id=c.user.user_id),method='put')} |
|
27 | ${h.form(url('user', id=c.user.user_id),method='put')} | |
28 | <div class="form"> |
|
28 | <div class="form"> | |
29 |
< |
|
29 | <div class="field"> | |
|
30 | <div class="gravatar_box"> | |||
|
31 | <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(c.user.email)}"/></div> | |||
|
32 | <p> | |||
|
33 | <strong>Change your avatar at <a href="http://gravatar.com">gravatar.com</a></strong><br/> | |||
|
34 | ${_('Using')} ${c.user.email} | |||
|
35 | </p> | |||
|
36 | </div> | |||
|
37 | </div> | |||
|
38 | <div class="field"> | |||
|
39 | <div class="label"> | |||
|
40 | <label>${_('API key')}</label> ${c.user.api_key} | |||
|
41 | </div> | |||
|
42 | </div> | |||
|
43 | ||||
30 | <div class="fields"> |
|
44 | <div class="fields"> | |
31 | <div class="field"> |
|
45 | <div class="field"> | |
32 | <div class="gravatar_box"> |
|
|||
33 | <div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(c.user.email)}"/></div> |
|
|||
34 | <p> |
|
|||
35 | <strong>Change your avatar at <a href="http://gravatar.com">gravatar.com</a></strong><br/> |
|
|||
36 | ${_('Using')} ${c.user.email} |
|
|||
37 | </p> |
|
|||
38 | </div> |
|
|||
39 | </div> |
|
|||
40 |
|
||||
41 | <div class="field"> |
|
|||
42 | <div class="label"> |
|
46 | <div class="label"> | |
43 | <label for="username">${_('Username')}:</label> |
|
47 | <label for="username">${_('Username')}:</label> | |
44 | </div> |
|
48 | </div> | |
@@ -52,7 +56,7 b'' | |||||
52 | <label for="ldap_dn">${_('LDAP DN')}:</label> |
|
56 | <label for="ldap_dn">${_('LDAP DN')}:</label> | |
53 | </div> |
|
57 | </div> | |
54 | <div class="input"> |
|
58 | <div class="input"> | |
55 |
${h.text('ldap_dn',class_=' |
|
59 | ${h.text('ldap_dn',class_='medium')} | |
56 | </div> |
|
60 | </div> | |
57 | </div> |
|
61 | </div> | |
58 |
|
62 | |||
@@ -122,122 +126,24 b'' | |||||
122 | <div class="title"> |
|
126 | <div class="title"> | |
123 | <h5>${_('Permissions')}</h5> |
|
127 | <h5>${_('Permissions')}</h5> | |
124 | </div> |
|
128 | </div> | |
125 | <form id="map_form" method="post" action="{%url update_permissions %}"> |
|
129 | ${h.form(url('user', id=c.user.user_id),method='put')} | |
126 |
|
|
130 | <div class="form"> | |
127 | <div class="fields"> |
|
131 | <!-- fields --> | |
128 |
|
132 | <div class="fields"> | ||
129 |
|
133 | <div class="field"> | ||
130 |
|
134 | <div class="label label-checkbox"> | ||
131 | <table> |
|
135 | <label for="">${_('Create repositories')}:</label> | |
132 | <tr> |
|
136 | </div> | |
133 | <td class="label">${_('Permissions')}:</td> |
|
137 | <div class="checkboxes"> | |
134 | <td> |
|
138 | ${h.checkbox('create',value=True)} | |
135 |
|
|
139 | </div> | |
136 | <div style="float:left"> |
|
140 | </div> | |
137 | <div class="text">${_('Granted permissions')}</div> |
|
141 | <div class="buttons"> | |
138 | ${h.select('granted_permissions',[],c.granted_permissions,multiple=True,size=8,style="min-width:210px")} |
|
142 | ${h.submit('save','Save',class_="ui-button")} | |
139 | </div> |
|
143 | ${h.reset('reset','Reset',class_="ui-button")} | |
140 | <div style="float:left;width:20px;padding-top:50px"> |
|
144 | </div> | |
141 | <img alt="add" id="add_element" |
|
145 | </div> | |
142 | style="padding:2px;cursor:pointer" |
|
146 | </div> | |
143 | src="${h.url("/images/icons/arrow_left.png")}"> |
|
147 | ${h.end_form()} | |
144 | <br /> |
|
|||
145 | <img alt="remove" id="remove_element" |
|
|||
146 | style="padding:2px;cursor:pointer" |
|
|||
147 | src="${h.url("/images/icons/arrow_right.png")}"> |
|
|||
148 | </div> |
|
|||
149 | <div style="float:left"> |
|
|||
150 | <div class="text">${_('Available permissions')}</div> |
|
|||
151 | ${h.select('available_permissions',[],c.available_permissions,multiple=True,size=8,style="min-width:210px")} |
|
|||
152 | </div> |
|
|||
153 | </div> |
|
|||
154 | </td> |
|
|||
155 | </tr> |
|
|||
156 |
|
||||
157 | </table> |
|
|||
158 | <div class="buttons"> |
|
|||
159 | ${h.submit('Save','Save',class_="ui-button")} |
|
|||
160 | </div> |
|
|||
161 | </div> |
|
|||
162 | </div> |
|
|||
163 | </form> |
|
|||
164 |
|
||||
165 |
|
||||
166 | <script type="text/javascript"> |
|
|||
167 | YAHOO.util.Event.onDOMReady(function(){ |
|
|||
168 |
|
||||
169 | var D = YAHOO.util.Dom; |
|
|||
170 | var E = YAHOO.util.Event; |
|
|||
171 |
|
||||
172 | //temp container for storage. |
|
|||
173 | var cache = new Array(); |
|
|||
174 | var c = D.get('id_granted_permissions'); |
|
|||
175 |
|
||||
176 | //get only selected options for further fullfilment |
|
|||
177 | for(var i = 0;node =c.options[i];i++){ |
|
|||
178 | if(node.selected){ |
|
|||
179 | //push selected to my temp storage left overs :) |
|
|||
180 | cache.push(node); |
|
|||
181 | } |
|
|||
182 | } |
|
|||
183 |
|
||||
184 | //clear select |
|
|||
185 | c.options.length = 0; |
|
|||
186 |
|
||||
187 | //fill it with remembered options |
|
|||
188 | for(var i = 0;node = cache[i];i++){ |
|
|||
189 | c.options[i]=new Option(node.text, node.value, false, false); |
|
|||
190 | } |
|
|||
191 |
|
||||
192 | function target_callback(e){ |
|
|||
193 | window.location='/admin/t4?g='+e.target.value; |
|
|||
194 | } |
|
|||
195 |
|
||||
196 | function prompts_action_callback(e){ |
|
|||
197 |
|
||||
198 | var choosen = D.get('id_granted_permissions'); |
|
|||
199 | var availible = D.get('id_available_permissions'); |
|
|||
200 |
|
||||
201 | if (this.id=='add_element'){ |
|
|||
202 | for(var i=0; node = availible.options[i];i++){ |
|
|||
203 | if(node.selected){ |
|
|||
204 | choosen.appendChild(new Option(node.text, node.value, false, false)); |
|
|||
205 | } |
|
|||
206 | } |
|
|||
207 | } |
|
|||
208 | else if (this.id=='remove_element'){ |
|
|||
209 |
|
||||
210 | //temp container for storage. |
|
|||
211 | cache = new Array(); |
|
|||
212 |
|
||||
213 | for(var i = 0;node = choosen.options[i];i++){ |
|
|||
214 | if(!node.selected){ |
|
|||
215 | //push left overs :) |
|
|||
216 | cache.push(node); |
|
|||
217 | } |
|
|||
218 | } |
|
|||
219 | //clear select |
|
|||
220 | choosen.options.length = 0; |
|
|||
221 | for(var i = 0;node = cache[i];i++){ |
|
|||
222 | choosen.options[i]=new Option(node.text, node.value, false, false); |
|
|||
223 | } |
|
|||
224 | } |
|
|||
225 | else{ |
|
|||
226 |
|
||||
227 | } |
|
|||
228 | } |
|
|||
229 |
|
||||
230 | E.addListener('id_groups','change',target_callback); |
|
|||
231 |
|
||||
232 | E.addListener(['add_element','remove_element'],'click',prompts_action_callback) |
|
|||
233 |
|
||||
234 | E.addListener('map_form','submit',function(){ |
|
|||
235 | var choosen = D.get('id_granted_permissions'); |
|
|||
236 | for (var i = 0; i < choosen.options.length; i++) { |
|
|||
237 | choosen.options[i].selected = 'selected'; |
|
|||
238 | } |
|
|||
239 | }) |
|
|||
240 | }); |
|
|||
241 | </script> |
|
|||
242 | </div> |
|
148 | </div> | |
243 | </%def> |
|
149 | </%def> |
@@ -34,7 +34,11 b'' | |||||
34 | </p> |
|
34 | </p> | |
35 | </div> |
|
35 | </div> | |
36 | </div> |
|
36 | </div> | |
37 |
|
37 | <div class="field"> | ||
|
38 | <div class="label"> | |||
|
39 | <label>${_('API key')}</label> ${c.user.api_key} | |||
|
40 | </div> | |||
|
41 | </div> | |||
38 | <div class="fields"> |
|
42 | <div class="fields"> | |
39 | <div class="field"> |
|
43 | <div class="field"> | |
40 | <div class="label"> |
|
44 | <div class="label"> |
General Comments 0
You need to be logged in to leave comments.
Login now