Show More
@@ -0,0 +1,63 b'' | |||||
|
1 | # -*- coding: utf-8 -*- | |||
|
2 | """ | |||
|
3 | rhodecode.model.users_group | |||
|
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |||
|
5 | ||||
|
6 | repository permission model for RhodeCode | |||
|
7 | ||||
|
8 | :created_on: Oct 1, 2011 | |||
|
9 | :author: nvinot | |||
|
10 | :copyright: (C) 2011-2011 Nicolas Vinot <aeris@imirhil.fr> | |||
|
11 | :license: GPLv3, see COPYING for more details. | |||
|
12 | """ | |||
|
13 | # This program is free software: you can redistribute it and/or modify | |||
|
14 | # it under the terms of the GNU General Public License as published by | |||
|
15 | # the Free Software Foundation, either version 3 of the License, or | |||
|
16 | # (at your option) any later version. | |||
|
17 | # | |||
|
18 | # This program is distributed in the hope that it will be useful, | |||
|
19 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
20 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
21 | # GNU General Public License for more details. | |||
|
22 | # | |||
|
23 | # You should have received a copy of the GNU General Public License | |||
|
24 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
|
25 | ||||
|
26 | import logging | |||
|
27 | from rhodecode.model.db import BaseModel, RepoToPerm, Permission | |||
|
28 | from rhodecode.model.meta import Session | |||
|
29 | ||||
|
30 | log = logging.getLogger(__name__) | |||
|
31 | ||||
|
32 | class RepositoryPermissionModel(BaseModel): | |||
|
33 | def get_user_permission(self, repository, user): | |||
|
34 | return RepoToPerm.query() \ | |||
|
35 | .filter(RepoToPerm.user == user) \ | |||
|
36 | .filter(RepoToPerm.repository == repository) \ | |||
|
37 | .scalar() | |||
|
38 | ||||
|
39 | def update_user_permission(self, repository, user, permission): | |||
|
40 | permission = Permission.get_by_key(permission) | |||
|
41 | current = self.get_user_permission(repository, user) | |||
|
42 | if current: | |||
|
43 | if not current.permission is permission: | |||
|
44 | current.permission = permission | |||
|
45 | else: | |||
|
46 | p = RepoToPerm() | |||
|
47 | p.user = user | |||
|
48 | p.repository = repository | |||
|
49 | p.permission = permission | |||
|
50 | Session.add(p) | |||
|
51 | Session.commit() | |||
|
52 | ||||
|
53 | def delete_user_permission(self, repository, user): | |||
|
54 | current = self.get_user_permission(repository, user) | |||
|
55 | if current: | |||
|
56 | Session.delete(current) | |||
|
57 | Session.commit() | |||
|
58 | ||||
|
59 | def update_or_delete_user_permission(self, repository, user, permission): | |||
|
60 | if permission: | |||
|
61 | self.update_user_permission(repository, user, permission) | |||
|
62 | else: | |||
|
63 | self.delete_user_permission(repository, user) |
@@ -0,0 +1,89 b'' | |||||
|
1 | # -*- coding: utf-8 -*- | |||
|
2 | """ | |||
|
3 | rhodecode.model.users_group | |||
|
4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |||
|
5 | ||||
|
6 | users group model for RhodeCode | |||
|
7 | ||||
|
8 | :created_on: Oct 1, 2011 | |||
|
9 | :author: nvinot | |||
|
10 | :copyright: (C) 2011-2011 Nicolas Vinot <aeris@imirhil.fr> | |||
|
11 | :license: GPLv3, see COPYING for more details. | |||
|
12 | """ | |||
|
13 | # This program is free software: you can redistribute it and/or modify | |||
|
14 | # it under the terms of the GNU General Public License as published by | |||
|
15 | # the Free Software Foundation, either version 3 of the License, or | |||
|
16 | # (at your option) any later version. | |||
|
17 | # | |||
|
18 | # This program is distributed in the hope that it will be useful, | |||
|
19 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
20 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
21 | # GNU General Public License for more details. | |||
|
22 | # | |||
|
23 | # You should have received a copy of the GNU General Public License | |||
|
24 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |||
|
25 | ||||
|
26 | import logging | |||
|
27 | import traceback | |||
|
28 | ||||
|
29 | from rhodecode.model import BaseModel | |||
|
30 | from rhodecode.model.caching_query import FromCache | |||
|
31 | from rhodecode.model.db import UsersGroupMember, UsersGroup | |||
|
32 | ||||
|
33 | log = logging.getLogger(__name__) | |||
|
34 | ||||
|
35 | class UsersGroupModel(BaseModel): | |||
|
36 | ||||
|
37 | def get(self, users_group_id, cache = False): | |||
|
38 | users_group = UsersGroup.query() | |||
|
39 | if cache: | |||
|
40 | users_group = users_group.options(FromCache("sql_cache_short", | |||
|
41 | "get_users_group_%s" % users_group_id)) | |||
|
42 | return users_group.get(users_group_id) | |||
|
43 | ||||
|
44 | def get_by_name(self, name, cache = False, case_insensitive = False): | |||
|
45 | users_group = UsersGroup.query() | |||
|
46 | if case_insensitive: | |||
|
47 | users_group = users_group.filter(UsersGroup.users_group_name.ilike(name)) | |||
|
48 | else: | |||
|
49 | users_group = users_group.filter(UsersGroup.users_group_name == name) | |||
|
50 | if cache: | |||
|
51 | users_group = users_group.options(FromCache("sql_cache_short", | |||
|
52 | "get_users_group_%s" % name)) | |||
|
53 | return users_group.scalar() | |||
|
54 | ||||
|
55 | def create(self, form_data): | |||
|
56 | try: | |||
|
57 | new_users_group = UsersGroup() | |||
|
58 | for k, v in form_data.items(): | |||
|
59 | setattr(new_users_group, k, v) | |||
|
60 | ||||
|
61 | self.sa.add(new_users_group) | |||
|
62 | self.sa.commit() | |||
|
63 | return new_users_group | |||
|
64 | except: | |||
|
65 | log.error(traceback.format_exc()) | |||
|
66 | self.sa.rollback() | |||
|
67 | raise | |||
|
68 | ||||
|
69 | def add_user_to_group(self, users_group, user): | |||
|
70 | for m in users_group.members: | |||
|
71 | u = m.user | |||
|
72 | if u.user_id == user.user_id: | |||
|
73 | return m | |||
|
74 | ||||
|
75 | try: | |||
|
76 | users_group_member = UsersGroupMember() | |||
|
77 | users_group_member.user = user | |||
|
78 | users_group_member.users_group = users_group | |||
|
79 | ||||
|
80 | users_group.members.append(users_group_member) | |||
|
81 | user.group_member.append(users_group_member) | |||
|
82 | ||||
|
83 | self.sa.add(users_group_member) | |||
|
84 | self.sa.commit() | |||
|
85 | return users_group_member | |||
|
86 | except: | |||
|
87 | log.error(traceback.format_exc()) | |||
|
88 | self.sa.rollback() | |||
|
89 | raise |
@@ -24,6 +24,8 b' pdebug = false' | |||||
24 | #smtp_port = |
|
24 | #smtp_port = | |
25 | #smtp_use_tls = false |
|
25 | #smtp_use_tls = false | |
26 | #smtp_use_ssl = true |
|
26 | #smtp_use_ssl = true | |
|
27 | # Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.) | |||
|
28 | #smtp_auth = | |||
27 |
|
29 | |||
28 | [server:main] |
|
30 | [server:main] | |
29 | ##nr of threads to spawn |
|
31 | ##nr of threads to spawn |
@@ -58,7 +58,9 b' INPUT::' | |||||
58 |
|
58 | |||
59 | api_key:"<api_key>" |
|
59 | api_key : "<api_key>" | |
60 | method: "pull" |
|
60 | method : "pull" | |
61 | args: {"repo":<repo_name>} |
|
61 | args : { | |
|
62 | "repo" : "<repo_name>" | |||
|
63 | } | |||
62 |
|
64 | |||
63 | OUTPUT:: |
|
65 | OUTPUT:: | |
64 |
|
66 | |||
@@ -66,46 +68,295 b' OUTPUT::' | |||||
66 | error:null |
|
68 | error : null | |
67 |
|
69 | |||
68 |
|
70 | |||
|
71 | get_users | |||
|
72 | --------- | |||
|
73 | ||||
|
74 | Lists all existing users. This command can be executed only using api_key | |||
|
75 | belonging to user with admin rights. | |||
|
76 | ||||
|
77 | INPUT:: | |||
|
78 | ||||
|
79 | api_key : "<api_key>" | |||
|
80 | method : "get_users" | |||
|
81 | args : { } | |||
|
82 | ||||
|
83 | OUTPUT:: | |||
|
84 | ||||
|
85 | result: [ | |||
|
86 | { | |||
|
87 | "id" : "<id>", | |||
|
88 | "username" : "<username>", | |||
|
89 | "firstname": "<firstname>", | |||
|
90 | "lastname" : "<lastname>", | |||
|
91 | "email" : "<email>", | |||
|
92 | "active" : "<bool>", | |||
|
93 | "admin" :Â "<bool>", | |||
|
94 | "ldap" : "<ldap_dn>" | |||
|
95 | }, | |||
|
96 | … | |||
|
97 | ] | |||
|
98 | error: null | |||
|
99 | ||||
69 | create_user |
|
100 | create_user | |
70 | ----------- |
|
101 | ----------- | |
71 |
|
102 | |||
72 |
Creates new user in RhodeCode. This command can be executed only using api_key |
|
103 | Creates new user in RhodeCode. This command can be executed only using api_key | |
73 | belonging to user with admin rights |
|
104 | belonging to user with admin rights. | |
74 |
|
105 | |||
75 | INPUT:: |
|
106 | INPUT:: | |
76 |
|
107 | |||
77 | api_key:"<api_key>" |
|
108 | api_key : "<api_key>" | |
78 | method: "create_user" |
|
109 | method : "create_user" | |
79 | args: {"username": "<username>", |
|
110 | args : { | |
|
111 | "username" : "<username>", | |||
80 |
"password": "<password>", |
|
112 | "password" : "<password>", | |
81 | "active": "<bool>", |
|
113 | "firstname" : "<firstname>", | |
82 | "admin": "<bool>", |
|
|||
83 | "name": "<firstname>", |
|
|||
84 |
"lastname": "<lastname>", |
|
114 | "lastname" : "<lastname>", | |
85 |
"email": "<useremail>" |
|
115 | "email" : "<useremail>" | |
|
116 | "active" : "<bool> = True", | |||
|
117 | "admin" : "<bool> = False", | |||
|
118 | "ldap_dn" : "<ldap_dn> = None" | |||
|
119 | } | |||
|
120 | ||||
|
121 | OUTPUT:: | |||
|
122 | ||||
|
123 | result: { | |||
|
124 | "msg" : "created new user <username>" | |||
|
125 | } | |||
|
126 | error: null | |||
|
127 | ||||
|
128 | get_users_groups | |||
|
129 | ---------------- | |||
|
130 | ||||
|
131 | Lists all existing users groups. This command can be executed only using api_key | |||
|
132 | belonging to user with admin rights. | |||
|
133 | ||||
|
134 | INPUT:: | |||
|
135 | ||||
|
136 | api_key : "<api_key>" | |||
|
137 | method : "get_users_groups" | |||
|
138 | args : { } | |||
86 |
|
139 | |||
87 | OUTPUT:: |
|
140 | OUTPUT:: | |
88 |
|
141 | |||
89 | result:{"id": <newuserid>, |
|
142 | result : [ | |
90 | "msg":"created new user <username>"} |
|
143 | { | |
|
144 | "id" : "<id>", | |||
|
145 | "name" : "<name>", | |||
|
146 | "active": "<bool>", | |||
|
147 | "members" : [ | |||
|
148 | { | |||
|
149 | "id" : "<userid>", | |||
|
150 | "username" : "<username>", | |||
|
151 | "firstname": "<firstname>", | |||
|
152 | "lastname" : "<lastname>", | |||
|
153 | "email" : "<email>", | |||
|
154 | "active" : "<bool>", | |||
|
155 | "admin" :Â "<bool>", | |||
|
156 | "ldap" : "<ldap_dn>" | |||
|
157 | }, | |||
|
158 | … | |||
|
159 | ] | |||
|
160 | } | |||
|
161 | ] | |||
91 | error:null |
|
162 | error : null | |
92 |
|
163 | |||
|
164 | get_users_group | |||
|
165 | --------------- | |||
|
166 | ||||
|
167 | Gets an existing users group. This command can be executed only using api_key | |||
|
168 | belonging to user with admin rights. | |||
|
169 | ||||
|
170 | INPUT:: | |||
|
171 | ||||
|
172 | api_key : "<api_key>" | |||
|
173 | method : "get_users_group" | |||
|
174 | args : { | |||
|
175 | "group_name" : "<name>" | |||
|
176 | } | |||
|
177 | ||||
|
178 | OUTPUT:: | |||
|
179 | ||||
|
180 | result : None if group not exist | |||
|
181 | { | |||
|
182 | "id" : "<id>", | |||
|
183 | "name" : "<name>", | |||
|
184 | "active": "<bool>", | |||
|
185 | "members" : [ | |||
|
186 | { "id" : "<userid>", | |||
|
187 | "username" : "<username>", | |||
|
188 | "firstname": "<firstname>", | |||
|
189 | "lastname" : "<lastname>", | |||
|
190 | "email" : "<email>", | |||
|
191 | "active" : "<bool>", | |||
|
192 | "admin" :Â "<bool>", | |||
|
193 | "ldap" : "<ldap_dn>" | |||
|
194 | }, | |||
|
195 | … | |||
|
196 | ] | |||
|
197 | } | |||
|
198 | error : null | |||
93 |
|
199 | |||
94 | create_users_group |
|
200 | create_users_group | |
95 | ------------------ |
|
201 | ------------------ | |
96 |
|
202 | |||
97 |
|
|
203 | Creates new users group. This command can be executed only using api_key | |
|
204 | belonging to user with admin rights | |||
|
205 | ||||
|
206 | INPUT:: | |||
|
207 | ||||
|
208 | api_key : "<api_key>" | |||
|
209 | method : "create_users_group" | |||
|
210 | args: { | |||
|
211 | "name": "<name>", | |||
|
212 | "active":"<bool> = True" | |||
|
213 | } | |||
|
214 | ||||
|
215 | OUTPUT:: | |||
|
216 | ||||
|
217 | result: { | |||
|
218 | "id": "<newusersgroupid>", | |||
|
219 | "msg": "created new users group <name>" | |||
|
220 | } | |||
|
221 | error: null | |||
|
222 | ||||
|
223 | add_user_to_users_groups | |||
|
224 | ------------------------ | |||
|
225 | ||||
|
226 | Adds a user to a users group. This command can be executed only using api_key | |||
98 | belonging to user with admin rights |
|
227 | belonging to user with admin rights | |
99 |
|
228 | |||
100 | INPUT:: |
|
229 | INPUT:: | |
101 |
|
230 | |||
102 | api_key:"<api_key>" |
|
231 | api_key : "<api_key>" | |
103 |
method |
|
232 | method : "add_user_users_group" | |
104 | args: {"name": "<groupname>", |
|
233 | args: { | |
105 | "active":"<bool>"} |
|
234 | "group_name" : "<groupname>", | |
|
235 | "user_name" : "<username>" | |||
|
236 | } | |||
|
237 | ||||
|
238 | OUTPUT:: | |||
|
239 | ||||
|
240 | result: { | |||
|
241 | "id": "<newusersgroupmemberid>", | |||
|
242 | "msg": "created new users group member" | |||
|
243 | } | |||
|
244 | error: null | |||
|
245 | ||||
|
246 | get_repos | |||
|
247 | --------- | |||
|
248 | ||||
|
249 | Lists all existing repositories. This command can be executed only using api_key | |||
|
250 | belonging to user with admin rights | |||
|
251 | ||||
|
252 | INPUT:: | |||
|
253 | ||||
|
254 | api_key : "<api_key>" | |||
|
255 | method : "get_repos" | |||
|
256 | args: { } | |||
|
257 | ||||
|
258 | OUTPUT:: | |||
|
259 | ||||
|
260 | result: [ | |||
|
261 | { | |||
|
262 | "id" : "<id>", | |||
|
263 | "name" : "<name>" | |||
|
264 | "type" : "<type>", | |||
|
265 | "description" : "<description>" | |||
|
266 | }, | |||
|
267 | … | |||
|
268 | ] | |||
|
269 | error: null | |||
|
270 | ||||
|
271 | get_repo | |||
|
272 | -------- | |||
|
273 | ||||
|
274 | Gets an existing repository. This command can be executed only using api_key | |||
|
275 | belonging to user with admin rights | |||
|
276 | ||||
|
277 | INPUT:: | |||
|
278 | ||||
|
279 | api_key : "<api_key>" | |||
|
280 | method : "get_repo" | |||
|
281 | args: { | |||
|
282 | "name" : "<name>" | |||
|
283 | } | |||
106 |
|
284 | |||
107 | OUTPUT:: |
|
285 | OUTPUT:: | |
108 |
|
286 | |||
109 | result:{"id": <newusersgroupid>, |
|
287 | result: None if repository not exist | |
110 | "msg":"created new users group <groupname>"} |
|
288 | { | |
|
289 | "id" : "<id>", | |||
|
290 | "name" : "<name>" | |||
|
291 | "type" : "<type>", | |||
|
292 | "description" : "<description>", | |||
|
293 | "members" : [ | |||
|
294 | { "id" : "<userid>", | |||
|
295 | "username" : "<username>", | |||
|
296 | "firstname": "<firstname>", | |||
|
297 | "lastname" : "<lastname>", | |||
|
298 | "email" : "<email>", | |||
|
299 | "active" : "<bool>", | |||
|
300 | "admin" :Â "<bool>", | |||
|
301 | "ldap" : "<ldap_dn>", | |||
|
302 | "permission" : "repository_(read|write|admin)" | |||
|
303 | }, | |||
|
304 | … | |||
|
305 | { | |||
|
306 | "id" : "<usersgroupid>", | |||
|
307 | "name" : "<usersgroupname>", | |||
|
308 | "active": "<bool>", | |||
|
309 | "permission" : "repository_(read|write|admin)" | |||
|
310 | }, | |||
|
311 | … | |||
|
312 | ] | |||
|
313 | } | |||
111 |
error:null |
|
314 | error: null | |
|
315 | ||||
|
316 | create_repo | |||
|
317 | ----------- | |||
|
318 | ||||
|
319 | Creates a repository. This command can be executed only using api_key | |||
|
320 | belonging to user with admin rights. | |||
|
321 | If repository name contains "/", all needed repository groups will be created. | |||
|
322 | For example "foo/bar/baz" will create groups "foo", "bar" (with "foo" as parent), | |||
|
323 | and create "baz" repository with "bar" as group. | |||
|
324 | ||||
|
325 | INPUT:: | |||
|
326 | ||||
|
327 | api_key : "<api_key>" | |||
|
328 | method : "create_repo" | |||
|
329 | args: { | |||
|
330 | "name" : "<name>", | |||
|
331 | "owner_name" : "<ownername>", | |||
|
332 | "description" : "<description> = ''", | |||
|
333 | "repo_type" : "<type> = 'hg'", | |||
|
334 | "private" : "<bool> = False" | |||
|
335 | } | |||
|
336 | ||||
|
337 | OUTPUT:: | |||
|
338 | ||||
|
339 | result: None | |||
|
340 | error: null | |||
|
341 | ||||
|
342 | add_user_to_repo | |||
|
343 | ---------------- | |||
|
344 | ||||
|
345 | Add a user to a repository. This command can be executed only using api_key | |||
|
346 | belonging to user with admin rights. | |||
|
347 | If "perm" is None, user will be removed from the repository. | |||
|
348 | ||||
|
349 | INPUT:: | |||
|
350 | ||||
|
351 | api_key : "<api_key>" | |||
|
352 | method : "add_user_to_repo" | |||
|
353 | args: { | |||
|
354 | "repo_name" : "<reponame>", | |||
|
355 | "user_name" : "<username>", | |||
|
356 | "perm" : "(None|repository_(read|write|admin))", | |||
|
357 | } | |||
|
358 | ||||
|
359 | OUTPUT:: | |||
|
360 | ||||
|
361 | result: None | |||
|
362 | error: null |
@@ -24,6 +24,8 b' pdebug = false' | |||||
24 | #smtp_port = |
|
24 | #smtp_port = | |
25 | #smtp_use_tls = false |
|
25 | #smtp_use_tls = false | |
26 | #smtp_use_ssl = true |
|
26 | #smtp_use_ssl = true | |
|
27 | # Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.) | |||
|
28 | #smtp_auth = | |||
27 |
|
29 | |||
28 | [server:main] |
|
30 | [server:main] | |
29 | ##nr of threads to spawn |
|
31 | ##nr of threads to spawn |
@@ -24,6 +24,8 b' pdebug = false' | |||||
24 | #smtp_port = |
|
24 | #smtp_port = | |
25 | #smtp_use_tls = false |
|
25 | #smtp_use_tls = false | |
26 | #smtp_use_ssl = true |
|
26 | #smtp_use_ssl = true | |
|
27 | # Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.) | |||
|
28 | #smtp_auth = | |||
27 |
|
29 | |||
28 | [server:main] |
|
30 | [server:main] | |
29 | ##nr of threads to spawn |
|
31 | ##nr of threads to spawn | |
@@ -146,7 +148,7 b' logview.pylons.util = #eee' | |||||
146 | # SQLITE [default] |
|
148 | # SQLITE [default] | |
147 | sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db |
|
149 | sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db | |
148 |
|
150 | |||
149 | # POSTGRES |
|
151 | # POSTGRESQL | |
150 | # sqlalchemy.db1.url = postgresql://user:pass@localhost/rhodecode |
|
152 | # sqlalchemy.db1.url = postgresql://user:pass@localhost/rhodecode | |
151 |
|
153 | |||
152 | # MySQL |
|
154 | # MySQL |
@@ -26,7 +26,6 b'' | |||||
26 | import logging |
|
26 | import logging | |
27 | import traceback |
|
27 | import traceback | |
28 | import formencode |
|
28 | import formencode | |
29 | from operator import itemgetter |
|
|||
30 | from formencode import htmlfill |
|
29 | from formencode import htmlfill | |
31 |
|
30 | |||
32 | from paste.httpexceptions import HTTPInternalServerError |
|
31 | from paste.httpexceptions import HTTPInternalServerError | |
@@ -92,7 +91,7 b' class ReposController(BaseController):' | |||||
92 | return redirect(url('repos')) |
|
91 | return redirect(url('repos')) | |
93 |
|
92 | |||
94 | c.default_user_id = User.get_by_username('default').user_id |
|
93 | c.default_user_id = User.get_by_username('default').user_id | |
95 |
c.in_public_journal = |
|
94 | c.in_public_journal = UserFollowing.query()\ | |
96 | .filter(UserFollowing.user_id == c.default_user_id)\ |
|
95 | .filter(UserFollowing.user_id == c.default_user_id)\ | |
97 | .filter(UserFollowing.follows_repository == c.repo_info).scalar() |
|
96 | .filter(UserFollowing.follows_repository == c.repo_info).scalar() | |
98 |
|
97 | |||
@@ -110,30 +109,7 b' class ReposController(BaseController):' | |||||
110 | c.stats_percentage = '%.2f' % ((float((last_rev)) / |
|
109 | c.stats_percentage = '%.2f' % ((float((last_rev)) / | |
111 | c.repo_last_rev) * 100) |
|
110 | c.repo_last_rev) * 100) | |
112 |
|
111 | |||
113 | defaults = c.repo_info.get_dict() |
|
112 | defaults = RepoModel()._get_defaults(repo_name) | |
114 | group, repo_name = c.repo_info.groups_and_repo |
|
|||
115 | defaults['repo_name'] = repo_name |
|
|||
116 | defaults['repo_group'] = getattr(group[-1] if group else None, |
|
|||
117 | 'group_id', None) |
|
|||
118 |
|
||||
119 | #fill owner |
|
|||
120 | if c.repo_info.user: |
|
|||
121 | defaults.update({'user': c.repo_info.user.username}) |
|
|||
122 | else: |
|
|||
123 | replacement_user = self.sa.query(User)\ |
|
|||
124 | .filter(User.admin == True).first().username |
|
|||
125 | defaults.update({'user': replacement_user}) |
|
|||
126 |
|
||||
127 | #fill repository users |
|
|||
128 | for p in c.repo_info.repo_to_perm: |
|
|||
129 | defaults.update({'u_perm_%s' % p.user.username: |
|
|||
130 | p.permission.permission_name}) |
|
|||
131 |
|
||||
132 | #fill repository groups |
|
|||
133 | for p in c.repo_info.users_group_to_perm: |
|
|||
134 | defaults.update({'g_perm_%s' % p.users_group.users_group_name: |
|
|||
135 | p.permission.permission_name}) |
|
|||
136 |
|
||||
137 | return defaults |
|
113 | return defaults | |
138 |
|
114 | |||
139 | @HasPermissionAllDecorator('hg.admin') |
|
115 | @HasPermissionAllDecorator('hg.admin') |
@@ -2,10 +2,18 b' import traceback' | |||||
2 | import logging |
|
2 | import logging | |
3 |
|
3 | |||
4 | from rhodecode.controllers.api import JSONRPCController, JSONRPCError |
|
4 | from rhodecode.controllers.api import JSONRPCController, JSONRPCError | |
5 | from rhodecode.lib.auth import HasPermissionAllDecorator |
|
5 | from rhodecode.lib.auth import HasPermissionAllDecorator, \ | |
|
6 | HasPermissionAnyDecorator | |||
6 | from rhodecode.model.scm import ScmModel |
|
7 | from rhodecode.model.scm import ScmModel | |
7 |
|
8 | |||
8 | from rhodecode.model.db import User, UsersGroup, Repository |
|
9 | from rhodecode.model.db import User, UsersGroup, Group, Repository | |
|
10 | from rhodecode.model.repo import RepoModel | |||
|
11 | from rhodecode.model.user import UserModel | |||
|
12 | from rhodecode.model.repo_permission import RepositoryPermissionModel | |||
|
13 | from rhodecode.model.users_group import UsersGroupModel | |||
|
14 | from rhodecode.model import users_group | |||
|
15 | from rhodecode.model.repos_group import ReposGroupModel | |||
|
16 | from sqlalchemy.orm.exc import NoResultFound | |||
9 |
|
17 | |||
10 | log = logging.getLogger(__name__) |
|
18 | log = logging.getLogger(__name__) | |
11 |
|
19 | |||
@@ -45,54 +53,323 b' class ApiController(JSONRPCController):' | |||||
45 | except Exception: |
|
53 | except Exception: | |
46 | raise JSONRPCError('Unable to pull changes from "%s"' % repo) |
|
54 | raise JSONRPCError('Unable to pull changes from "%s"' % repo) | |
47 |
|
55 | |||
|
56 | @HasPermissionAllDecorator('hg.admin') | |||
|
57 | def get_user(self, apiuser, username): | |||
|
58 | """" | |||
|
59 | Get a user by username | |||
|
60 | ||||
|
61 | :param apiuser | |||
|
62 | :param username | |||
|
63 | """ | |||
|
64 | ||||
|
65 | user = User.get_by_username(username) | |||
|
66 | if not user: | |||
|
67 | return None | |||
|
68 | ||||
|
69 | return dict(id=user.user_id, | |||
|
70 | username=user.username, | |||
|
71 | firstname=user.name, | |||
|
72 | lastname=user.lastname, | |||
|
73 | email=user.email, | |||
|
74 | active=user.active, | |||
|
75 | admin=user.admin, | |||
|
76 | ldap=user.ldap_dn) | |||
48 |
|
77 | |||
49 | @HasPermissionAllDecorator('hg.admin') |
|
78 | @HasPermissionAllDecorator('hg.admin') | |
50 | def create_user(self, apiuser, username, password, active, admin, name, |
|
79 | def get_users(self, apiuser): | |
51 | lastname, email): |
|
80 | """" | |
|
81 | Get all users | |||
|
82 | ||||
|
83 | :param apiuser | |||
52 |
|
|
84 | """ | |
53 | Creates new user |
|
85 | ||
|
86 | result = [] | |||
|
87 | for user in User.getAll(): | |||
|
88 | result.append(dict(id=user.user_id, | |||
|
89 | username=user.username, | |||
|
90 | firstname=user.name, | |||
|
91 | lastname=user.lastname, | |||
|
92 | email=user.email, | |||
|
93 | active=user.active, | |||
|
94 | admin=user.admin, | |||
|
95 | ldap=user.ldap_dn)) | |||
|
96 | return result | |||
|
97 | ||||
|
98 | @HasPermissionAllDecorator('hg.admin') | |||
|
99 | def create_user(self, apiuser, username, password, firstname, | |||
|
100 | lastname, email, active=True, admin=False, ldap_dn=None): | |||
|
101 | """ | |||
|
102 | Create new user | |||
54 |
|
103 | |||
55 | :param apiuser: |
|
104 | :param apiuser: | |
56 | :param username: |
|
105 | :param username: | |
57 | :param password: |
|
106 | :param password: | |
58 | :param active: |
|
|||
59 | :param admin: |
|
|||
60 | :param name: |
|
107 | :param name: | |
61 | :param lastname: |
|
108 | :param lastname: | |
62 | :param email: |
|
109 | :param email: | |
|
110 | :param active: | |||
|
111 | :param admin: | |||
|
112 | :param ldap_dn: | |||
63 | """ |
|
113 | """ | |
64 |
|
114 | |||
|
115 | if self.get_user(apiuser, username): | |||
|
116 | raise JSONRPCError("user %s already exist" % username) | |||
|
117 | ||||
|
118 | try: | |||
65 | form_data = dict(username=username, |
|
119 | form_data = dict(username=username, | |
66 | password=password, |
|
120 | password=password, | |
67 | active=active, |
|
121 | active=active, | |
68 | admin=admin, |
|
122 | admin=admin, | |
69 | name=name, |
|
123 | name=firstname, | |
70 | lastname=lastname, |
|
124 | lastname=lastname, | |
71 |
email=email |
|
125 | email=email, | |
72 | try: |
|
126 | ldap_dn=ldap_dn) | |
73 |
u |
|
127 | UserModel().create_ldap(username, password, ldap_dn, form_data) | |
74 | return {'id':u.user_id, |
|
128 | return dict(msg='created new user %s' % username) | |
75 | 'msg':'created new user %s' % name} |
|
|||
76 | except Exception: |
|
129 | except Exception: | |
77 | log.error(traceback.format_exc()) |
|
130 | log.error(traceback.format_exc()) | |
78 | raise JSONRPCError('failed to create user %s' % name) |
|
131 | raise JSONRPCError('failed to create user %s' % username) | |
79 |
|
||||
80 |
|
132 | |||
81 | @HasPermissionAllDecorator('hg.admin') |
|
133 | @HasPermissionAllDecorator('hg.admin') | |
82 |
def |
|
134 | def get_users_group(self, apiuser, group_name): | |
|
135 | """" | |||
|
136 | Get users group by name | |||
|
137 | ||||
|
138 | :param apiuser | |||
|
139 | :param group_name | |||
|
140 | """ | |||
|
141 | ||||
|
142 | users_group = UsersGroup.get_by_group_name(group_name) | |||
|
143 | if not users_group: | |||
|
144 | return None | |||
|
145 | ||||
|
146 | members = [] | |||
|
147 | for user in users_group.members: | |||
|
148 | user = user.user | |||
|
149 | members.append(dict(id=user.user_id, | |||
|
150 | username=user.username, | |||
|
151 | firstname=user.name, | |||
|
152 | lastname=user.lastname, | |||
|
153 | email=user.email, | |||
|
154 | active=user.active, | |||
|
155 | admin=user.admin, | |||
|
156 | ldap=user.ldap_dn)) | |||
|
157 | ||||
|
158 | return dict(id=users_group.users_group_id, | |||
|
159 | name=users_group.users_group_name, | |||
|
160 | active=users_group.users_group_active, | |||
|
161 | members=members) | |||
|
162 | ||||
|
163 | @HasPermissionAllDecorator('hg.admin') | |||
|
164 | def get_users_groups(self, apiuser): | |||
|
165 | """" | |||
|
166 | Get all users groups | |||
|
167 | ||||
|
168 | :param apiuser | |||
|
169 | """ | |||
|
170 | ||||
|
171 | result = [] | |||
|
172 | for users_group in UsersGroup.getAll(): | |||
|
173 | members = [] | |||
|
174 | for user in users_group.members: | |||
|
175 | user = user.user | |||
|
176 | members.append(dict(id=user.user_id, | |||
|
177 | username=user.username, | |||
|
178 | firstname=user.name, | |||
|
179 | lastname=user.lastname, | |||
|
180 | email=user.email, | |||
|
181 | active=user.active, | |||
|
182 | admin=user.admin, | |||
|
183 | ldap=user.ldap_dn)) | |||
|
184 | ||||
|
185 | result.append(dict(id=users_group.users_group_id, | |||
|
186 | name=users_group.users_group_name, | |||
|
187 | active=users_group.users_group_active, | |||
|
188 | members=members)) | |||
|
189 | return result | |||
|
190 | ||||
|
191 | @HasPermissionAllDecorator('hg.admin') | |||
|
192 | def create_users_group(self, apiuser, name, active=True): | |||
83 | """ |
|
193 | """ | |
84 | Creates an new usergroup |
|
194 | Creates an new usergroup | |
85 |
|
195 | |||
86 | :param name: |
|
196 | :param name: | |
87 | :param active: |
|
197 | :param active: | |
88 | """ |
|
198 | """ | |
89 | form_data = {'users_group_name':name, |
|
199 | ||
90 | 'users_group_active':active} |
|
200 | if self.get_users_group(apiuser, name): | |
|
201 | raise JSONRPCError("users group %s already exist" % name) | |||
|
202 | ||||
91 | try: |
|
203 | try: | |
|
204 | form_data = dict(users_group_name=name, | |||
|
205 | users_group_active=active) | |||
92 | ug = UsersGroup.create(form_data) |
|
206 | ug = UsersGroup.create(form_data) | |
93 |
return |
|
207 | return dict(id=ug.users_group_id, | |
94 |
|
|
208 | msg='created new users group %s' % name) | |
95 | except Exception: |
|
209 | except Exception: | |
96 | log.error(traceback.format_exc()) |
|
210 | log.error(traceback.format_exc()) | |
97 | raise JSONRPCError('failed to create group %s' % name) |
|
211 | raise JSONRPCError('failed to create group %s' % name) | |
|
212 | ||||
|
213 | @HasPermissionAllDecorator('hg.admin') | |||
|
214 | def add_user_to_users_group(self, apiuser, group_name, user_name): | |||
|
215 | """" | |||
|
216 | Add a user to a group | |||
|
217 | ||||
|
218 | :param apiuser | |||
|
219 | :param group_name | |||
|
220 | :param user_name | |||
|
221 | """ | |||
|
222 | ||||
|
223 | try: | |||
|
224 | users_group = UsersGroup.get_by_group_name(group_name) | |||
|
225 | if not users_group: | |||
|
226 | raise JSONRPCError('unknown users group %s' % group_name) | |||
|
227 | ||||
|
228 | try: | |||
|
229 | user = User.get_by_username(user_name) | |||
|
230 | except NoResultFound: | |||
|
231 | raise JSONRPCError('unknown user %s' % user_name) | |||
|
232 | ||||
|
233 | ugm = UsersGroupModel().add_user_to_group(users_group, user) | |||
|
234 | ||||
|
235 | return dict(id=ugm.users_group_member_id, | |||
|
236 | msg='created new users group member') | |||
|
237 | except Exception: | |||
|
238 | log.error(traceback.format_exc()) | |||
|
239 | raise JSONRPCError('failed to create users group member') | |||
|
240 | ||||
|
241 | @HasPermissionAnyDecorator('hg.admin') | |||
|
242 | def get_repo(self, apiuser, repo_name): | |||
|
243 | """" | |||
|
244 | Get repository by name | |||
|
245 | ||||
|
246 | :param apiuser | |||
|
247 | :param repo_name | |||
|
248 | """ | |||
|
249 | ||||
|
250 | try: | |||
|
251 | repo = Repository.get_by_repo_name(repo_name) | |||
|
252 | except NoResultFound: | |||
|
253 | return None | |||
|
254 | ||||
|
255 | members = [] | |||
|
256 | for user in repo.repo_to_perm: | |||
|
257 | perm = user.permission.permission_name | |||
|
258 | user = user.user | |||
|
259 | members.append(dict(type_="user", | |||
|
260 | id=user.user_id, | |||
|
261 | username=user.username, | |||
|
262 | firstname=user.name, | |||
|
263 | lastname=user.lastname, | |||
|
264 | email=user.email, | |||
|
265 | active=user.active, | |||
|
266 | admin=user.admin, | |||
|
267 | ldap=user.ldap_dn, | |||
|
268 | permission=perm)) | |||
|
269 | for users_group in repo.users_group_to_perm: | |||
|
270 | perm = users_group.permission.permission_name | |||
|
271 | users_group = users_group.users_group | |||
|
272 | members.append(dict(type_="users_group", | |||
|
273 | id=users_group.users_group_id, | |||
|
274 | name=users_group.users_group_name, | |||
|
275 | active=users_group.users_group_active, | |||
|
276 | permission=perm)) | |||
|
277 | ||||
|
278 | return dict(id=repo.repo_id, | |||
|
279 | name=repo.repo_name, | |||
|
280 | type=repo.repo_type, | |||
|
281 | description=repo.description, | |||
|
282 | members=members) | |||
|
283 | ||||
|
284 | @HasPermissionAnyDecorator('hg.admin') | |||
|
285 | def get_repos(self, apiuser): | |||
|
286 | """" | |||
|
287 | Get all repositories | |||
|
288 | ||||
|
289 | :param apiuser | |||
|
290 | """ | |||
|
291 | ||||
|
292 | result = [] | |||
|
293 | for repository in Repository.getAll(): | |||
|
294 | result.append(dict(id=repository.repo_id, | |||
|
295 | name=repository.repo_name, | |||
|
296 | type=repository.repo_type, | |||
|
297 | description=repository.description)) | |||
|
298 | return result | |||
|
299 | ||||
|
300 | @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository') | |||
|
301 | def create_repo(self, apiuser, name, owner_name, description='', | |||
|
302 | repo_type='hg', private=False): | |||
|
303 | """ | |||
|
304 | Create a repository | |||
|
305 | ||||
|
306 | :param apiuser | |||
|
307 | :param name | |||
|
308 | :param description | |||
|
309 | :param type | |||
|
310 | :param private | |||
|
311 | :param owner_name | |||
|
312 | """ | |||
|
313 | ||||
|
314 | try: | |||
|
315 | try: | |||
|
316 | owner = User.get_by_username(owner_name) | |||
|
317 | except NoResultFound: | |||
|
318 | raise JSONRPCError('unknown user %s' % owner) | |||
|
319 | ||||
|
320 | if self.get_repo(apiuser, name): | |||
|
321 | raise JSONRPCError("repo %s already exist" % name) | |||
|
322 | ||||
|
323 | groups = name.split('/') | |||
|
324 | real_name = groups[-1] | |||
|
325 | groups = groups[:-1] | |||
|
326 | parent_id = None | |||
|
327 | for g in groups: | |||
|
328 | group = Group.get_by_group_name(g) | |||
|
329 | if not group: | |||
|
330 | group = ReposGroupModel().create(dict(group_name=g, | |||
|
331 | group_description='', | |||
|
332 | group_parent_id=parent_id)) | |||
|
333 | parent_id = group.group_id | |||
|
334 | ||||
|
335 | RepoModel().create(dict(repo_name=real_name, | |||
|
336 | repo_name_full=name, | |||
|
337 | description=description, | |||
|
338 | private=private, | |||
|
339 | repo_type=repo_type, | |||
|
340 | repo_group=parent_id, | |||
|
341 | clone_uri=None), owner) | |||
|
342 | except Exception: | |||
|
343 | log.error(traceback.format_exc()) | |||
|
344 | raise JSONRPCError('failed to create repository %s' % name) | |||
|
345 | ||||
|
346 | @HasPermissionAnyDecorator('hg.admin') | |||
|
347 | def add_user_to_repo(self, apiuser, repo_name, user_name, perm): | |||
|
348 | """ | |||
|
349 | Add permission for a user to a repository | |||
|
350 | ||||
|
351 | :param apiuser | |||
|
352 | :param repo_name | |||
|
353 | :param user_name | |||
|
354 | :param perm | |||
|
355 | """ | |||
|
356 | ||||
|
357 | try: | |||
|
358 | try: | |||
|
359 | repo = Repository.get_by_repo_name(repo_name) | |||
|
360 | except NoResultFound: | |||
|
361 | raise JSONRPCError('unknown repository %s' % repo) | |||
|
362 | ||||
|
363 | try: | |||
|
364 | user = User.get_by_username(user_name) | |||
|
365 | except NoResultFound: | |||
|
366 | raise JSONRPCError('unknown user %s' % user) | |||
|
367 | ||||
|
368 | RepositoryPermissionModel()\ | |||
|
369 | .update_or_delete_user_permission(repo, user, perm) | |||
|
370 | except Exception: | |||
|
371 | log.error(traceback.format_exc()) | |||
|
372 | raise JSONRPCError('failed to edit permission %(repo)s for %(user)s' | |||
|
373 | % dict(user=user_name, repo=repo_name)) | |||
|
374 | ||||
98 | No newline at end of file |
|
375 |
@@ -42,7 +42,7 b' from rhodecode.lib.utils import invalida' | |||||
42 |
|
42 | |||
43 | from rhodecode.model.forms import RepoSettingsForm, RepoForkForm |
|
43 | from rhodecode.model.forms import RepoSettingsForm, RepoForkForm | |
44 | from rhodecode.model.repo import RepoModel |
|
44 | from rhodecode.model.repo import RepoModel | |
45 |
from rhodecode.model.db import |
|
45 | from rhodecode.model.db import Group | |
46 |
|
46 | |||
47 | log = logging.getLogger(__name__) |
|
47 | log = logging.getLogger(__name__) | |
48 |
|
48 | |||
@@ -53,6 +53,14 b' class SettingsController(BaseRepoControl' | |||||
53 | def __before__(self): |
|
53 | def __before__(self): | |
54 | super(SettingsController, self).__before__() |
|
54 | super(SettingsController, self).__before__() | |
55 |
|
55 | |||
|
56 | def __load_defaults(self): | |||
|
57 | c.repo_groups = Group.groups_choices() | |||
|
58 | c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups) | |||
|
59 | ||||
|
60 | repo_model = RepoModel() | |||
|
61 | c.users_array = repo_model.get_users_js() | |||
|
62 | c.users_groups_array = repo_model.get_users_groups_js() | |||
|
63 | ||||
56 | @HasRepoPermissionAllDecorator('repository.admin') |
|
64 | @HasRepoPermissionAllDecorator('repository.admin') | |
57 | def index(self, repo_name): |
|
65 | def index(self, repo_name): | |
58 | repo_model = RepoModel() |
|
66 | repo_model = RepoModel() | |
@@ -66,28 +74,9 b' class SettingsController(BaseRepoControl' | |||||
66 |
|
74 | |||
67 | return redirect(url('home')) |
|
75 | return redirect(url('home')) | |
68 |
|
76 | |||
69 | c.users_array = repo_model.get_users_js() |
|
77 | self.__load_defaults() | |
70 | c.users_groups_array = repo_model.get_users_groups_js() |
|
|||
71 |
|
||||
72 | defaults = c.repo_info.get_dict() |
|
|||
73 |
|
78 | |||
74 | #fill owner |
|
79 | defaults = RepoModel()._get_defaults(repo_name) | |
75 | if c.repo_info.user: |
|
|||
76 | defaults.update({'user': c.repo_info.user.username}) |
|
|||
77 | else: |
|
|||
78 | replacement_user = self.sa.query(User)\ |
|
|||
79 | .filter(User.admin == True).first().username |
|
|||
80 | defaults.update({'user': replacement_user}) |
|
|||
81 |
|
||||
82 | #fill repository users |
|
|||
83 | for p in c.repo_info.repo_to_perm: |
|
|||
84 | defaults.update({'u_perm_%s' % p.user.username: |
|
|||
85 | p.permission.permission_name}) |
|
|||
86 |
|
||||
87 | #fill repository groups |
|
|||
88 | for p in c.repo_info.users_group_to_perm: |
|
|||
89 | defaults.update({'g_perm_%s' % p.users_group.users_group_name: |
|
|||
90 | p.permission.permission_name}) |
|
|||
91 |
|
80 | |||
92 | return htmlfill.render( |
|
81 | return htmlfill.render( | |
93 | render('settings/repo_settings.html'), |
|
82 | render('settings/repo_settings.html'), | |
@@ -100,15 +89,20 b' class SettingsController(BaseRepoControl' | |||||
100 | def update(self, repo_name): |
|
89 | def update(self, repo_name): | |
101 | repo_model = RepoModel() |
|
90 | repo_model = RepoModel() | |
102 | changed_name = repo_name |
|
91 | changed_name = repo_name | |
|
92 | ||||
|
93 | self.__load_defaults() | |||
|
94 | ||||
103 | _form = RepoSettingsForm(edit=True, |
|
95 | _form = RepoSettingsForm(edit=True, | |
104 |
old_data={'repo_name': repo_name} |
|
96 | old_data={'repo_name': repo_name}, | |
|
97 | repo_groups=c.repo_groups_choices)() | |||
105 | try: |
|
98 | try: | |
106 | form_result = _form.to_python(dict(request.POST)) |
|
99 | form_result = _form.to_python(dict(request.POST)) | |
|
100 | ||||
107 | repo_model.update(repo_name, form_result) |
|
101 | repo_model.update(repo_name, form_result) | |
108 | invalidate_cache('get_repo_cached_%s' % repo_name) |
|
102 | invalidate_cache('get_repo_cached_%s' % repo_name) | |
109 | h.flash(_('Repository %s updated successfully' % repo_name), |
|
103 | h.flash(_('Repository %s updated successfully' % repo_name), | |
110 | category='success') |
|
104 | category='success') | |
111 | changed_name = form_result['repo_name'] |
|
105 | changed_name = form_result['repo_name_full'] | |
112 | action_logger(self.rhodecode_user, 'user_updated_repo', |
|
106 | action_logger(self.rhodecode_user, 'user_updated_repo', | |
113 |
|
|
107 | changed_name, '', self.sa) | |
114 | except formencode.Invalid, errors: |
|
108 | except formencode.Invalid, errors: |
@@ -394,13 +394,12 b' def get_current_revision(quiet=False):' | |||||
394 | try: |
|
394 | try: | |
395 | from vcs import get_repo |
|
395 | from vcs import get_repo | |
396 | from vcs.utils.helpers import get_scm |
|
396 | from vcs.utils.helpers import get_scm | |
397 | from vcs.exceptions import RepositoryError, VCSError |
|
|||
398 | repopath = os.path.join(os.path.dirname(__file__), '..', '..') |
|
397 | repopath = os.path.join(os.path.dirname(__file__), '..', '..') | |
399 | scm = get_scm(repopath)[0] |
|
398 | scm = get_scm(repopath)[0] | |
400 | repo = get_repo(path=repopath, alias=scm) |
|
399 | repo = get_repo(path=repopath, alias=scm) | |
401 | tip = repo.get_changeset() |
|
400 | tip = repo.get_changeset() | |
402 | return (tip.revision, tip.short_id) |
|
401 | return (tip.revision, tip.short_id) | |
403 | except (ImportError, RepositoryError, VCSError), err: |
|
402 | except Exception, err: | |
404 | if not quiet: |
|
403 | if not quiet: | |
405 | print ("Cannot retrieve rhodecode's revision. Original error " |
|
404 | print ("Cannot retrieve rhodecode's revision. Original error " | |
406 | "was: %s" % err) |
|
405 | "was: %s" % err) |
@@ -54,7 +54,9 b' class AuthLdap(object):' | |||||
54 | port = port or 689 |
|
54 | port = port or 689 | |
55 | ldap_server_type = ldap_server_type + 's' |
|
55 | ldap_server_type = ldap_server_type + 's' | |
56 |
|
56 | |||
57 | self.TLS_REQCERT = ldap.__dict__['OPT_X_TLS_' + tls_reqcert] |
|
57 | OPT_X_TLS_DEMAND = 2 | |
|
58 | self.TLS_REQCERT = getattr(ldap, 'OPT_X_TLS_%s' % tls_reqcert, | |||
|
59 | OPT_X_TLS_DEMAND) | |||
58 | self.LDAP_SERVER_ADDRESS = server |
|
60 | self.LDAP_SERVER_ADDRESS = server | |
59 | self.LDAP_SERVER_PORT = port |
|
61 | self.LDAP_SERVER_PORT = port | |
60 |
|
62 | |||
@@ -68,7 +70,7 b' class AuthLdap(object):' | |||||
68 |
|
70 | |||
69 | self.BASE_DN = base_dn |
|
71 | self.BASE_DN = base_dn | |
70 | self.LDAP_FILTER = ldap_filter |
|
72 | self.LDAP_FILTER = ldap_filter | |
71 |
self.SEARCH_SCOPE = ldap |
|
73 | self.SEARCH_SCOPE = getattr(ldap, 'SCOPE_%s' % search_scope) | |
72 | self.attr_login = attr_login |
|
74 | self.attr_login = attr_login | |
73 |
|
75 | |||
74 | def authenticate_ldap(self, username, password): |
|
76 | def authenticate_ldap(self, username, password): | |
@@ -88,7 +90,9 b' class AuthLdap(object):' | |||||
88 | if "," in username: |
|
90 | if "," in username: | |
89 | raise LdapUsernameError("invalid character in username: ,") |
|
91 | raise LdapUsernameError("invalid character in username: ,") | |
90 | try: |
|
92 | try: | |
91 |
|
|
93 | if hasattr(ldap,'OPT_X_TLS_CACERTDIR'): | |
|
94 | ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, | |||
|
95 | '/etc/openldap/cacerts') | |||
92 | ldap.set_option(ldap.OPT_REFERRALS, ldap.OPT_OFF) |
|
96 | ldap.set_option(ldap.OPT_REFERRALS, ldap.OPT_OFF) | |
93 | ldap.set_option(ldap.OPT_RESTART, ldap.OPT_ON) |
|
97 | ldap.set_option(ldap.OPT_RESTART, ldap.OPT_ON) | |
94 | ldap.set_option(ldap.OPT_TIMEOUT, 20) |
|
98 | ldap.set_option(ldap.OPT_TIMEOUT, 20) |
@@ -356,9 +356,10 b' def send_email(recipients, subject, body' | |||||
356 | tls = str2bool(email_config.get('smtp_use_tls')) |
|
356 | tls = str2bool(email_config.get('smtp_use_tls')) | |
357 | ssl = str2bool(email_config.get('smtp_use_ssl')) |
|
357 | ssl = str2bool(email_config.get('smtp_use_ssl')) | |
358 | debug = str2bool(config.get('debug')) |
|
358 | debug = str2bool(config.get('debug')) | |
|
359 | smtp_auth = email_config.get('smtp_auth') | |||
359 |
|
360 | |||
360 | try: |
|
361 | try: | |
361 | m = SmtpMailer(mail_from, user, passwd, mail_server, |
|
362 | m = SmtpMailer(mail_from, user, passwd, mail_server,smtp_auth, | |
362 | mail_port, ssl, tls, debug=debug) |
|
363 | mail_port, ssl, tls, debug=debug) | |
363 | m.send(recipients, subject, body) |
|
364 | m.send(recipients, subject, body) | |
364 | except: |
|
365 | except: |
@@ -167,6 +167,8 b' class SimpleGit(object):' | |||||
167 | username = REMOTE_USER(environ) |
|
167 | username = REMOTE_USER(environ) | |
168 | try: |
|
168 | try: | |
169 | user = self.__get_user(username) |
|
169 | user = self.__get_user(username) | |
|
170 | if user is None: | |||
|
171 | return HTTPForbidden()(environ, start_response) | |||
170 | username = user.username |
|
172 | username = user.username | |
171 | except: |
|
173 | except: | |
172 | log.error(traceback.format_exc()) |
|
174 | log.error(traceback.format_exc()) |
@@ -133,6 +133,8 b' class SimpleHg(object):' | |||||
133 | username = REMOTE_USER(environ) |
|
133 | username = REMOTE_USER(environ) | |
134 | try: |
|
134 | try: | |
135 | user = self.__get_user(username) |
|
135 | user = self.__get_user(username) | |
|
136 | if user is None: | |||
|
137 | return HTTPForbidden()(environ, start_response) | |||
136 | username = user.username |
|
138 | username = user.username | |
137 | except: |
|
139 | except: | |
138 | log.error(traceback.format_exc()) |
|
140 | log.error(traceback.format_exc()) |
@@ -39,7 +39,7 b' from email import encoders' | |||||
39 | class SmtpMailer(object): |
|
39 | class SmtpMailer(object): | |
40 | """SMTP mailer class |
|
40 | """SMTP mailer class | |
41 |
|
41 | |||
42 | mailer = SmtpMailer(mail_from, user, passwd, mail_server, |
|
42 | mailer = SmtpMailer(mail_from, user, passwd, mail_server, smtp_auth | |
43 | mail_port, ssl, tls) |
|
43 | mail_port, ssl, tls) | |
44 | mailer.send(recipients, subject, body, attachment_files) |
|
44 | mailer.send(recipients, subject, body, attachment_files) | |
45 |
|
45 | |||
@@ -49,7 +49,7 b' class SmtpMailer(object):' | |||||
49 |
|
49 | |||
50 | """ |
|
50 | """ | |
51 |
|
51 | |||
52 | def __init__(self, mail_from, user, passwd, mail_server, |
|
52 | def __init__(self, mail_from, user, passwd, mail_server, smtp_auth=None, | |
53 |
|
|
53 | mail_port=None, ssl=False, tls=False, debug=False): | |
54 |
|
54 | |||
55 | self.mail_from = mail_from |
|
55 | self.mail_from = mail_from | |
@@ -60,6 +60,7 b' class SmtpMailer(object):' | |||||
60 | self.ssl = ssl |
|
60 | self.ssl = ssl | |
61 | self.tls = tls |
|
61 | self.tls = tls | |
62 | self.debug = debug |
|
62 | self.debug = debug | |
|
63 | self.auth = smtp_auth | |||
63 |
|
64 | |||
64 | def send(self, recipients=[], subject='', body='', attachment_files=None): |
|
65 | def send(self, recipients=[], subject='', body='', attachment_files=None): | |
65 |
|
66 | |||
@@ -78,6 +79,8 b' class SmtpMailer(object):' | |||||
78 | smtp_serv.set_debuglevel(1) |
|
79 | smtp_serv.set_debuglevel(1) | |
79 |
|
80 | |||
80 | smtp_serv.ehlo() |
|
81 | smtp_serv.ehlo() | |
|
82 | if self.auth: | |||
|
83 | smtp_serv.esmtp_features["auth"] = self.auth | |||
81 |
|
84 | |||
82 | #if server requires authorization you must provide login and password |
|
85 | # if server requires authorization you must provide login and password | |
83 | #but only if we have them |
|
86 | # but only if we have them | |
@@ -159,3 +162,4 b' class SmtpMailer(object):' | |||||
159 | #just for safe seek to 0 |
|
162 | # just for safe seek to 0 | |
160 | msg_file.seek(0) |
|
163 | msg_file.seek(0) | |
161 | return msg_file.read() |
|
164 | return msg_file.read() | |
|
165 |
@@ -30,11 +30,8 b' import traceback' | |||||
30 | from datetime import date |
|
30 | from datetime import date | |
31 |
|
31 | |||
32 | from sqlalchemy import * |
|
32 | from sqlalchemy import * | |
33 | from sqlalchemy.exc import DatabaseError |
|
|||
34 | from sqlalchemy.ext.hybrid import hybrid_property |
|
33 | from sqlalchemy.ext.hybrid import hybrid_property | |
35 |
from sqlalchemy.orm import relationship, |
|
34 | from sqlalchemy.orm import relationship, joinedload, class_mapper, validates | |
36 | validates |
|
|||
37 | from sqlalchemy.orm.interfaces import MapperExtension |
|
|||
38 | from beaker.cache import cache_region, region_invalidate |
|
35 | from beaker.cache import cache_region, region_invalidate | |
39 |
|
36 | |||
40 | from vcs import get_backend |
|
37 | from vcs import get_backend | |
@@ -129,11 +126,15 b' class BaseModel(object):' | |||||
129 | @classmethod |
|
126 | @classmethod | |
130 | def get(cls, id_): |
|
127 | def get(cls, id_): | |
131 | if id_: |
|
128 | if id_: | |
132 |
return |
|
129 | return cls.query().get(id_) | |
|
130 | ||||
|
131 | @classmethod | |||
|
132 | def getAll(cls): | |||
|
133 | return cls.query().all() | |||
133 |
|
134 | |||
134 | @classmethod |
|
135 | @classmethod | |
135 | def delete(cls, id_): |
|
136 | def delete(cls, id_): | |
136 |
obj = |
|
137 | obj = cls.query().get(id_) | |
137 | Session.delete(obj) |
|
138 | Session.delete(obj) | |
138 | Session.commit() |
|
139 | Session.commit() | |
139 |
|
140 | |||
@@ -178,13 +179,13 b' class RhodeCodeSettings(Base, BaseModel)' | |||||
178 |
|
179 | |||
179 | @classmethod |
|
180 | @classmethod | |
180 | def get_by_name(cls, ldap_key): |
|
181 | def get_by_name(cls, ldap_key): | |
181 |
return |
|
182 | return cls.query()\ | |
182 | .filter(cls.app_settings_name == ldap_key).scalar() |
|
183 | .filter(cls.app_settings_name == ldap_key).scalar() | |
183 |
|
184 | |||
184 | @classmethod |
|
185 | @classmethod | |
185 | def get_app_settings(cls, cache=False): |
|
186 | def get_app_settings(cls, cache=False): | |
186 |
|
187 | |||
187 |
ret = |
|
188 | ret = cls.query() | |
188 |
|
189 | |||
189 | if cache: |
|
190 | if cache: | |
190 | ret = ret.options(FromCache("sql_cache_short", "get_hg_settings")) |
|
191 | ret = ret.options(FromCache("sql_cache_short", "get_hg_settings")) | |
@@ -200,7 +201,7 b' class RhodeCodeSettings(Base, BaseModel)' | |||||
200 |
|
201 | |||
201 | @classmethod |
|
202 | @classmethod | |
202 | def get_ldap_settings(cls, cache=False): |
|
203 | def get_ldap_settings(cls, cache=False): | |
203 |
ret = |
|
204 | ret = cls.query()\ | |
204 | .filter(cls.app_settings_name.startswith('ldap_')).all() |
|
205 | .filter(cls.app_settings_name.startswith('ldap_')).all() | |
205 | fd = {} |
|
206 | fd = {} | |
206 | for row in ret: |
|
207 | for row in ret: | |
@@ -227,7 +228,7 b' class RhodeCodeUi(Base, BaseModel):' | |||||
227 |
|
228 | |||
228 | @classmethod |
|
229 | @classmethod | |
229 | def get_by_key(cls, key): |
|
230 | def get_by_key(cls, key): | |
230 |
return |
|
231 | return cls.query().filter(cls.ui_key == key) | |
231 |
|
232 | |||
232 |
|
233 | |||
233 | @classmethod |
|
234 | @classmethod | |
@@ -311,7 +312,7 b' class User(Base, BaseModel):' | |||||
311 |
|
312 | |||
312 | @classmethod |
|
313 | @classmethod | |
313 | def get_by_api_key(cls, api_key): |
|
314 | def get_by_api_key(cls, api_key): | |
314 |
return |
|
315 | return cls.query().filter(cls.api_key == api_key).one() | |
315 |
|
316 | |||
316 | def update_lastlogin(self): |
|
317 | def update_lastlogin(self): | |
317 | """Update user lastlogin""" |
|
318 | """Update user lastlogin""" | |
@@ -376,11 +377,11 b' class UsersGroup(Base, BaseModel):' | |||||
376 | @classmethod |
|
377 | @classmethod | |
377 | def get_by_group_name(cls, group_name, cache=False, case_insensitive=False): |
|
378 | def get_by_group_name(cls, group_name, cache=False, case_insensitive=False): | |
378 | if case_insensitive: |
|
379 | if case_insensitive: | |
379 |
gr = |
|
380 | gr = cls.query()\ | |
380 | .filter(cls.users_group_name.ilike(group_name)) |
|
381 | .filter(cls.users_group_name.ilike(group_name)) | |
381 | else: |
|
382 | else: | |
382 |
gr = |
|
383 | gr = cls.query()\ | |
383 |
.filter( |
|
384 | .filter(cls.users_group_name == group_name) | |
384 | if cache: |
|
385 | if cache: | |
385 | gr = gr.options(FromCache("sql_cache_short", |
|
386 | gr = gr.options(FromCache("sql_cache_short", | |
386 | "get_user_%s" % group_name)) |
|
387 | "get_user_%s" % group_name)) | |
@@ -389,7 +390,7 b' class UsersGroup(Base, BaseModel):' | |||||
389 |
|
390 | |||
390 | @classmethod |
|
391 | @classmethod | |
391 | def get(cls, users_group_id, cache=False): |
|
392 | def get(cls, users_group_id, cache=False): | |
392 |
users_group = |
|
393 | users_group = cls.query() | |
393 | if cache: |
|
394 | if cache: | |
394 | users_group = users_group.options(FromCache("sql_cache_short", |
|
395 | users_group = users_group.options(FromCache("sql_cache_short", | |
395 | "get_users_group_%s" % users_group_id)) |
|
396 | "get_users_group_%s" % users_group_id)) | |
@@ -422,10 +423,10 b' class UsersGroup(Base, BaseModel):' | |||||
422 | Session.flush() |
|
423 | Session.flush() | |
423 | members_list = [] |
|
424 | members_list = [] | |
424 | if v: |
|
425 | if v: | |
|
426 | v = [v] if isinstance(v, basestring) else v | |||
425 | for u_id in set(v): |
|
427 | for u_id in set(v): | |
426 |
member |
|
428 | member = UsersGroupMember(users_group_id, u_id) | |
427 | users_group_id, |
|
429 | members_list.append(member) | |
428 | u_id)) |
|
|||
429 | setattr(users_group, 'members', members_list) |
|
430 | setattr(users_group, 'members', members_list) | |
430 | setattr(users_group, k, v) |
|
431 | setattr(users_group, k, v) | |
431 |
|
432 | |||
@@ -457,7 +458,6 b' class UsersGroup(Base, BaseModel):' | |||||
457 | Session.rollback() |
|
458 | Session.rollback() | |
458 | raise |
|
459 | raise | |
459 |
|
460 | |||
460 |
|
||||
461 | class UsersGroupMember(Base, BaseModel): |
|
461 | class UsersGroupMember(Base, BaseModel): | |
462 | __tablename__ = 'users_groups_members' |
|
462 | __tablename__ = 'users_groups_members' | |
463 | __table_args__ = {'extend_existing':True} |
|
463 | __table_args__ = {'extend_existing':True} | |
@@ -473,6 +473,15 b' class UsersGroupMember(Base, BaseModel):' | |||||
473 | self.users_group_id = gr_id |
|
473 | self.users_group_id = gr_id | |
474 | self.user_id = u_id |
|
474 | self.user_id = u_id | |
475 |
|
475 | |||
|
476 | @staticmethod | |||
|
477 | def add_user_to_group(group, user): | |||
|
478 | ugm = UsersGroupMember() | |||
|
479 | ugm.users_group = group | |||
|
480 | ugm.user = user | |||
|
481 | Session.add(ugm) | |||
|
482 | Session.commit() | |||
|
483 | return ugm | |||
|
484 | ||||
476 | class Repository(Base, BaseModel): |
|
485 | class Repository(Base, BaseModel): | |
477 | __tablename__ = 'repositories' |
|
486 | __tablename__ = 'repositories' | |
478 | __table_args__ = (UniqueConstraint('repo_name'), {'extend_existing':True},) |
|
487 | __table_args__ = (UniqueConstraint('repo_name'), {'extend_existing':True},) | |
@@ -514,16 +523,14 b' class Repository(Base, BaseModel):' | |||||
514 | @classmethod |
|
523 | @classmethod | |
515 | def get_by_repo_name(cls, repo_name): |
|
524 | def get_by_repo_name(cls, repo_name): | |
516 | q = Session.query(cls).filter(cls.repo_name == repo_name) |
|
525 | q = Session.query(cls).filter(cls.repo_name == repo_name) | |
517 |
|
||||
518 | q = q.options(joinedload(Repository.fork))\ |
|
526 | q = q.options(joinedload(Repository.fork))\ | |
519 | .options(joinedload(Repository.user))\ |
|
527 | .options(joinedload(Repository.user))\ | |
520 |
.options(joinedload(Repository.group)) |
|
528 | .options(joinedload(Repository.group)) | |
521 |
|
||||
522 | return q.one() |
|
529 | return q.one() | |
523 |
|
530 | |||
524 | @classmethod |
|
531 | @classmethod | |
525 | def get_repo_forks(cls, repo_id): |
|
532 | def get_repo_forks(cls, repo_id): | |
526 |
return |
|
533 | return cls.query().filter(Repository.fork_id == repo_id) | |
527 |
|
534 | |||
528 | @classmethod |
|
535 | @classmethod | |
529 | def base_path(cls): |
|
536 | def base_path(cls): | |
@@ -606,7 +613,7 b' class Repository(Base, BaseModel):' | |||||
606 | baseui._tcfg = config.config() |
|
613 | baseui._tcfg = config.config() | |
607 |
|
614 | |||
608 |
|
615 | |||
609 |
ret = |
|
616 | ret = RhodeCodeUi.query()\ | |
610 | .options(FromCache("sql_cache_short", "repository_repo_ui")).all() |
|
617 | .options(FromCache("sql_cache_short", "repository_repo_ui")).all() | |
611 |
|
618 | |||
612 | hg_ui = ret |
|
619 | hg_ui = ret | |
@@ -661,7 +668,7 b' class Repository(Base, BaseModel):' | |||||
661 | None otherwise. `cache_active = False` means that this cache |
|
668 | None otherwise. `cache_active = False` means that this cache | |
662 | state is not valid and needs to be invalidated |
|
669 | state is not valid and needs to be invalidated | |
663 | """ |
|
670 | """ | |
664 |
return |
|
671 | return CacheInvalidation.query()\ | |
665 | .filter(CacheInvalidation.cache_key == self.repo_name)\ |
|
672 | .filter(CacheInvalidation.cache_key == self.repo_name)\ | |
666 | .filter(CacheInvalidation.cache_active == False)\ |
|
673 | .filter(CacheInvalidation.cache_active == False)\ | |
667 | .scalar() |
|
674 | .scalar() | |
@@ -670,7 +677,7 b' class Repository(Base, BaseModel):' | |||||
670 | """ |
|
677 | """ | |
671 | set a cache for invalidation for this instance |
|
678 | set a cache for invalidation for this instance | |
672 | """ |
|
679 | """ | |
673 |
inv = |
|
680 | inv = CacheInvalidation.query()\ | |
674 | .filter(CacheInvalidation.cache_key == self.repo_name)\ |
|
681 | .filter(CacheInvalidation.cache_key == self.repo_name)\ | |
675 | .scalar() |
|
682 | .scalar() | |
676 |
|
683 | |||
@@ -772,8 +779,17 b' class Group(Base, BaseModel):' | |||||
772 | return '/' |
|
779 | return '/' | |
773 |
|
780 | |||
774 | @classmethod |
|
781 | @classmethod | |
775 | def get_by_group_name(cls, group_name): |
|
782 | def get_by_group_name(cls, group_name, cache=False, case_insensitive=False): | |
776 | return cls.query().filter(cls.group_name == group_name).scalar() |
|
783 | if case_insensitive: | |
|
784 | gr = cls.query()\ | |||
|
785 | .filter(cls.group_name.ilike(group_name)) | |||
|
786 | else: | |||
|
787 | gr = cls.query()\ | |||
|
788 | .filter(cls.group_name == group_name) | |||
|
789 | if cache: | |||
|
790 | gr = gr.options(FromCache("sql_cache_short", | |||
|
791 | "get_group_%s" % group_name)) | |||
|
792 | return gr.scalar() | |||
777 |
|
793 | |||
778 | @property |
|
794 | @property | |
779 | def parents(self): |
|
795 | def parents(self): | |
@@ -801,7 +817,7 b' class Group(Base, BaseModel):' | |||||
801 |
|
817 | |||
802 | @property |
|
818 | @property | |
803 | def children(self): |
|
819 | def children(self): | |
804 |
return |
|
820 | return Group.query().filter(Group.parent_group == self) | |
805 |
|
821 | |||
806 | @property |
|
822 | @property | |
807 | def name(self): |
|
823 | def name(self): | |
@@ -817,7 +833,7 b' class Group(Base, BaseModel):' | |||||
817 |
|
833 | |||
818 | @property |
|
834 | @property | |
819 | def repositories(self): |
|
835 | def repositories(self): | |
820 |
return |
|
836 | return Repository.query().filter(Repository.group == self) | |
821 |
|
837 | |||
822 | @property |
|
838 | @property | |
823 | def repositories_recursive_count(self): |
|
839 | def repositories_recursive_count(self): | |
@@ -839,7 +855,8 b' class Group(Base, BaseModel):' | |||||
839 |
|
855 | |||
840 | :param group_name: |
|
856 | :param group_name: | |
841 | """ |
|
857 | """ | |
842 |
path_prefix = self.parent_group.full_path_splitted if |
|
858 | path_prefix = (self.parent_group.full_path_splitted if | |
|
859 | self.parent_group else []) | |||
843 | return Group.url_sep().join(path_prefix + [group_name]) |
|
860 | return Group.url_sep().join(path_prefix + [group_name]) | |
844 |
|
861 | |||
845 |
|
862 | |||
@@ -856,7 +873,7 b' class Permission(Base, BaseModel):' | |||||
856 |
|
873 | |||
857 | @classmethod |
|
874 | @classmethod | |
858 | def get_by_key(cls, key): |
|
875 | def get_by_key(cls, key): | |
859 |
return |
|
876 | return cls.query().filter(cls.permission_name == key).scalar() | |
860 |
|
877 | |||
861 | class RepoToPerm(Base, BaseModel): |
|
878 | class RepoToPerm(Base, BaseModel): | |
862 | __tablename__ = 'repo_to_perm' |
|
879 | __tablename__ = 'repo_to_perm' | |
@@ -885,7 +902,7 b' class UserToPerm(Base, BaseModel):' | |||||
885 | if not isinstance(perm, Permission): |
|
902 | if not isinstance(perm, Permission): | |
886 | raise Exception('perm needs to be an instance of Permission class') |
|
903 | raise Exception('perm needs to be an instance of Permission class') | |
887 |
|
904 | |||
888 |
return |
|
905 | return cls.query().filter(cls.user_id == user_id)\ | |
889 | .filter(cls.permission == perm).scalar() is not None |
|
906 | .filter(cls.permission == perm).scalar() is not None | |
890 |
|
907 | |||
891 | @classmethod |
|
908 | @classmethod | |
@@ -909,7 +926,7 b' class UserToPerm(Base, BaseModel):' | |||||
909 | raise Exception('perm needs to be an instance of Permission class') |
|
926 | raise Exception('perm needs to be an instance of Permission class') | |
910 |
|
927 | |||
911 | try: |
|
928 | try: | |
912 |
|
|
929 | cls.query().filter(cls.user_id == user_id)\ | |
913 | .filter(cls.permission == perm).delete() |
|
930 | .filter(cls.permission == perm).delete() | |
914 | Session.commit() |
|
931 | Session.commit() | |
915 | except: |
|
932 | except: | |
@@ -945,7 +962,7 b' class UsersGroupToPerm(Base, BaseModel):' | |||||
945 | if not isinstance(perm, Permission): |
|
962 | if not isinstance(perm, Permission): | |
946 | raise Exception('perm needs to be an instance of Permission class') |
|
963 | raise Exception('perm needs to be an instance of Permission class') | |
947 |
|
964 | |||
948 |
return |
|
965 | return cls.query().filter(cls.users_group_id == | |
949 | users_group_id)\ |
|
966 | users_group_id)\ | |
950 | .filter(cls.permission == perm)\ |
|
967 | .filter(cls.permission == perm)\ | |
951 | .scalar() is not None |
|
968 | .scalar() is not None | |
@@ -971,7 +988,7 b' class UsersGroupToPerm(Base, BaseModel):' | |||||
971 | raise Exception('perm needs to be an instance of Permission class') |
|
988 | raise Exception('perm needs to be an instance of Permission class') | |
972 |
|
989 | |||
973 | try: |
|
990 | try: | |
974 |
|
|
991 | cls.query().filter(cls.users_group_id == users_group_id)\ | |
975 | .filter(cls.permission == perm).delete() |
|
992 | .filter(cls.permission == perm).delete() | |
976 | Session.commit() |
|
993 | Session.commit() | |
977 | except: |
|
994 | except: | |
@@ -1023,7 +1040,7 b' class UserFollowing(Base, BaseModel):' | |||||
1023 |
|
1040 | |||
1024 | @classmethod |
|
1041 | @classmethod | |
1025 | def get_repo_followers(cls, repo_id): |
|
1042 | def get_repo_followers(cls, repo_id): | |
1026 |
return |
|
1043 | return cls.query().filter(cls.follows_repo_id == repo_id) | |
1027 |
|
1044 | |||
1028 | class CacheInvalidation(Base, BaseModel): |
|
1045 | class CacheInvalidation(Base, BaseModel): | |
1029 | __tablename__ = 'cache_invalidation' |
|
1046 | __tablename__ = 'cache_invalidation' | |
@@ -1049,3 +1066,4 b' class DbMigrateVersion(Base, BaseModel):' | |||||
1049 | repository_id = Column('repository_id', String(250), primary_key=True) |
|
1066 | repository_id = Column('repository_id', String(250), primary_key=True) | |
1050 | repository_path = Column('repository_path', Text) |
|
1067 | repository_path = Column('repository_path', Text) | |
1051 | version = Column('version', Integer) |
|
1068 | version = Column('version', Integer) | |
|
1069 |
@@ -186,7 +186,8 b' class ValidPasswordsMatch(formencode.val' | |||||
186 |
|
186 | |||
187 | def validate_python(self, value, state): |
|
187 | def validate_python(self, value, state): | |
188 |
|
188 | |||
189 |
|
|
189 | pass_val = value.get('password') or value.get('new_password') | |
|
190 | if pass_val != value['password_confirmation']: | |||
190 | e_dict = {'password_confirmation': |
|
191 | e_dict = {'password_confirmation': | |
191 | _('Passwords do not match')} |
|
192 | _('Passwords do not match')} | |
192 | raise formencode.Invalid('', value, state, error_dict=e_dict) |
|
193 | raise formencode.Invalid('', value, state, error_dict=e_dict) | |
@@ -196,8 +197,8 b' class ValidAuth(formencode.validators.Fa' | |||||
196 |
|
|
197 | 'invalid_password':_('invalid password'), | |
197 |
|
|
198 | 'invalid_login':_('invalid user name'), | |
198 |
|
|
199 | 'disabled_account':_('Your account is disabled') | |
|
200 | } | |||
199 |
|
201 | |||
200 | } |
|
|||
201 | #error mapping |
|
202 | # error mapping | |
202 | e_dict = {'username':messages['invalid_login'], |
|
203 | e_dict = {'username':messages['invalid_login'], | |
203 | 'password':messages['invalid_password']} |
|
204 | 'password':messages['invalid_password']} | |
@@ -253,6 +254,7 b' def ValidRepoName(edit, old_data):' | |||||
253 | # db key This is an actual just the name to store in the |
|
254 | # db key This is an actual just the name to store in the | |
254 | # database |
|
255 | # database | |
255 | repo_name_full = group_path + Group.url_sep() + repo_name |
|
256 | repo_name_full = group_path + Group.url_sep() + repo_name | |
|
257 | ||||
256 | else: |
|
258 | else: | |
257 | group_path = '' |
|
259 | group_path = '' | |
258 | repo_name_full = repo_name |
|
260 | repo_name_full = repo_name | |
@@ -496,8 +498,6 b' class LoginForm(formencode.Schema):' | |||||
496 | 'tooShort':_('Enter %(min)i characters or more')} |
|
498 | 'tooShort':_('Enter %(min)i characters or more')} | |
497 | ) |
|
499 | ) | |
498 |
|
500 | |||
499 |
|
||||
500 | #chained validators have access to all data |
|
|||
501 | chained_validators = [ValidAuth] |
|
501 | chained_validators = [ValidAuth] | |
502 |
|
502 | |||
503 | def UserForm(edit=False, old_data={}): |
|
503 | def UserForm(edit=False, old_data={}): | |
@@ -508,15 +508,18 b' def UserForm(edit=False, old_data={}):' | |||||
508 | ValidUsername(edit, old_data)) |
|
508 | ValidUsername(edit, old_data)) | |
509 | if edit: |
|
509 | if edit: | |
510 | new_password = All(UnicodeString(strip=True, min=6, not_empty=False)) |
|
510 | new_password = All(UnicodeString(strip=True, min=6, not_empty=False)) | |
|
511 | password_confirmation = All(UnicodeString(strip=True, min=6, not_empty=False)) | |||
511 | admin = StringBoolean(if_missing=False) |
|
512 | admin = StringBoolean(if_missing=False) | |
512 | else: |
|
513 | else: | |
513 | password = All(UnicodeString(strip=True, min=6, not_empty=True)) |
|
514 | password = All(UnicodeString(strip=True, min=6, not_empty=True)) | |
|
515 | password_confirmation = All(UnicodeString(strip=True, min=6, not_empty=False)) | |||
|
516 | ||||
514 | active = StringBoolean(if_missing=False) |
|
517 | active = StringBoolean(if_missing=False) | |
515 | name = UnicodeString(strip=True, min=1, not_empty=True) |
|
518 | name = UnicodeString(strip=True, min=1, not_empty=True) | |
516 | lastname = UnicodeString(strip=True, min=1, not_empty=True) |
|
519 | lastname = UnicodeString(strip=True, min=1, not_empty=True) | |
517 | email = All(Email(not_empty=True), UniqSystemEmail(old_data)) |
|
520 | email = All(Email(not_empty=True), UniqSystemEmail(old_data)) | |
518 |
|
521 | |||
519 | chained_validators = [ValidPassword] |
|
522 | chained_validators = [ValidPasswordsMatch, ValidPassword] | |
520 |
|
523 | |||
521 | return _UserForm |
|
524 | return _UserForm | |
522 |
|
525 | |||
@@ -616,16 +619,19 b' def RepoForkForm(edit=False, old_data={}' | |||||
616 |
|
619 | |||
617 | return _RepoForkForm |
|
620 | return _RepoForkForm | |
618 |
|
621 | |||
619 |
def RepoSettingsForm(edit=False, old_data={}) |
|
622 | def RepoSettingsForm(edit=False, old_data={}, supported_backends=BACKENDS.keys(), | |
|
623 | repo_groups=[]): | |||
620 | class _RepoForm(formencode.Schema): |
|
624 | class _RepoForm(formencode.Schema): | |
621 | allow_extra_fields = True |
|
625 | allow_extra_fields = True | |
622 | filter_extra_fields = False |
|
626 | filter_extra_fields = False | |
623 | repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), |
|
627 | repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), | |
624 | SlugifyName()) |
|
628 | SlugifyName()) | |
625 | description = UnicodeString(strip=True, min=1, not_empty=True) |
|
629 | description = UnicodeString(strip=True, min=1, not_empty=True) | |
|
630 | repo_group = OneOf(repo_groups, hideList=True) | |||
626 | private = StringBoolean(if_missing=False) |
|
631 | private = StringBoolean(if_missing=False) | |
627 |
|
632 | |||
628 |
chained_validators = [ValidRepoName(edit, old_data), ValidPerms, |
|
633 | chained_validators = [ValidRepoName(edit, old_data), ValidPerms, | |
|
634 | ValidSettings] | |||
629 | return _RepoForm |
|
635 | return _RepoForm | |
630 |
|
636 | |||
631 |
|
637 |
@@ -94,6 +94,46 b' class RepoModel(BaseModel):' | |||||
94 | for gr in users_groups]) |
|
94 | for gr in users_groups]) | |
95 | return users_groups_array |
|
95 | return users_groups_array | |
96 |
|
96 | |||
|
97 | def _get_defaults(self, repo_name): | |||
|
98 | """ | |||
|
99 | Get's information about repository, and returns a dict for | |||
|
100 | usage in forms | |||
|
101 | ||||
|
102 | :param repo_name: | |||
|
103 | """ | |||
|
104 | ||||
|
105 | repo_info = Repository.get_by_repo_name(repo_name) | |||
|
106 | ||||
|
107 | if repo_info is None: | |||
|
108 | return None | |||
|
109 | ||||
|
110 | defaults = repo_info.get_dict() | |||
|
111 | group, repo_name = repo_info.groups_and_repo | |||
|
112 | defaults['repo_name'] = repo_name | |||
|
113 | defaults['repo_group'] = getattr(group[-1] if group else None, | |||
|
114 | 'group_id', None) | |||
|
115 | ||||
|
116 | # fill owner | |||
|
117 | if repo_info.user: | |||
|
118 | defaults.update({'user': repo_info.user.username}) | |||
|
119 | else: | |||
|
120 | replacement_user = User.query().filter(User.admin == | |||
|
121 | True).first().username | |||
|
122 | defaults.update({'user': replacement_user}) | |||
|
123 | ||||
|
124 | # fill repository users | |||
|
125 | for p in repo_info.repo_to_perm: | |||
|
126 | defaults.update({'u_perm_%s' % p.user.username: | |||
|
127 | p.permission.permission_name}) | |||
|
128 | ||||
|
129 | # fill repository groups | |||
|
130 | for p in repo_info.users_group_to_perm: | |||
|
131 | defaults.update({'g_perm_%s' % p.users_group.users_group_name: | |||
|
132 | p.permission.permission_name}) | |||
|
133 | ||||
|
134 | return defaults | |||
|
135 | ||||
|
136 | ||||
97 | def update(self, repo_name, form_data): |
|
137 | def update(self, repo_name, form_data): | |
98 | try: |
|
138 | try: | |
99 | cur_repo = self.get_by_repo_name(repo_name, cache=False) |
|
139 | cur_repo = self.get_by_repo_name(repo_name, cache=False) | |
@@ -151,7 +191,7 b' class RepoModel(BaseModel):' | |||||
151 | elif k == 'repo_name': |
|
191 | elif k == 'repo_name': | |
152 | pass |
|
192 | pass | |
153 | elif k == 'repo_group': |
|
193 | elif k == 'repo_group': | |
154 |
cur_repo.group |
|
194 | cur_repo.group = Group.get(v) | |
155 |
|
195 | |||
156 | else: |
|
196 | else: | |
157 | setattr(cur_repo, k, v) |
|
197 | setattr(cur_repo, k, v) | |
@@ -368,3 +408,4 b' class RepoModel(BaseModel):' | |||||
368 | % (datetime.today()\ |
|
408 | % (datetime.today()\ | |
369 | .strftime('%Y%m%d_%H%M%S_%f'), |
|
409 | .strftime('%Y%m%d_%H%M%S_%f'), | |
370 | repo.repo_name))) |
|
410 | repo.repo_name))) | |
|
411 |
@@ -49,7 +49,6 b" PERM_WEIGHTS = {'repository.none': 0," | |||||
49 |
|
49 | |||
50 |
|
50 | |||
51 | class UserModel(BaseModel): |
|
51 | class UserModel(BaseModel): | |
52 |
|
||||
53 | def get(self, user_id, cache=False): |
|
52 | def get(self, user_id, cache=False): | |
54 | user = self.sa.query(User) |
|
53 | user = self.sa.query(User) | |
55 | if cache: |
|
54 | if cache: | |
@@ -87,6 +86,7 b' class UserModel(BaseModel):' | |||||
87 | new_user.api_key = generate_api_key(form_data['username']) |
|
86 | new_user.api_key = generate_api_key(form_data['username']) | |
88 | self.sa.add(new_user) |
|
87 | self.sa.add(new_user) | |
89 | self.sa.commit() |
|
88 | self.sa.commit() | |
|
89 | return new_user | |||
90 | except: |
|
90 | except: | |
91 | log.error(traceback.format_exc()) |
|
91 | log.error(traceback.format_exc()) | |
92 | self.sa.rollback() |
|
92 | self.sa.rollback() | |
@@ -96,6 +96,7 b' class UserModel(BaseModel):' | |||||
96 | """ |
|
96 | """ | |
97 | Checks if user is in database, if not creates this user marked |
|
97 | Checks if user is in database, if not creates this user marked | |
98 | as ldap user |
|
98 | as ldap user | |
|
99 | ||||
99 | :param username: |
|
100 | :param username: | |
100 | :param password: |
|
101 | :param password: | |
101 | :param user_dn: |
|
102 | :param user_dn: | |
@@ -386,3 +387,4 b' class UserModel(BaseModel):' | |||||
386 | repository.repo_name] = p |
|
387 | repository.repo_name] = p | |
387 |
|
388 | |||
388 | return user |
|
389 | return user | |
|
390 |
@@ -29,7 +29,7 b'' | |||||
29 | <div class="fields"> |
|
29 | <div class="fields"> | |
30 | <div class="field"> |
|
30 | <div class="field"> | |
31 | <div class="label"> |
|
31 | <div class="label"> | |
32 |
<label for=" |
|
32 | <label for="group_name">${_('Group name')}:</label> | |
33 | </div> |
|
33 | </div> | |
34 | <div class="input"> |
|
34 | <div class="input"> | |
35 | ${h.text('group_name',class_='medium')} |
|
35 | ${h.text('group_name',class_='medium')} | |
@@ -38,7 +38,7 b'' | |||||
38 |
|
38 | |||
39 | <div class="field"> |
|
39 | <div class="field"> | |
40 | <div class="label label-textarea"> |
|
40 | <div class="label label-textarea"> | |
41 | <label for="description">${_('Description')}:</label> |
|
41 | <label for="group_description">${_('Description')}:</label> | |
42 | </div> |
|
42 | </div> | |
43 | <div class="textarea text-area editor"> |
|
43 | <div class="textarea text-area editor"> | |
44 | ${h.textarea('group_description',cols=23,rows=5,class_="medium")} |
|
44 | ${h.textarea('group_description',cols=23,rows=5,class_="medium")} | |
@@ -47,7 +47,7 b'' | |||||
47 |
|
47 | |||
48 | <div class="field"> |
|
48 | <div class="field"> | |
49 | <div class="label"> |
|
49 | <div class="label"> | |
50 |
<label for=" |
|
50 | <label for="group_parent_id">${_('Group parent')}:</label> | |
51 | </div> |
|
51 | </div> | |
52 | <div class="input"> |
|
52 | <div class="input"> | |
53 | ${h.select('group_parent_id','',c.repo_groups,class_="medium")} |
|
53 | ${h.select('group_parent_id','',c.repo_groups,class_="medium")} |
@@ -29,7 +29,7 b'' | |||||
29 | <div class="fields"> |
|
29 | <div class="fields"> | |
30 | <div class="field"> |
|
30 | <div class="field"> | |
31 | <div class="label"> |
|
31 | <div class="label"> | |
32 |
<label for=" |
|
32 | <label for="group_name">${_('Group name')}:</label> | |
33 | </div> |
|
33 | </div> | |
34 | <div class="input"> |
|
34 | <div class="input"> | |
35 | ${h.text('group_name',class_='medium')} |
|
35 | ${h.text('group_name',class_='medium')} | |
@@ -38,7 +38,7 b'' | |||||
38 |
|
38 | |||
39 | <div class="field"> |
|
39 | <div class="field"> | |
40 | <div class="label label-textarea"> |
|
40 | <div class="label label-textarea"> | |
41 | <label for="description">${_('Description')}:</label> |
|
41 | <label for="group_description">${_('Description')}:</label> | |
42 | </div> |
|
42 | </div> | |
43 | <div class="textarea text-area editor"> |
|
43 | <div class="textarea text-area editor"> | |
44 | ${h.textarea('group_description',cols=23,rows=5,class_="medium")} |
|
44 | ${h.textarea('group_description',cols=23,rows=5,class_="medium")} | |
@@ -47,7 +47,7 b'' | |||||
47 |
|
47 | |||
48 | <div class="field"> |
|
48 | <div class="field"> | |
49 | <div class="label"> |
|
49 | <div class="label"> | |
50 |
<label for=" |
|
50 | <label for="group_parent_id">${_('Group parent')}:</label> | |
51 | </div> |
|
51 | </div> | |
52 | <div class="input"> |
|
52 | <div class="input"> | |
53 | ${h.select('group_parent_id','',c.repo_groups,class_="medium")} |
|
53 | ${h.select('group_parent_id','',c.repo_groups,class_="medium")} |
@@ -34,7 +34,7 b'' | |||||
34 | <div class="checkboxes"> |
|
34 | <div class="checkboxes"> | |
35 | <div class="checkbox"> |
|
35 | <div class="checkbox"> | |
36 | ${h.checkbox('destroy',True)} |
|
36 | ${h.checkbox('destroy',True)} | |
37 |
<label for=" |
|
37 | <label for="destroy"> | |
38 | <span class="tooltip" title="${h.tooltip(_('In case a repository was deleted from filesystem and there are leftovers in the database check this option to scan obsolete data in database and remove it.'))}"> |
|
38 | <span class="tooltip" title="${h.tooltip(_('In case a repository was deleted from filesystem and there are leftovers in the database check this option to scan obsolete data in database and remove it.'))}"> | |
39 | ${_('destroy old data')}</span> </label> |
|
39 | ${_('destroy old data')}</span> </label> | |
40 | </div> |
|
40 | </div> | |
@@ -56,12 +56,12 b'' | |||||
56 | <div class="fields"> |
|
56 | <div class="fields"> | |
57 | <div class="field"> |
|
57 | <div class="field"> | |
58 | <div class="label label-checkbox"> |
|
58 | <div class="label label-checkbox"> | |
59 |
<label |
|
59 | <label>${_('index build option')}:</label> | |
60 | </div> |
|
60 | </div> | |
61 | <div class="checkboxes"> |
|
61 | <div class="checkboxes"> | |
62 | <div class="checkbox"> |
|
62 | <div class="checkbox"> | |
63 | ${h.checkbox('full_index',True)} |
|
63 | ${h.checkbox('full_index',True)} | |
64 |
<label for=" |
|
64 | <label for="full_index">${_('build from scratch')}</label> | |
65 | </div> |
|
65 | </div> | |
66 | </div> |
|
66 | </div> | |
67 | </div> |
|
67 | </div> | |
@@ -100,7 +100,7 b'' | |||||
100 |
|
100 | |||
101 | <div class="field"> |
|
101 | <div class="field"> | |
102 | <div class="label"> |
|
102 | <div class="label"> | |
103 | <label for="ga_code">${_('GA code')}:</label> |
|
103 | <label for="rhodecode_ga_code">${_('GA code')}:</label> | |
104 | </div> |
|
104 | </div> | |
105 | <div class="input"> |
|
105 | <div class="input"> | |
106 | ${h.text('rhodecode_ga_code',size=30)} |
|
106 | ${h.text('rhodecode_ga_code',size=30)} | |
@@ -124,7 +124,7 b'' | |||||
124 |
|
124 | |||
125 | <div class="field"> |
|
125 | <div class="field"> | |
126 | <div class="label label-checkbox"> |
|
126 | <div class="label label-checkbox"> | |
127 |
<label |
|
127 | <label>${_('Web')}:</label> | |
128 | </div> |
|
128 | </div> | |
129 | <div class="checkboxes"> |
|
129 | <div class="checkboxes"> | |
130 | <div class="checkbox"> |
|
130 | <div class="checkbox"> | |
@@ -136,7 +136,7 b'' | |||||
136 |
|
136 | |||
137 | <div class="field"> |
|
137 | <div class="field"> | |
138 | <div class="label label-checkbox"> |
|
138 | <div class="label label-checkbox"> | |
139 |
<label |
|
139 | <label>${_('Hooks')}:</label> | |
140 | </div> |
|
140 | </div> | |
141 | <div class="input"> |
|
141 | <div class="input"> | |
142 | ${h.link_to(_('advanced setup'),url('admin_edit_setting',setting_id='hooks'))} |
|
142 | ${h.link_to(_('advanced setup'),url('admin_edit_setting',setting_id='hooks'))} |
@@ -47,6 +47,15 b'' | |||||
47 |
|
47 | |||
48 | <div class="field"> |
|
48 | <div class="field"> | |
49 | <div class="label"> |
|
49 | <div class="label"> | |
|
50 | <label for="password_confirmation">${_('Password confirmation')}:</label> | |||
|
51 | </div> | |||
|
52 | <div class="input"> | |||
|
53 | ${h.password('password_confirmation',class_="small",autocomplete="off")} | |||
|
54 | </div> | |||
|
55 | </div> | |||
|
56 | ||||
|
57 | <div class="field"> | |||
|
58 | <div class="label"> | |||
50 | <label for="name">${_('First Name')}:</label> |
|
59 | <label for="name">${_('First Name')}:</label> | |
51 | </div> |
|
60 | </div> | |
52 | <div class="input"> |
|
61 | <div class="input"> |
@@ -71,6 +71,15 b'' | |||||
71 |
|
71 | |||
72 | <div class="field"> |
|
72 | <div class="field"> | |
73 | <div class="label"> |
|
73 | <div class="label"> | |
|
74 | <label for="password_confirmation">${_('New password confirmation')}:</label> | |||
|
75 | </div> | |||
|
76 | <div class="input"> | |||
|
77 | ${h.password('password_confirmation',class_="medium",autocomplete="off")} | |||
|
78 | </div> | |||
|
79 | </div> | |||
|
80 | ||||
|
81 | <div class="field"> | |||
|
82 | <div class="label"> | |||
74 | <label for="name">${_('First Name')}:</label> |
|
83 | <label for="name">${_('First Name')}:</label> | |
75 | </div> |
|
84 | </div> | |
76 | <div class="input"> |
|
85 | <div class="input"> | |
@@ -132,7 +141,7 b'' | |||||
132 | <div class="fields"> |
|
141 | <div class="fields"> | |
133 | <div class="field"> |
|
142 | <div class="field"> | |
134 | <div class="label label-checkbox"> |
|
143 | <div class="label label-checkbox"> | |
135 | <label for="">${_('Create repositories')}:</label> |
|
144 | <label for="create_repo_perm">${_('Create repositories')}:</label> | |
136 | </div> |
|
145 | </div> | |
137 | <div class="checkboxes"> |
|
146 | <div class="checkboxes"> | |
138 | ${h.checkbox('create_repo_perm',value=True)} |
|
147 | ${h.checkbox('create_repo_perm',value=True)} |
@@ -60,6 +60,15 b'' | |||||
60 |
|
|
60 | ||
61 |
|
|
61 | <div class="field"> | |
62 |
|
|
62 | <div class="label"> | |
|
63 | <label for="password_confirmation">${_('New password confirmation')}:</label> | |||
|
64 | </div> | |||
|
65 | <div class="input"> | |||
|
66 | ${h.password('password_confirmation',class_="medium",autocomplete="off")} | |||
|
67 | </div> | |||
|
68 | </div> | |||
|
69 | ||||
|
70 | <div class="field"> | |||
|
71 | <div class="label"> | |||
63 | <label for="name">${_('First Name')}:</label> |
|
72 | <label for="name">${_('First Name')}:</label> | |
64 | </div> |
|
73 | </div> | |
65 | <div class="input"> |
|
74 | <div class="input"> | |
@@ -154,10 +163,12 b'' | |||||
154 | </tr> |
|
163 | </tr> | |
155 | %endfor |
|
164 | %endfor | |
156 | %else: |
|
165 | %else: | |
|
166 | <div style="padding:5px 0px 10px 0px;"> | |||
157 | ${_('No repositories yet')} |
|
167 | ${_('No repositories yet')} | |
158 | %if h.HasPermissionAny('hg.admin','hg.create.repository')(): |
|
168 | %if h.HasPermissionAny('hg.admin','hg.create.repository')(): | |
159 | ${h.link_to(_('create one now'),h.url('admin_settings_create_repository'))} |
|
169 | ${h.link_to(_('create one now'),h.url('admin_settings_create_repository'),class_="ui-button-small")} | |
160 | %endif |
|
170 | %endif | |
|
171 | </div> | |||
161 | %endif |
|
172 | %endif | |
162 | </tbody> |
|
173 | </tbody> | |
163 | </table> |
|
174 | </table> |
@@ -253,7 +253,7 b'' | |||||
253 | <div class="fields"> |
|
253 | <div class="fields"> | |
254 | <div class="field"> |
|
254 | <div class="field"> | |
255 | <div class="label label-checkbox"> |
|
255 | <div class="label label-checkbox"> | |
256 | <label for="">${_('Create repositories')}:</label> |
|
256 | <label for="create_repo_perm">${_('Create repositories')}:</label> | |
257 | </div> |
|
257 | </div> | |
258 | <div class="checkboxes"> |
|
258 | <div class="checkboxes"> | |
259 | ${h.checkbox('create_repo_perm',value=True)} |
|
259 | ${h.checkbox('create_repo_perm',value=True)} |
@@ -34,7 +34,14 b'' | |||||
34 | ${h.text('repo_name',class_="small")} |
|
34 | ${h.text('repo_name',class_="small")} | |
35 | </div> |
|
35 | </div> | |
36 | </div> |
|
36 | </div> | |
37 |
|
37 | <div class="field"> | ||
|
38 | <div class="label"> | |||
|
39 | <label for="repo_group">${_('Repository group')}:</label> | |||
|
40 | </div> | |||
|
41 | <div class="input"> | |||
|
42 | ${h.select('repo_group','',c.repo_groups,class_="medium")} | |||
|
43 | </div> | |||
|
44 | </div> | |||
38 | <div class="field"> |
|
45 | <div class="field"> | |
39 | <div class="label label-textarea"> |
|
46 | <div class="label label-textarea"> | |
40 | <label for="description">${_('Description')}:</label> |
|
47 | <label for="description">${_('Description')}:</label> |
@@ -77,8 +77,6 b' class TestController(TestCase):' | |||||
77 | self.assertEqual(response.session['rhodecode_user'].username, username) |
|
77 | self.assertEqual(response.session['rhodecode_user'].username, username) | |
78 | return response.follow() |
|
78 | return response.follow() | |
79 |
|
79 | |||
80 |
|
||||
81 |
|
||||
82 | def checkSessionFlash(self, response, msg): |
|
80 | def checkSessionFlash(self, response, msg): | |
83 | self.assertTrue('flash' in response.session) |
|
81 | self.assertTrue('flash' in response.session) | |
84 | self.assertTrue(msg in response.session['flash'][0][1]) |
|
82 | self.assertTrue(msg in response.session['flash'][0][1]) |
@@ -137,6 +137,7 b' class TestAdminSettingsController(TestCo' | |||||
137 | params=dict(_method='put', |
|
137 | params=dict(_method='put', | |
138 | username='test_admin', |
|
138 | username='test_admin', | |
139 | new_password=new_password, |
|
139 | new_password=new_password, | |
|
140 | password_confirmation = new_password, | |||
140 | password='', |
|
141 | password='', | |
141 | name=new_name, |
|
142 | name=new_name, | |
142 | lastname=new_lastname, |
|
143 | lastname=new_lastname, | |
@@ -160,6 +161,7 b' class TestAdminSettingsController(TestCo' | |||||
160 | _method='put', |
|
161 | _method='put', | |
161 | username='test_admin', |
|
162 | username='test_admin', | |
162 | new_password=old_password, |
|
163 | new_password=old_password, | |
|
164 | password_confirmation = old_password, | |||
163 | password='', |
|
165 | password='', | |
164 | name=old_name, |
|
166 | name=old_name, | |
165 | lastname=old_lastname, |
|
167 | lastname=old_lastname, | |
@@ -186,6 +188,7 b' class TestAdminSettingsController(TestCo' | |||||
186 | _method='put', |
|
188 | _method='put', | |
187 | username='test_admin', |
|
189 | username='test_admin', | |
188 | new_password='test12', |
|
190 | new_password='test12', | |
|
191 | password_confirmation = 'test122', | |||
189 | name='NewName', |
|
192 | name='NewName', | |
190 | lastname='NewLastname', |
|
193 | lastname='NewLastname', | |
191 | email=new_email,)) |
|
194 | email=new_email,)) | |
@@ -201,6 +204,7 b' class TestAdminSettingsController(TestCo' | |||||
201 | _method='put', |
|
204 | _method='put', | |
202 | username='test_admin', |
|
205 | username='test_admin', | |
203 | new_password='test12', |
|
206 | new_password='test12', | |
|
207 | password_confirmation = 'test122', | |||
204 | name='NewName', |
|
208 | name='NewName', | |
205 | lastname='NewLastname', |
|
209 | lastname='NewLastname', | |
206 | email=new_email,)) |
|
210 | email=new_email,)) |
@@ -16,12 +16,14 b' class TestAdminUsersController(TestContr' | |||||
16 | self.log_user() |
|
16 | self.log_user() | |
17 | username = 'newtestuser' |
|
17 | username = 'newtestuser' | |
18 | password = 'test12' |
|
18 | password = 'test12' | |
|
19 | password_confirmation = password | |||
19 | name = 'name' |
|
20 | name = 'name' | |
20 | lastname = 'lastname' |
|
21 | lastname = 'lastname' | |
21 | email = 'mail@mail.com' |
|
22 | email = 'mail@mail.com' | |
22 |
|
23 | |||
23 | response = self.app.post(url('users'), {'username':username, |
|
24 | response = self.app.post(url('users'), {'username':username, | |
24 | 'password':password, |
|
25 | 'password':password, | |
|
26 | 'password_confirmation':password_confirmation, | |||
25 | 'name':name, |
|
27 | 'name':name, | |
26 | 'active':True, |
|
28 | 'active':True, | |
27 | 'lastname':lastname, |
|
29 | 'lastname':lastname, | |
@@ -90,6 +92,7 b' class TestAdminUsersController(TestContr' | |||||
90 |
|
92 | |||
91 | response = self.app.post(url('users'), {'username':username, |
|
93 | response = self.app.post(url('users'), {'username':username, | |
92 | 'password':password, |
|
94 | 'password':password, | |
|
95 | 'password_confirmation':password, | |||
93 | 'name':name, |
|
96 | 'name':name, | |
94 | 'active':True, |
|
97 | 'active':True, | |
95 | 'lastname':lastname, |
|
98 | 'lastname':lastname, |
@@ -48,7 +48,8 b' from rhodecode.tests import TESTS_TMP_PA' | |||||
48 | from rhodecode.config.environment import load_environment |
|
48 | from rhodecode.config.environment import load_environment | |
49 |
|
49 | |||
50 | rel_path = dn(dn(dn(os.path.abspath(__file__)))) |
|
50 | rel_path = dn(dn(dn(os.path.abspath(__file__)))) | |
51 | conf = appconfig('config:development.ini', relative_to=rel_path) |
|
51 | ||
|
52 | conf = appconfig('config:%s' % sys.argv[1], relative_to=rel_path) | |||
52 | load_environment(conf.global_conf, conf.local_conf) |
|
53 | load_environment(conf.global_conf, conf.local_conf) | |
53 |
|
54 | |||
54 | add_cache(conf) |
|
55 | add_cache(conf) | |
@@ -56,10 +57,13 b' add_cache(conf)' | |||||
56 | USER = 'test_admin' |
|
57 | USER = 'test_admin' | |
57 | PASS = 'test12' |
|
58 | PASS = 'test12' | |
58 | HOST = '127.0.0.1:5000' |
|
59 | HOST = '127.0.0.1:5000' | |
59 | DEBUG = True if sys.argv[1:] else False |
|
60 | DEBUG = False | |
60 | print 'DEBUG:', DEBUG |
|
61 | print 'DEBUG:', DEBUG | |
61 | log = logging.getLogger(__name__) |
|
62 | log = logging.getLogger(__name__) | |
62 |
|
63 | |||
|
64 | engine = engine_from_config(conf, 'sqlalchemy.db1.') | |||
|
65 | init_model(engine) | |||
|
66 | sa = meta.Session | |||
63 |
|
67 | |||
64 | class Command(object): |
|
68 | class Command(object): | |
65 |
|
69 | |||
@@ -96,22 +100,15 b' def test_wrapp(func):' | |||||
96 | return res |
|
100 | return res | |
97 | return __wrapp |
|
101 | return __wrapp | |
98 |
|
102 | |||
99 | def get_session(): |
|
|||
100 | engine = engine_from_config(conf, 'sqlalchemy.db1.') |
|
|||
101 | init_model(engine) |
|
|||
102 | sa = meta.Session |
|
|||
103 | return sa |
|
|||
104 |
|
||||
105 |
|
103 | |||
106 | def create_test_user(force=True): |
|
104 | def create_test_user(force=True): | |
107 | print '\tcreating test user' |
|
105 | print '\tcreating test user' | |
108 | sa = get_session() |
|
|||
109 |
|
106 | |||
110 | user = sa.query(User).filter(User.username == USER).scalar() |
|
107 | user = User.get_by_username(USER) | |
111 |
|
108 | |||
112 | if force and user is not None: |
|
109 | if force and user is not None: | |
113 | print '\tremoving current user' |
|
110 | print '\tremoving current user' | |
114 |
for repo in |
|
111 | for repo in Repository.query().filter(Repository.user == user).all(): | |
115 | sa.delete(repo) |
|
112 | sa.delete(repo) | |
116 | sa.delete(user) |
|
113 | sa.delete(user) | |
117 | sa.commit() |
|
114 | sa.commit() | |
@@ -134,9 +131,8 b' def create_test_user(force=True):' | |||||
134 |
|
131 | |||
135 | def create_test_repo(force=True): |
|
132 | def create_test_repo(force=True): | |
136 | from rhodecode.model.repo import RepoModel |
|
133 | from rhodecode.model.repo import RepoModel | |
137 | sa = get_session() |
|
|||
138 |
|
134 | |||
139 | user = sa.query(User).filter(User.username == USER).scalar() |
|
135 | user = User.get_by_username(USER) | |
140 | if user is None: |
|
136 | if user is None: | |
141 | raise Exception('user not found') |
|
137 | raise Exception('user not found') | |
142 |
|
138 | |||
@@ -156,22 +152,17 b' def create_test_repo(force=True):' | |||||
156 |
|
152 | |||
157 |
|
153 | |||
158 | def set_anonymous_access(enable=True): |
|
154 | def set_anonymous_access(enable=True): | |
159 | sa = get_session() |
|
155 | user = User.get_by_username('default') | |
160 | user = sa.query(User).filter(User.username == 'default').one() |
|
|||
161 | sa.expire(user) |
|
|||
162 | user.active = enable |
|
156 | user.active = enable | |
163 | sa.add(user) |
|
157 | sa.add(user) | |
164 | sa.commit() |
|
158 | sa.commit() | |
165 | sa.remove() |
|
|||
166 | import time;time.sleep(3) |
|
|||
167 | print '\tanonymous access is now:', enable |
|
159 | print '\tanonymous access is now:', enable | |
168 |
|
160 | if enable != User.get_by_username('default').active: | ||
|
161 | raise Exception('Cannot set anonymous access') | |||
169 |
|
162 | |||
170 | def get_anonymous_access(): |
|
163 | def get_anonymous_access(): | |
171 | sa = get_session() |
|
164 | user = User.get_by_username('default') | |
172 | obj1 = sa.query(User).filter(User.username == 'default').one() |
|
165 | return user.active | |
173 | sa.expire(obj1) |
|
|||
174 | return obj1.active |
|
|||
175 |
|
166 | |||
176 |
|
167 | |||
177 | #============================================================================== |
|
168 | #============================================================================== | |
@@ -378,16 +369,15 b' def test_push_wrong_path():' | |||||
378 |
|
369 | |||
379 | @test_wrapp |
|
370 | @test_wrapp | |
380 | def get_logs(): |
|
371 | def get_logs(): | |
381 | sa = get_session() |
|
372 | return UserLog.query().all() | |
382 | return len(sa.query(UserLog).all()) |
|
|||
383 |
|
373 | |||
384 | @test_wrapp |
|
374 | @test_wrapp | |
385 | def test_logs(initial): |
|
375 | def test_logs(initial): | |
386 | sa = get_session() |
|
376 | logs = UserLog.query().all() | |
387 | logs = sa.query(UserLog).all() |
|
377 | operations = 4 | |
388 | operations = 7 |
|
378 | if len(initial) + operations != len(logs): | |
389 | if initial + operations != len(logs): |
|
379 | raise Exception("missing number of logs initial:%s vs current:%s" % \ | |
390 | raise Exception("missing number of logs %s vs %s" % (initial, len(logs))) |
|
380 | (len(initial), len(logs))) | |
391 |
|
381 | |||
392 |
|
382 | |||
393 | if __name__ == '__main__': |
|
383 | if __name__ == '__main__': | |
@@ -395,18 +385,17 b" if __name__ == '__main__':" | |||||
395 | create_test_repo() |
|
385 | create_test_repo() | |
396 |
|
386 | |||
397 | initial_logs = get_logs() |
|
387 | initial_logs = get_logs() | |
|
388 | print 'initial activity logs: %s' % len(initial_logs) | |||
398 |
|
389 | |||
399 |
|
|
390 | #test_push_modify_file() | |
400 | test_clone_with_credentials() |
|
391 | test_clone_with_credentials() | |
401 | test_clone_wrong_credentials() |
|
392 | test_clone_wrong_credentials() | |
402 |
|
393 | |||
403 |
|
||||
404 | test_push_new_file(commits=2, with_clone=True) |
|
394 | test_push_new_file(commits=2, with_clone=True) | |
405 |
|
395 | |||
406 | test_clone_anonymous() |
|
396 | test_clone_anonymous() | |
407 | test_push_wrong_path() |
|
397 | test_push_wrong_path() | |
408 |
|
398 | |||
409 |
|
||||
410 | test_push_wrong_credentials() |
|
399 | test_push_wrong_credentials() | |
411 |
|
400 | |||
412 | test_logs(initial_logs) |
|
401 | test_logs(initial_logs) |
General Comments 0
You need to be logged in to leave comments.
Login now