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 | 24 | #smtp_port = |
|
25 | 25 | #smtp_use_tls = false |
|
26 | 26 | #smtp_use_ssl = true |
|
27 | # Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.) | |
|
28 | #smtp_auth = | |
|
27 | 29 | |
|
28 | 30 | [server:main] |
|
29 | 31 | ##nr of threads to spawn |
@@ -7,7 +7,7 b' API' | |||
|
7 | 7 | |
|
8 | 8 | Starting from RhodeCode version 1.2 a simple API was implemented. |
|
9 | 9 | There's a single schema for calling all api methods. API is implemented |
|
10 |
with JSON protocol both ways. An url to send API request in RhodeCode is |
|
|
10 | with JSON protocol both ways. An url to send API request in RhodeCode is | |
|
11 | 11 | <your_server>/_admin/api |
|
12 | 12 | |
|
13 | 13 | |
@@ -22,90 +22,341 b' All clients need to send JSON data in su' | |||
|
22 | 22 | Example call for autopulling remotes repos using curl:: |
|
23 | 23 | curl https://server.com/_admin/api -X POST -H 'content-type:text/plain' --data-binary '{"api_key":"xe7cdb2v278e4evbdf5vs04v832v0efvcbcve4a3","method":"pull","args":{"repo":"CPython"}}' |
|
24 | 24 | |
|
25 |
Simply provide |
|
|
25 | Simply provide | |
|
26 | 26 | - *api_key* for access and permission validation. |
|
27 | 27 | - *method* is name of method to call |
|
28 | 28 | - *args* is an key:value list of arguments to pass to method |
|
29 | ||
|
29 | ||
|
30 | 30 | .. note:: |
|
31 | ||
|
32 |
api_key can be found in your user account page |
|
|
33 | ||
|
34 | ||
|
31 | ||
|
32 | api_key can be found in your user account page | |
|
33 | ||
|
34 | ||
|
35 | 35 | RhodeCode API will return always a JSON formatted answer:: |
|
36 | ||
|
36 | ||
|
37 | 37 | { |
|
38 |
"result": "<result>", |
|
|
38 | "result": "<result>", | |
|
39 | 39 | "error": null |
|
40 | 40 | } |
|
41 | 41 | |
|
42 | 42 | All responses from API will be `HTTP/1.0 200 OK`, if there's an error while |
|
43 |
calling api *error* key from response will contain failure description |
|
|
43 | calling api *error* key from response will contain failure description | |
|
44 | 44 | and result will be null. |
|
45 | 45 | |
|
46 | 46 | API METHODS |
|
47 | 47 | +++++++++++ |
|
48 | 48 | |
|
49 | ||
|
49 | ||
|
50 | 50 | pull |
|
51 | 51 | ---- |
|
52 | 52 | |
|
53 |
Pulls given repo from remote location. Can be used to automatically keep |
|
|
54 |
remote repos up to date. This command can be executed only using api_key |
|
|
55 | belonging to user with admin rights | |
|
56 | ||
|
57 | INPUT:: | |
|
58 | ||
|
59 | api_key:"<api_key>" | |
|
60 | method: "pull" | |
|
61 | args: {"repo":<repo_name>} | |
|
62 | ||
|
63 | OUTPUT:: | |
|
64 | ||
|
65 | result:"Pulled from <repo_name>" | |
|
66 | error:null | |
|
67 | ||
|
68 | ||
|
69 | create_user | |
|
70 | ----------- | |
|
71 | ||
|
72 | Creates new user in RhodeCode. This command can be executed only using api_key | |
|
53 | Pulls given repo from remote location. Can be used to automatically keep | |
|
54 | remote repos up to date. This command can be executed only using api_key | |
|
73 | 55 | belonging to user with admin rights |
|
74 | 56 | |
|
75 | 57 | INPUT:: |
|
76 | 58 | |
|
77 | api_key:"<api_key>" | |
|
78 |
method |
|
|
79 | args: {"username": "<username>", | |
|
80 |
|
|
|
81 | "active": "<bool>", | |
|
82 | "admin": "<bool>", | |
|
83 | "name": "<firstname>", | |
|
84 | "lastname": "<lastname>", | |
|
85 | "email": "<useremail>"} | |
|
59 | api_key : "<api_key>" | |
|
60 | method : "pull" | |
|
61 | args : { | |
|
62 | "repo" : "<repo_name>" | |
|
63 | } | |
|
64 | ||
|
65 | OUTPUT:: | |
|
66 | ||
|
67 | result : "Pulled from <repo_name>" | |
|
68 | error : null | |
|
69 | ||
|
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 | ||
|
100 | create_user | |
|
101 | ----------- | |
|
102 | ||
|
103 | Creates new user in RhodeCode. This command can be executed only using api_key | |
|
104 | belonging to user with admin rights. | |
|
105 | ||
|
106 | INPUT:: | |
|
107 | ||
|
108 | api_key : "<api_key>" | |
|
109 | method : "create_user" | |
|
110 | args : { | |
|
111 | "username" : "<username>", | |
|
112 | "password" : "<password>", | |
|
113 | "firstname" : "<firstname>", | |
|
114 | "lastname" : "<lastname>", | |
|
115 | "email" : "<useremail>" | |
|
116 | "active" : "<bool> = True", | |
|
117 | "admin" : "<bool> = False", | |
|
118 | "ldap_dn" : "<ldap_dn> = None" | |
|
119 | } | |
|
86 | 120 | |
|
87 | 121 | OUTPUT:: |
|
88 | 122 | |
|
89 | result:{"id": <newuserid>, | |
|
90 |
"msg":"created new user <username>" |
|
|
91 | error:null | |
|
92 | ||
|
93 | ||
|
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 : { } | |
|
139 | ||
|
140 | OUTPUT:: | |
|
141 | ||
|
142 | result : [ | |
|
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 | ] | |
|
162 | error : null | |
|
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 | |
|
199 | ||
|
94 | 200 | create_users_group |
|
95 | 201 | ------------------ |
|
96 | 202 | |
|
97 |
|
|
|
203 | Creates new users group. This command can be executed only using api_key | |
|
98 | 204 | belonging to user with admin rights |
|
99 | 205 | |
|
100 | 206 | INPUT:: |
|
101 | 207 | |
|
102 | api_key:"<api_key>" | |
|
103 | method: "create_user" | |
|
104 | args: {"name": "<groupname>", | |
|
105 |
|
|
|
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 | |
|
227 | belonging to user with admin rights | |
|
228 | ||
|
229 | INPUT:: | |
|
230 | ||
|
231 | api_key : "<api_key>" | |
|
232 | method : "add_user_users_group" | |
|
233 | args: { | |
|
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: { } | |
|
106 | 257 | |
|
107 | 258 | OUTPUT:: |
|
108 | 259 | |
|
109 | result:{"id": <newusersgroupid>, | |
|
110 | "msg":"created new users group <groupname>"} | |
|
111 | error:null | |
|
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 | } | |
|
284 | ||
|
285 | OUTPUT:: | |
|
286 | ||
|
287 | result: None if repository not exist | |
|
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 | } | |
|
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 | 24 | #smtp_port = |
|
25 | 25 | #smtp_use_tls = false |
|
26 | 26 | #smtp_use_ssl = true |
|
27 | # Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.) | |
|
28 | #smtp_auth = | |
|
27 | 29 | |
|
28 | 30 | [server:main] |
|
29 | 31 | ##nr of threads to spawn |
@@ -24,6 +24,8 b' pdebug = false' | |||
|
24 | 24 | #smtp_port = |
|
25 | 25 | #smtp_use_tls = false |
|
26 | 26 | #smtp_use_ssl = true |
|
27 | # Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.) | |
|
28 | #smtp_auth = | |
|
27 | 29 | |
|
28 | 30 | [server:main] |
|
29 | 31 | ##nr of threads to spawn |
@@ -146,7 +148,7 b' logview.pylons.util = #eee' | |||
|
146 | 148 | # SQLITE [default] |
|
147 | 149 | sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db |
|
148 | 150 | |
|
149 | # POSTGRES | |
|
151 | # POSTGRESQL | |
|
150 | 152 | # sqlalchemy.db1.url = postgresql://user:pass@localhost/rhodecode |
|
151 | 153 | |
|
152 | 154 | # MySQL |
@@ -26,7 +26,6 b'' | |||
|
26 | 26 | import logging |
|
27 | 27 | import traceback |
|
28 | 28 | import formencode |
|
29 | from operator import itemgetter | |
|
30 | 29 | from formencode import htmlfill |
|
31 | 30 | |
|
32 | 31 | from paste.httpexceptions import HTTPInternalServerError |
@@ -92,7 +91,7 b' class ReposController(BaseController):' | |||
|
92 | 91 | return redirect(url('repos')) |
|
93 | 92 | |
|
94 | 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 | 95 | .filter(UserFollowing.user_id == c.default_user_id)\ |
|
97 | 96 | .filter(UserFollowing.follows_repository == c.repo_info).scalar() |
|
98 | 97 | |
@@ -110,30 +109,7 b' class ReposController(BaseController):' | |||
|
110 | 109 | c.stats_percentage = '%.2f' % ((float((last_rev)) / |
|
111 | 110 | c.repo_last_rev) * 100) |
|
112 | 111 | |
|
113 | defaults = c.repo_info.get_dict() | |
|
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 | ||
|
112 | defaults = RepoModel()._get_defaults(repo_name) | |
|
137 | 113 | return defaults |
|
138 | 114 | |
|
139 | 115 | @HasPermissionAllDecorator('hg.admin') |
@@ -2,10 +2,18 b' import traceback' | |||
|
2 | 2 | import logging |
|
3 | 3 | |
|
4 | 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 | 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 | 18 | log = logging.getLogger(__name__) |
|
11 | 19 | |
@@ -13,86 +21,354 b' log = logging.getLogger(__name__)' | |||
|
13 | 21 | class ApiController(JSONRPCController): |
|
14 | 22 | """ |
|
15 | 23 | API Controller |
|
16 | ||
|
17 | ||
|
24 | ||
|
25 | ||
|
18 | 26 | Each method needs to have USER as argument this is then based on given |
|
19 | 27 | API_KEY propagated as instance of user object |
|
20 | ||
|
28 | ||
|
21 | 29 | Preferably this should be first argument also |
|
22 | ||
|
23 | ||
|
24 |
Each function should also **raise** JSONRPCError for any |
|
|
30 | ||
|
31 | ||
|
32 | Each function should also **raise** JSONRPCError for any | |
|
25 | 33 | errors that happens |
|
26 | ||
|
34 | ||
|
27 | 35 | """ |
|
28 | 36 | |
|
29 | 37 | @HasPermissionAllDecorator('hg.admin') |
|
30 | 38 | def pull(self, apiuser, repo): |
|
31 | 39 | """ |
|
32 | 40 | Dispatch pull action on given repo |
|
33 | ||
|
34 | ||
|
41 | ||
|
42 | ||
|
35 | 43 | :param user: |
|
36 | 44 | :param repo: |
|
37 | 45 | """ |
|
38 | 46 | |
|
39 | 47 | if Repository.is_valid(repo) is False: |
|
40 | 48 | raise JSONRPCError('Unknown repo "%s"' % repo) |
|
41 | ||
|
49 | ||
|
42 | 50 | try: |
|
43 | 51 | ScmModel().pull_changes(repo, self.rhodecode_user.username) |
|
44 | 52 | return 'Pulled from %s' % repo |
|
45 | 53 | except Exception: |
|
46 | 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 | 78 | @HasPermissionAllDecorator('hg.admin') |
|
50 | def create_user(self, apiuser, username, password, active, admin, name, | |
|
51 | lastname, email): | |
|
79 | def get_users(self, apiuser): | |
|
80 | """" | |
|
81 | Get all users | |
|
82 | ||
|
83 | :param apiuser | |
|
52 | 84 |
|
|
53 | Creates new user | |
|
54 | ||
|
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 | |
|
103 | ||
|
55 | 104 | :param apiuser: |
|
56 | 105 | :param username: |
|
57 | 106 | :param password: |
|
58 | :param active: | |
|
59 | :param admin: | |
|
60 | 107 | :param name: |
|
61 | 108 | :param lastname: |
|
62 | 109 | :param email: |
|
110 | :param active: | |
|
111 | :param admin: | |
|
112 | :param ldap_dn: | |
|
63 | 113 | """ |
|
64 | ||
|
65 | form_data = dict(username=username, | |
|
66 | password=password, | |
|
67 | active=active, | |
|
68 | admin=admin, | |
|
69 | name=name, | |
|
70 | lastname=lastname, | |
|
71 | email=email) | |
|
114 | ||
|
115 | if self.get_user(apiuser, username): | |
|
116 | raise JSONRPCError("user %s already exist" % username) | |
|
117 | ||
|
72 | 118 | try: |
|
73 | u = User.create(form_data) | |
|
74 | return {'id':u.user_id, | |
|
75 | 'msg':'created new user %s' % name} | |
|
119 | form_data = dict(username=username, | |
|
120 | password=password, | |
|
121 | active=active, | |
|
122 | admin=admin, | |
|
123 | name=firstname, | |
|
124 | lastname=lastname, | |
|
125 | email=email, | |
|
126 | ldap_dn=ldap_dn) | |
|
127 | UserModel().create_ldap(username, password, ldap_dn, form_data) | |
|
128 | return dict(msg='created new user %s' % username) | |
|
76 | 129 | except Exception: |
|
77 | 130 | log.error(traceback.format_exc()) |
|
78 | raise JSONRPCError('failed to create user %s' % name) | |
|
131 | raise JSONRPCError('failed to create user %s' % username) | |
|
132 | ||
|
133 | @HasPermissionAllDecorator('hg.admin') | |
|
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 | |
|
79 | 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) | |
|
80 | 162 | |
|
81 | 163 | @HasPermissionAllDecorator('hg.admin') |
|
82 |
def |
|
|
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 | 194 | Creates an new usergroup |
|
85 | ||
|
195 | ||
|
86 | 196 | :param name: |
|
87 | 197 | :param active: |
|
88 | 198 | """ |
|
89 | form_data = {'users_group_name':name, | |
|
90 | 'users_group_active':active} | |
|
199 | ||
|
200 | if self.get_users_group(apiuser, name): | |
|
201 | raise JSONRPCError("users group %s already exist" % name) | |
|
202 | ||
|
91 | 203 | try: |
|
204 | form_data = dict(users_group_name=name, | |
|
205 | users_group_active=active) | |
|
92 | 206 | ug = UsersGroup.create(form_data) |
|
93 |
return |
|
|
94 |
|
|
|
207 | return dict(id=ug.users_group_id, | |
|
208 | msg='created new users group %s' % name) | |
|
95 | 209 | except Exception: |
|
96 | 210 | log.error(traceback.format_exc()) |
|
97 | 211 | raise JSONRPCError('failed to create group %s' % name) |
|
98 | No newline at end of file | |
|
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 |
@@ -42,7 +42,7 b' from rhodecode.lib.utils import invalida' | |||
|
42 | 42 | |
|
43 | 43 | from rhodecode.model.forms import RepoSettingsForm, RepoForkForm |
|
44 | 44 | from rhodecode.model.repo import RepoModel |
|
45 |
from rhodecode.model.db import |
|
|
45 | from rhodecode.model.db import Group | |
|
46 | 46 | |
|
47 | 47 | log = logging.getLogger(__name__) |
|
48 | 48 | |
@@ -52,7 +52,15 b' class SettingsController(BaseRepoControl' | |||
|
52 | 52 | @LoginRequired() |
|
53 | 53 | def __before__(self): |
|
54 | 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 | 64 | @HasRepoPermissionAllDecorator('repository.admin') |
|
57 | 65 | def index(self, repo_name): |
|
58 | 66 | repo_model = RepoModel() |
@@ -66,28 +74,9 b' class SettingsController(BaseRepoControl' | |||
|
66 | 74 | |
|
67 | 75 | return redirect(url('home')) |
|
68 | 76 | |
|
69 | c.users_array = repo_model.get_users_js() | |
|
70 | c.users_groups_array = repo_model.get_users_groups_js() | |
|
71 | ||
|
72 | defaults = c.repo_info.get_dict() | |
|
77 | self.__load_defaults() | |
|
73 | 78 | |
|
74 | #fill owner | |
|
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}) | |
|
79 | defaults = RepoModel()._get_defaults(repo_name) | |
|
91 | 80 | |
|
92 | 81 | return htmlfill.render( |
|
93 | 82 | render('settings/repo_settings.html'), |
@@ -100,17 +89,22 b' class SettingsController(BaseRepoControl' | |||
|
100 | 89 | def update(self, repo_name): |
|
101 | 90 | repo_model = RepoModel() |
|
102 | 91 | changed_name = repo_name |
|
92 | ||
|
93 | self.__load_defaults() | |
|
94 | ||
|
103 | 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 | 98 | try: |
|
106 | 99 | form_result = _form.to_python(dict(request.POST)) |
|
100 | ||
|
107 | 101 | repo_model.update(repo_name, form_result) |
|
108 | 102 | invalidate_cache('get_repo_cached_%s' % repo_name) |
|
109 | 103 | h.flash(_('Repository %s updated successfully' % repo_name), |
|
110 | 104 | category='success') |
|
111 | changed_name = form_result['repo_name'] | |
|
105 | changed_name = form_result['repo_name_full'] | |
|
112 | 106 | action_logger(self.rhodecode_user, 'user_updated_repo', |
|
113 |
|
|
|
107 | changed_name, '', self.sa) | |
|
114 | 108 | except formencode.Invalid, errors: |
|
115 | 109 | c.repo_info = repo_model.get_by_repo_name(repo_name) |
|
116 | 110 | c.users_array = repo_model.get_users_js() |
@@ -394,13 +394,12 b' def get_current_revision(quiet=False):' | |||
|
394 | 394 | try: |
|
395 | 395 | from vcs import get_repo |
|
396 | 396 | from vcs.utils.helpers import get_scm |
|
397 | from vcs.exceptions import RepositoryError, VCSError | |
|
398 | 397 | repopath = os.path.join(os.path.dirname(__file__), '..', '..') |
|
399 | 398 | scm = get_scm(repopath)[0] |
|
400 | 399 | repo = get_repo(path=repopath, alias=scm) |
|
401 | 400 | tip = repo.get_changeset() |
|
402 | 401 | return (tip.revision, tip.short_id) |
|
403 | except (ImportError, RepositoryError, VCSError), err: | |
|
402 | except Exception, err: | |
|
404 | 403 | if not quiet: |
|
405 | 404 | print ("Cannot retrieve rhodecode's revision. Original error " |
|
406 | 405 | "was: %s" % err) |
@@ -53,8 +53,10 b' class AuthLdap(object):' | |||
|
53 | 53 | if self.TLS_KIND == 'LDAPS': |
|
54 | 54 | port = port or 689 |
|
55 | 55 | ldap_server_type = ldap_server_type + 's' |
|
56 | ||
|
57 | self.TLS_REQCERT = ldap.__dict__['OPT_X_TLS_' + tls_reqcert] | |
|
56 | ||
|
57 | OPT_X_TLS_DEMAND = 2 | |
|
58 | self.TLS_REQCERT = getattr(ldap, 'OPT_X_TLS_%s' % tls_reqcert, | |
|
59 | OPT_X_TLS_DEMAND) | |
|
58 | 60 | self.LDAP_SERVER_ADDRESS = server |
|
59 | 61 | self.LDAP_SERVER_PORT = port |
|
60 | 62 | |
@@ -63,12 +65,12 b' class AuthLdap(object):' | |||
|
63 | 65 | self.LDAP_BIND_PASS = bind_pass |
|
64 | 66 | |
|
65 | 67 | self.LDAP_SERVER = "%s://%s:%s" % (ldap_server_type, |
|
66 |
|
|
|
67 |
|
|
|
68 | self.LDAP_SERVER_ADDRESS, | |
|
69 | self.LDAP_SERVER_PORT) | |
|
68 | 70 | |
|
69 | 71 | self.BASE_DN = base_dn |
|
70 | 72 | self.LDAP_FILTER = ldap_filter |
|
71 |
self.SEARCH_SCOPE = ldap |
|
|
73 | self.SEARCH_SCOPE = getattr(ldap, 'SCOPE_%s' % search_scope) | |
|
72 | 74 | self.attr_login = attr_login |
|
73 | 75 | |
|
74 | 76 | def authenticate_ldap(self, username, password): |
@@ -88,7 +90,9 b' class AuthLdap(object):' | |||
|
88 | 90 | if "," in username: |
|
89 | 91 | raise LdapUsernameError("invalid character in username: ,") |
|
90 | 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 | 96 | ldap.set_option(ldap.OPT_REFERRALS, ldap.OPT_OFF) |
|
93 | 97 | ldap.set_option(ldap.OPT_RESTART, ldap.OPT_ON) |
|
94 | 98 | ldap.set_option(ldap.OPT_TIMEOUT, 20) |
@@ -356,9 +356,10 b' def send_email(recipients, subject, body' | |||
|
356 | 356 | tls = str2bool(email_config.get('smtp_use_tls')) |
|
357 | 357 | ssl = str2bool(email_config.get('smtp_use_ssl')) |
|
358 | 358 | debug = str2bool(config.get('debug')) |
|
359 | smtp_auth = email_config.get('smtp_auth') | |
|
359 | 360 | |
|
360 | 361 | try: |
|
361 | m = SmtpMailer(mail_from, user, passwd, mail_server, | |
|
362 | m = SmtpMailer(mail_from, user, passwd, mail_server,smtp_auth, | |
|
362 | 363 | mail_port, ssl, tls, debug=debug) |
|
363 | 364 | m.send(recipients, subject, body) |
|
364 | 365 | except: |
@@ -167,6 +167,8 b' class SimpleGit(object):' | |||
|
167 | 167 | username = REMOTE_USER(environ) |
|
168 | 168 | try: |
|
169 | 169 | user = self.__get_user(username) |
|
170 | if user is None: | |
|
171 | return HTTPForbidden()(environ, start_response) | |
|
170 | 172 | username = user.username |
|
171 | 173 | except: |
|
172 | 174 | log.error(traceback.format_exc()) |
@@ -133,6 +133,8 b' class SimpleHg(object):' | |||
|
133 | 133 | username = REMOTE_USER(environ) |
|
134 | 134 | try: |
|
135 | 135 | user = self.__get_user(username) |
|
136 | if user is None: | |
|
137 | return HTTPForbidden()(environ, start_response) | |
|
136 | 138 | username = user.username |
|
137 | 139 | except: |
|
138 | 140 | log.error(traceback.format_exc()) |
@@ -39,7 +39,7 b' from email import encoders' | |||
|
39 | 39 | class SmtpMailer(object): |
|
40 | 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 | 43 | mail_port, ssl, tls) |
|
44 | 44 | mailer.send(recipients, subject, body, attachment_files) |
|
45 | 45 | |
@@ -49,8 +49,8 b' class SmtpMailer(object):' | |||
|
49 | 49 | |
|
50 | 50 | """ |
|
51 | 51 | |
|
52 | def __init__(self, mail_from, user, passwd, mail_server, | |
|
53 |
|
|
|
52 | def __init__(self, mail_from, user, passwd, mail_server, smtp_auth=None, | |
|
53 | mail_port=None, ssl=False, tls=False, debug=False): | |
|
54 | 54 | |
|
55 | 55 | self.mail_from = mail_from |
|
56 | 56 | self.mail_server = mail_server |
@@ -60,6 +60,7 b' class SmtpMailer(object):' | |||
|
60 | 60 | self.ssl = ssl |
|
61 | 61 | self.tls = tls |
|
62 | 62 | self.debug = debug |
|
63 | self.auth = smtp_auth | |
|
63 | 64 | |
|
64 | 65 | def send(self, recipients=[], subject='', body='', attachment_files=None): |
|
65 | 66 | |
@@ -78,9 +79,11 b' class SmtpMailer(object):' | |||
|
78 | 79 | smtp_serv.set_debuglevel(1) |
|
79 | 80 | |
|
80 | 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 | |
|
83 | #but only if we have them | |
|
85 | # if server requires authorization you must provide login and password | |
|
86 | # but only if we have them | |
|
84 | 87 | if self.user and self.passwd: |
|
85 | 88 | smtp_serv.login(self.user, self.passwd) |
|
86 | 89 | |
@@ -156,6 +159,7 b' class SmtpMailer(object):' | |||
|
156 | 159 | if isinstance(msg_file, str): |
|
157 | 160 | return open(msg_file, "rb").read() |
|
158 | 161 | else: |
|
159 | #just for safe seek to 0 | |
|
162 | # just for safe seek to 0 | |
|
160 | 163 | msg_file.seek(0) |
|
161 | 164 | return msg_file.read() |
|
165 |
@@ -30,11 +30,8 b' import traceback' | |||
|
30 | 30 | from datetime import date |
|
31 | 31 | |
|
32 | 32 | from sqlalchemy import * |
|
33 | from sqlalchemy.exc import DatabaseError | |
|
34 | 33 | from sqlalchemy.ext.hybrid import hybrid_property |
|
35 |
from sqlalchemy.orm import relationship, |
|
|
36 | validates | |
|
37 | from sqlalchemy.orm.interfaces import MapperExtension | |
|
34 | from sqlalchemy.orm import relationship, joinedload, class_mapper, validates | |
|
38 | 35 | from beaker.cache import cache_region, region_invalidate |
|
39 | 36 | |
|
40 | 37 | from vcs import get_backend |
@@ -60,24 +57,24 b' log = logging.getLogger(__name__)' | |||
|
60 | 57 | class ModelSerializer(json.JSONEncoder): |
|
61 | 58 | """ |
|
62 | 59 | Simple Serializer for JSON, |
|
63 | ||
|
60 | ||
|
64 | 61 | usage:: |
|
65 | ||
|
62 | ||
|
66 | 63 | to make object customized for serialization implement a __json__ |
|
67 | 64 | method that will return a dict for serialization into json |
|
68 | ||
|
65 | ||
|
69 | 66 | example:: |
|
70 | ||
|
67 | ||
|
71 | 68 | class Task(object): |
|
72 | ||
|
69 | ||
|
73 | 70 | def __init__(self, name, value): |
|
74 | 71 | self.name = name |
|
75 | 72 | self.value = value |
|
76 | ||
|
73 | ||
|
77 | 74 | def __json__(self): |
|
78 | 75 | return dict(name=self.name, |
|
79 |
value=self.value) |
|
|
80 | ||
|
76 | value=self.value) | |
|
77 | ||
|
81 | 78 | """ |
|
82 | 79 | |
|
83 | 80 | def default(self, obj): |
@@ -129,11 +126,15 b' class BaseModel(object):' | |||
|
129 | 126 | @classmethod |
|
130 | 127 | def get(cls, id_): |
|
131 | 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 | 135 | @classmethod |
|
135 | 136 | def delete(cls, id_): |
|
136 |
obj = |
|
|
137 | obj = cls.query().get(id_) | |
|
137 | 138 | Session.delete(obj) |
|
138 | 139 | Session.commit() |
|
139 | 140 | |
@@ -160,13 +161,13 b' class RhodeCodeSettings(Base, BaseModel)' | |||
|
160 | 161 | v = self._app_settings_value |
|
161 | 162 | if v == 'ldap_active': |
|
162 | 163 | v = str2bool(v) |
|
163 |
return v |
|
|
164 | return v | |
|
164 | 165 | |
|
165 | 166 | @app_settings_value.setter |
|
166 | def app_settings_value(self,val): | |
|
167 | def app_settings_value(self, val): | |
|
167 | 168 | """ |
|
168 | 169 | Setter that will always make sure we use unicode in app_settings_value |
|
169 | ||
|
170 | ||
|
170 | 171 | :param val: |
|
171 | 172 | """ |
|
172 | 173 | self._app_settings_value = safe_unicode(val) |
@@ -178,13 +179,13 b' class RhodeCodeSettings(Base, BaseModel)' | |||
|
178 | 179 | |
|
179 | 180 | @classmethod |
|
180 | 181 | def get_by_name(cls, ldap_key): |
|
181 |
return |
|
|
182 | return cls.query()\ | |
|
182 | 183 | .filter(cls.app_settings_name == ldap_key).scalar() |
|
183 | 184 | |
|
184 | 185 | @classmethod |
|
185 | 186 | def get_app_settings(cls, cache=False): |
|
186 | 187 | |
|
187 |
ret = |
|
|
188 | ret = cls.query() | |
|
188 | 189 | |
|
189 | 190 | if cache: |
|
190 | 191 | ret = ret.options(FromCache("sql_cache_short", "get_hg_settings")) |
@@ -200,7 +201,7 b' class RhodeCodeSettings(Base, BaseModel)' | |||
|
200 | 201 | |
|
201 | 202 | @classmethod |
|
202 | 203 | def get_ldap_settings(cls, cache=False): |
|
203 |
ret = |
|
|
204 | ret = cls.query()\ | |
|
204 | 205 | .filter(cls.app_settings_name.startswith('ldap_')).all() |
|
205 | 206 | fd = {} |
|
206 | 207 | for row in ret: |
@@ -227,7 +228,7 b' class RhodeCodeUi(Base, BaseModel):' | |||
|
227 | 228 | |
|
228 | 229 | @classmethod |
|
229 | 230 | def get_by_key(cls, key): |
|
230 |
return |
|
|
231 | return cls.query().filter(cls.ui_key == key) | |
|
231 | 232 | |
|
232 | 233 | |
|
233 | 234 | @classmethod |
@@ -311,7 +312,7 b' class User(Base, BaseModel):' | |||
|
311 | 312 | |
|
312 | 313 | @classmethod |
|
313 | 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 | 317 | def update_lastlogin(self): |
|
317 | 318 | """Update user lastlogin""" |
@@ -376,11 +377,11 b' class UsersGroup(Base, BaseModel):' | |||
|
376 | 377 | @classmethod |
|
377 | 378 | def get_by_group_name(cls, group_name, cache=False, case_insensitive=False): |
|
378 | 379 | if case_insensitive: |
|
379 |
gr = |
|
|
380 | .filter(cls.users_group_name.ilike(group_name)) | |
|
380 | gr = cls.query()\ | |
|
381 | .filter(cls.users_group_name.ilike(group_name)) | |
|
381 | 382 | else: |
|
382 |
gr = |
|
|
383 |
.filter( |
|
|
383 | gr = cls.query()\ | |
|
384 | .filter(cls.users_group_name == group_name) | |
|
384 | 385 | if cache: |
|
385 | 386 | gr = gr.options(FromCache("sql_cache_short", |
|
386 | 387 | "get_user_%s" % group_name)) |
@@ -389,7 +390,7 b' class UsersGroup(Base, BaseModel):' | |||
|
389 | 390 | |
|
390 | 391 | @classmethod |
|
391 | 392 | def get(cls, users_group_id, cache=False): |
|
392 |
users_group = |
|
|
393 | users_group = cls.query() | |
|
393 | 394 | if cache: |
|
394 | 395 | users_group = users_group.options(FromCache("sql_cache_short", |
|
395 | 396 | "get_users_group_%s" % users_group_id)) |
@@ -422,10 +423,10 b' class UsersGroup(Base, BaseModel):' | |||
|
422 | 423 | Session.flush() |
|
423 | 424 | members_list = [] |
|
424 | 425 | if v: |
|
426 | v = [v] if isinstance(v, basestring) else v | |
|
425 | 427 | for u_id in set(v): |
|
426 |
member |
|
|
427 | users_group_id, | |
|
428 | u_id)) | |
|
428 | member = UsersGroupMember(users_group_id, u_id) | |
|
429 | members_list.append(member) | |
|
429 | 430 | setattr(users_group, 'members', members_list) |
|
430 | 431 | setattr(users_group, k, v) |
|
431 | 432 | |
@@ -457,7 +458,6 b' class UsersGroup(Base, BaseModel):' | |||
|
457 | 458 | Session.rollback() |
|
458 | 459 | raise |
|
459 | 460 | |
|
460 | ||
|
461 | 461 | class UsersGroupMember(Base, BaseModel): |
|
462 | 462 | __tablename__ = 'users_groups_members' |
|
463 | 463 | __table_args__ = {'extend_existing':True} |
@@ -473,6 +473,15 b' class UsersGroupMember(Base, BaseModel):' | |||
|
473 | 473 | self.users_group_id = gr_id |
|
474 | 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 | 485 | class Repository(Base, BaseModel): |
|
477 | 486 | __tablename__ = 'repositories' |
|
478 | 487 | __table_args__ = (UniqueConstraint('repo_name'), {'extend_existing':True},) |
@@ -510,29 +519,27 b' class Repository(Base, BaseModel):' | |||
|
510 | 519 | @classmethod |
|
511 | 520 | def url_sep(cls): |
|
512 | 521 | return '/' |
|
513 | ||
|
522 | ||
|
514 | 523 | @classmethod |
|
515 | 524 | def get_by_repo_name(cls, repo_name): |
|
516 | 525 | q = Session.query(cls).filter(cls.repo_name == repo_name) |
|
517 | ||
|
518 | 526 | q = q.options(joinedload(Repository.fork))\ |
|
519 | 527 | .options(joinedload(Repository.user))\ |
|
520 |
.options(joinedload(Repository.group)) |
|
|
521 | ||
|
528 | .options(joinedload(Repository.group)) | |
|
522 | 529 | return q.one() |
|
523 | 530 | |
|
524 | 531 | @classmethod |
|
525 | 532 | def get_repo_forks(cls, repo_id): |
|
526 |
return |
|
|
533 | return cls.query().filter(Repository.fork_id == repo_id) | |
|
527 | 534 | |
|
528 | 535 | @classmethod |
|
529 | 536 | def base_path(cls): |
|
530 | 537 | """ |
|
531 | 538 | Returns base path when all repos are stored |
|
532 | ||
|
539 | ||
|
533 | 540 | :param cls: |
|
534 | 541 | """ |
|
535 |
q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == |
|
|
542 | q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == | |
|
536 | 543 | cls.url_sep()) |
|
537 | 544 | q.options(FromCache("sql_cache_short", "repository_repo_path")) |
|
538 | 545 | return q.one().ui_value |
@@ -568,7 +575,7 b' class Repository(Base, BaseModel):' | |||
|
568 | 575 | Returns base full path for that repository means where it actually |
|
569 | 576 | exists on a filesystem |
|
570 | 577 | """ |
|
571 |
q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == |
|
|
578 | q = Session.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == | |
|
572 | 579 | Repository.url_sep()) |
|
573 | 580 | q.options(FromCache("sql_cache_short", "repository_repo_path")) |
|
574 | 581 | return q.one().ui_value |
@@ -585,7 +592,7 b' class Repository(Base, BaseModel):' | |||
|
585 | 592 | def get_new_name(self, repo_name): |
|
586 | 593 | """ |
|
587 | 594 | returns new full repository name based on assigned group and new new |
|
588 | ||
|
595 | ||
|
589 | 596 | :param group_name: |
|
590 | 597 | """ |
|
591 | 598 | path_prefix = self.group.full_path_splitted if self.group else [] |
@@ -606,7 +613,7 b' class Repository(Base, BaseModel):' | |||
|
606 | 613 | baseui._tcfg = config.config() |
|
607 | 614 | |
|
608 | 615 | |
|
609 |
ret = |
|
|
616 | ret = RhodeCodeUi.query()\ | |
|
610 | 617 | .options(FromCache("sql_cache_short", "repository_repo_ui")).all() |
|
611 | 618 | |
|
612 | 619 | hg_ui = ret |
@@ -622,7 +629,7 b' class Repository(Base, BaseModel):' | |||
|
622 | 629 | def is_valid(cls, repo_name): |
|
623 | 630 | """ |
|
624 | 631 | returns True if given repo name is a valid filesystem repository |
|
625 | ||
|
632 | ||
|
626 | 633 | @param cls: |
|
627 | 634 | @param repo_name: |
|
628 | 635 | """ |
@@ -661,7 +668,7 b' class Repository(Base, BaseModel):' | |||
|
661 | 668 | None otherwise. `cache_active = False` means that this cache |
|
662 | 669 | state is not valid and needs to be invalidated |
|
663 | 670 | """ |
|
664 |
return |
|
|
671 | return CacheInvalidation.query()\ | |
|
665 | 672 | .filter(CacheInvalidation.cache_key == self.repo_name)\ |
|
666 | 673 | .filter(CacheInvalidation.cache_active == False)\ |
|
667 | 674 | .scalar() |
@@ -670,7 +677,7 b' class Repository(Base, BaseModel):' | |||
|
670 | 677 | """ |
|
671 | 678 | set a cache for invalidation for this instance |
|
672 | 679 | """ |
|
673 |
inv = |
|
|
680 | inv = CacheInvalidation.query()\ | |
|
674 | 681 | .filter(CacheInvalidation.cache_key == self.repo_name)\ |
|
675 | 682 | .scalar() |
|
676 | 683 | |
@@ -763,17 +770,26 b' class Group(Base, BaseModel):' | |||
|
763 | 770 | |
|
764 | 771 | repo_groups.extend([(x.group_id, _name(x.full_path_splitted)) |
|
765 | 772 | for x in cls.query().all()]) |
|
766 | ||
|
767 |
repo_groups = sorted(repo_groups,key=lambda t: t[1].split(sep)[0]) |
|
|
773 | ||
|
774 | repo_groups = sorted(repo_groups, key=lambda t: t[1].split(sep)[0]) | |
|
768 | 775 | return repo_groups |
|
769 | ||
|
776 | ||
|
770 | 777 | @classmethod |
|
771 | 778 | def url_sep(cls): |
|
772 | 779 | return '/' |
|
773 | 780 | |
|
774 | 781 | @classmethod |
|
775 | def get_by_group_name(cls, group_name): | |
|
776 | return cls.query().filter(cls.group_name == group_name).scalar() | |
|
782 | def get_by_group_name(cls, group_name, cache=False, case_insensitive=False): | |
|
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 | 794 | @property |
|
779 | 795 | def parents(self): |
@@ -801,7 +817,7 b' class Group(Base, BaseModel):' | |||
|
801 | 817 | |
|
802 | 818 | @property |
|
803 | 819 | def children(self): |
|
804 |
return |
|
|
820 | return Group.query().filter(Group.parent_group == self) | |
|
805 | 821 | |
|
806 | 822 | @property |
|
807 | 823 | def name(self): |
@@ -817,7 +833,7 b' class Group(Base, BaseModel):' | |||
|
817 | 833 | |
|
818 | 834 | @property |
|
819 | 835 | def repositories(self): |
|
820 |
return |
|
|
836 | return Repository.query().filter(Repository.group == self) | |
|
821 | 837 | |
|
822 | 838 | @property |
|
823 | 839 | def repositories_recursive_count(self): |
@@ -836,10 +852,11 b' class Group(Base, BaseModel):' | |||
|
836 | 852 | def get_new_name(self, group_name): |
|
837 | 853 | """ |
|
838 | 854 | returns new full group name based on parent and new name |
|
839 | ||
|
855 | ||
|
840 | 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 | 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 | 874 | @classmethod |
|
858 | 875 | def get_by_key(cls, key): |
|
859 |
return |
|
|
876 | return cls.query().filter(cls.permission_name == key).scalar() | |
|
860 | 877 | |
|
861 | 878 | class RepoToPerm(Base, BaseModel): |
|
862 | 879 | __tablename__ = 'repo_to_perm' |
@@ -885,7 +902,7 b' class UserToPerm(Base, BaseModel):' | |||
|
885 | 902 | if not isinstance(perm, Permission): |
|
886 | 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 | 906 | .filter(cls.permission == perm).scalar() is not None |
|
890 | 907 | |
|
891 | 908 | @classmethod |
@@ -909,7 +926,7 b' class UserToPerm(Base, BaseModel):' | |||
|
909 | 926 | raise Exception('perm needs to be an instance of Permission class') |
|
910 | 927 | |
|
911 | 928 | try: |
|
912 |
|
|
|
929 | cls.query().filter(cls.user_id == user_id)\ | |
|
913 | 930 | .filter(cls.permission == perm).delete() |
|
914 | 931 | Session.commit() |
|
915 | 932 | except: |
@@ -945,7 +962,7 b' class UsersGroupToPerm(Base, BaseModel):' | |||
|
945 | 962 | if not isinstance(perm, Permission): |
|
946 | 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 | 966 | users_group_id)\ |
|
950 | 967 | .filter(cls.permission == perm)\ |
|
951 | 968 | .scalar() is not None |
@@ -971,7 +988,7 b' class UsersGroupToPerm(Base, BaseModel):' | |||
|
971 | 988 | raise Exception('perm needs to be an instance of Permission class') |
|
972 | 989 | |
|
973 | 990 | try: |
|
974 |
|
|
|
991 | cls.query().filter(cls.users_group_id == users_group_id)\ | |
|
975 | 992 | .filter(cls.permission == perm).delete() |
|
976 | 993 | Session.commit() |
|
977 | 994 | except: |
@@ -1023,7 +1040,7 b' class UserFollowing(Base, BaseModel):' | |||
|
1023 | 1040 | |
|
1024 | 1041 | @classmethod |
|
1025 | 1042 | def get_repo_followers(cls, repo_id): |
|
1026 |
return |
|
|
1043 | return cls.query().filter(cls.follows_repo_id == repo_id) | |
|
1027 | 1044 | |
|
1028 | 1045 | class CacheInvalidation(Base, BaseModel): |
|
1029 | 1046 | __tablename__ = 'cache_invalidation' |
@@ -1049,3 +1066,4 b' class DbMigrateVersion(Base, BaseModel):' | |||
|
1049 | 1066 | repository_id = Column('repository_id', String(250), primary_key=True) |
|
1050 | 1067 | repository_path = Column('repository_path', Text) |
|
1051 | 1068 | version = Column('version', Integer) |
|
1069 |
@@ -185,20 +185,21 b' class ValidPassword(formencode.validator' | |||
|
185 | 185 | class ValidPasswordsMatch(formencode.validators.FancyValidator): |
|
186 | 186 | |
|
187 | 187 | def validate_python(self, value, state): |
|
188 | ||
|
189 |
|
|
|
188 | ||
|
189 | pass_val = value.get('password') or value.get('new_password') | |
|
190 | if pass_val != value['password_confirmation']: | |
|
190 | 191 | e_dict = {'password_confirmation': |
|
191 | 192 | _('Passwords do not match')} |
|
192 | 193 | raise formencode.Invalid('', value, state, error_dict=e_dict) |
|
193 | 194 | |
|
194 | 195 | class ValidAuth(formencode.validators.FancyValidator): |
|
195 | 196 | messages = { |
|
196 |
|
|
|
197 |
|
|
|
198 |
|
|
|
199 | ||
|
200 | } | |
|
201 | #error mapping | |
|
197 | 'invalid_password':_('invalid password'), | |
|
198 | 'invalid_login':_('invalid user name'), | |
|
199 | 'disabled_account':_('Your account is disabled') | |
|
200 | } | |
|
201 | ||
|
202 | # error mapping | |
|
202 | 203 | e_dict = {'username':messages['invalid_login'], |
|
203 | 204 | 'password':messages['invalid_password']} |
|
204 | 205 | e_dict_disable = {'username':messages['disabled_account']} |
@@ -253,6 +254,7 b' def ValidRepoName(edit, old_data):' | |||
|
253 | 254 | # db key This is an actual just the name to store in the |
|
254 | 255 | # database |
|
255 | 256 | repo_name_full = group_path + Group.url_sep() + repo_name |
|
257 | ||
|
256 | 258 | else: |
|
257 | 259 | group_path = '' |
|
258 | 260 | repo_name_full = repo_name |
@@ -496,8 +498,6 b' class LoginForm(formencode.Schema):' | |||
|
496 | 498 | 'tooShort':_('Enter %(min)i characters or more')} |
|
497 | 499 | ) |
|
498 | 500 | |
|
499 | ||
|
500 | #chained validators have access to all data | |
|
501 | 501 | chained_validators = [ValidAuth] |
|
502 | 502 | |
|
503 | 503 | def UserForm(edit=False, old_data={}): |
@@ -508,15 +508,18 b' def UserForm(edit=False, old_data={}):' | |||
|
508 | 508 | ValidUsername(edit, old_data)) |
|
509 | 509 | if edit: |
|
510 | 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 | 512 | admin = StringBoolean(if_missing=False) |
|
512 | 513 | else: |
|
513 | 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 | 517 | active = StringBoolean(if_missing=False) |
|
515 | 518 | name = UnicodeString(strip=True, min=1, not_empty=True) |
|
516 | 519 | lastname = UnicodeString(strip=True, min=1, not_empty=True) |
|
517 | 520 | email = All(Email(not_empty=True), UniqSystemEmail(old_data)) |
|
518 | 521 | |
|
519 | chained_validators = [ValidPassword] | |
|
522 | chained_validators = [ValidPasswordsMatch, ValidPassword] | |
|
520 | 523 | |
|
521 | 524 | return _UserForm |
|
522 | 525 | |
@@ -616,16 +619,19 b' def RepoForkForm(edit=False, old_data={}' | |||
|
616 | 619 | |
|
617 | 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 | 624 | class _RepoForm(formencode.Schema): |
|
621 | 625 | allow_extra_fields = True |
|
622 | 626 | filter_extra_fields = False |
|
623 | 627 | repo_name = All(UnicodeString(strip=True, min=1, not_empty=True), |
|
624 | 628 | SlugifyName()) |
|
625 | 629 | description = UnicodeString(strip=True, min=1, not_empty=True) |
|
630 | repo_group = OneOf(repo_groups, hideList=True) | |
|
626 | 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 | 635 | return _RepoForm |
|
630 | 636 | |
|
631 | 637 |
@@ -94,6 +94,46 b' class RepoModel(BaseModel):' | |||
|
94 | 94 | for gr in users_groups]) |
|
95 | 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 | 137 | def update(self, repo_name, form_data): |
|
98 | 138 | try: |
|
99 | 139 | cur_repo = self.get_by_repo_name(repo_name, cache=False) |
@@ -151,7 +191,7 b' class RepoModel(BaseModel):' | |||
|
151 | 191 | elif k == 'repo_name': |
|
152 | 192 | pass |
|
153 | 193 | elif k == 'repo_group': |
|
154 |
cur_repo.group |
|
|
194 | cur_repo.group = Group.get(v) | |
|
155 | 195 | |
|
156 | 196 | else: |
|
157 | 197 | setattr(cur_repo, k, v) |
@@ -305,7 +345,7 b' class RepoModel(BaseModel):' | |||
|
305 | 345 | :param parent_id: |
|
306 | 346 | :param clone_uri: |
|
307 | 347 | """ |
|
308 | from rhodecode.lib.utils import is_valid_repo,is_valid_repos_group | |
|
348 | from rhodecode.lib.utils import is_valid_repo, is_valid_repos_group | |
|
309 | 349 | |
|
310 | 350 | if new_parent_id: |
|
311 | 351 | paths = Group.get(new_parent_id).full_path.split(Group.url_sep()) |
@@ -316,7 +356,7 b' class RepoModel(BaseModel):' | |||
|
316 | 356 | repo_path = os.path.join(*map(lambda x:safe_str(x), |
|
317 | 357 | [self.repos_path, new_parent_path, repo_name])) |
|
318 | 358 | |
|
319 | ||
|
359 | ||
|
320 | 360 | # check if this path is not a repository |
|
321 | 361 | if is_valid_repo(repo_path, self.repos_path): |
|
322 | 362 | raise Exception('This path %s is a valid repository' % repo_path) |
@@ -324,7 +364,7 b' class RepoModel(BaseModel):' | |||
|
324 | 364 | # check if this path is a group |
|
325 | 365 | if is_valid_repos_group(repo_path, self.repos_path): |
|
326 | 366 | raise Exception('This path %s is a valid group' % repo_path) |
|
327 | ||
|
367 | ||
|
328 | 368 | log.info('creating repo %s in %s @ %s', repo_name, repo_path, |
|
329 | 369 | clone_uri) |
|
330 | 370 | backend = get_backend(alias) |
@@ -368,3 +408,4 b' class RepoModel(BaseModel):' | |||
|
368 | 408 | % (datetime.today()\ |
|
369 | 409 | .strftime('%Y%m%d_%H%M%S_%f'), |
|
370 | 410 | repo.repo_name))) |
|
411 |
@@ -127,8 +127,8 b' class ReposGroupModel(BaseModel):' | |||
|
127 | 127 | try: |
|
128 | 128 | repos_group = Group.get(repos_group_id) |
|
129 | 129 | old_path = repos_group.full_path |
|
130 | ||
|
131 | #change properties | |
|
130 | ||
|
131 | # change properties | |
|
132 | 132 | repos_group.group_description = form_data['group_description'] |
|
133 | 133 | repos_group.parent_group = Group.get(form_data['group_parent_id']) |
|
134 | 134 | repos_group.group_name = repos_group.get_new_name(form_data['group_name']) |
@@ -49,7 +49,6 b" PERM_WEIGHTS = {'repository.none': 0," | |||
|
49 | 49 | |
|
50 | 50 | |
|
51 | 51 | class UserModel(BaseModel): |
|
52 | ||
|
53 | 52 | def get(self, user_id, cache=False): |
|
54 | 53 | user = self.sa.query(User) |
|
55 | 54 | if cache: |
@@ -87,6 +86,7 b' class UserModel(BaseModel):' | |||
|
87 | 86 | new_user.api_key = generate_api_key(form_data['username']) |
|
88 | 87 | self.sa.add(new_user) |
|
89 | 88 | self.sa.commit() |
|
89 | return new_user | |
|
90 | 90 | except: |
|
91 | 91 | log.error(traceback.format_exc()) |
|
92 | 92 | self.sa.rollback() |
@@ -96,6 +96,7 b' class UserModel(BaseModel):' | |||
|
96 | 96 | """ |
|
97 | 97 | Checks if user is in database, if not creates this user marked |
|
98 | 98 | as ldap user |
|
99 | ||
|
99 | 100 | :param username: |
|
100 | 101 | :param password: |
|
101 | 102 | :param user_dn: |
@@ -386,3 +387,4 b' class UserModel(BaseModel):' | |||
|
386 | 387 | repository.repo_name] = p |
|
387 | 388 | |
|
388 | 389 | return user |
|
390 |
@@ -29,7 +29,7 b'' | |||
|
29 | 29 | <div class="fields"> |
|
30 | 30 | <div class="field"> |
|
31 | 31 | <div class="label"> |
|
32 |
<label for=" |
|
|
32 | <label for="group_name">${_('Group name')}:</label> | |
|
33 | 33 | </div> |
|
34 | 34 | <div class="input"> |
|
35 | 35 | ${h.text('group_name',class_='medium')} |
@@ -38,7 +38,7 b'' | |||
|
38 | 38 | |
|
39 | 39 | <div class="field"> |
|
40 | 40 | <div class="label label-textarea"> |
|
41 | <label for="description">${_('Description')}:</label> | |
|
41 | <label for="group_description">${_('Description')}:</label> | |
|
42 | 42 | </div> |
|
43 | 43 | <div class="textarea text-area editor"> |
|
44 | 44 | ${h.textarea('group_description',cols=23,rows=5,class_="medium")} |
@@ -47,7 +47,7 b'' | |||
|
47 | 47 | |
|
48 | 48 | <div class="field"> |
|
49 | 49 | <div class="label"> |
|
50 |
<label for=" |
|
|
50 | <label for="group_parent_id">${_('Group parent')}:</label> | |
|
51 | 51 | </div> |
|
52 | 52 | <div class="input"> |
|
53 | 53 | ${h.select('group_parent_id','',c.repo_groups,class_="medium")} |
@@ -29,7 +29,7 b'' | |||
|
29 | 29 | <div class="fields"> |
|
30 | 30 | <div class="field"> |
|
31 | 31 | <div class="label"> |
|
32 |
<label for=" |
|
|
32 | <label for="group_name">${_('Group name')}:</label> | |
|
33 | 33 | </div> |
|
34 | 34 | <div class="input"> |
|
35 | 35 | ${h.text('group_name',class_='medium')} |
@@ -38,7 +38,7 b'' | |||
|
38 | 38 | |
|
39 | 39 | <div class="field"> |
|
40 | 40 | <div class="label label-textarea"> |
|
41 | <label for="description">${_('Description')}:</label> | |
|
41 | <label for="group_description">${_('Description')}:</label> | |
|
42 | 42 | </div> |
|
43 | 43 | <div class="textarea text-area editor"> |
|
44 | 44 | ${h.textarea('group_description',cols=23,rows=5,class_="medium")} |
@@ -47,7 +47,7 b'' | |||
|
47 | 47 | |
|
48 | 48 | <div class="field"> |
|
49 | 49 | <div class="label"> |
|
50 |
<label for=" |
|
|
50 | <label for="group_parent_id">${_('Group parent')}:</label> | |
|
51 | 51 | </div> |
|
52 | 52 | <div class="input"> |
|
53 | 53 | ${h.select('group_parent_id','',c.repo_groups,class_="medium")} |
@@ -34,7 +34,7 b'' | |||
|
34 | 34 | <div class="checkboxes"> |
|
35 | 35 | <div class="checkbox"> |
|
36 | 36 | ${h.checkbox('destroy',True)} |
|
37 |
<label for=" |
|
|
37 | <label for="destroy"> | |
|
38 | 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 | 39 | ${_('destroy old data')}</span> </label> |
|
40 | 40 | </div> |
@@ -56,12 +56,12 b'' | |||
|
56 | 56 | <div class="fields"> |
|
57 | 57 | <div class="field"> |
|
58 | 58 | <div class="label label-checkbox"> |
|
59 |
<label |
|
|
59 | <label>${_('index build option')}:</label> | |
|
60 | 60 | </div> |
|
61 | 61 | <div class="checkboxes"> |
|
62 | 62 | <div class="checkbox"> |
|
63 | 63 | ${h.checkbox('full_index',True)} |
|
64 |
<label for=" |
|
|
64 | <label for="full_index">${_('build from scratch')}</label> | |
|
65 | 65 | </div> |
|
66 | 66 | </div> |
|
67 | 67 | </div> |
@@ -100,7 +100,7 b'' | |||
|
100 | 100 | |
|
101 | 101 | <div class="field"> |
|
102 | 102 | <div class="label"> |
|
103 | <label for="ga_code">${_('GA code')}:</label> | |
|
103 | <label for="rhodecode_ga_code">${_('GA code')}:</label> | |
|
104 | 104 | </div> |
|
105 | 105 | <div class="input"> |
|
106 | 106 | ${h.text('rhodecode_ga_code',size=30)} |
@@ -124,7 +124,7 b'' | |||
|
124 | 124 | |
|
125 | 125 | <div class="field"> |
|
126 | 126 | <div class="label label-checkbox"> |
|
127 |
<label |
|
|
127 | <label>${_('Web')}:</label> | |
|
128 | 128 | </div> |
|
129 | 129 | <div class="checkboxes"> |
|
130 | 130 | <div class="checkbox"> |
@@ -136,7 +136,7 b'' | |||
|
136 | 136 | |
|
137 | 137 | <div class="field"> |
|
138 | 138 | <div class="label label-checkbox"> |
|
139 |
<label |
|
|
139 | <label>${_('Hooks')}:</label> | |
|
140 | 140 | </div> |
|
141 | 141 | <div class="input"> |
|
142 | 142 | ${h.link_to(_('advanced setup'),url('admin_edit_setting',setting_id='hooks'))} |
@@ -44,7 +44,16 b'' | |||
|
44 | 44 | ${h.password('password',class_='small')} |
|
45 | 45 | </div> |
|
46 | 46 | </div> |
|
47 | ||
|
47 | ||
|
48 | <div class="field"> | |
|
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 | ||
|
48 | 57 | <div class="field"> |
|
49 | 58 | <div class="label"> |
|
50 | 59 | <label for="name">${_('First Name')}:</label> |
@@ -68,7 +68,16 b'' | |||
|
68 | 68 | ${h.password('new_password',class_='medium',autocomplete="off")} |
|
69 | 69 | </div> |
|
70 | 70 | </div> |
|
71 | ||
|
71 | ||
|
72 | <div class="field"> | |
|
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 | ||
|
72 | 81 | <div class="field"> |
|
73 | 82 | <div class="label"> |
|
74 | 83 | <label for="name">${_('First Name')}:</label> |
@@ -132,7 +141,7 b'' | |||
|
132 | 141 | <div class="fields"> |
|
133 | 142 | <div class="field"> |
|
134 | 143 | <div class="label label-checkbox"> |
|
135 | <label for="">${_('Create repositories')}:</label> | |
|
144 | <label for="create_repo_perm">${_('Create repositories')}:</label> | |
|
136 | 145 | </div> |
|
137 | 146 | <div class="checkboxes"> |
|
138 | 147 | ${h.checkbox('create_repo_perm',value=True)} |
@@ -57,7 +57,16 b'' | |||
|
57 | 57 | ${h.password('new_password',class_="medium",autocomplete="off")} |
|
58 | 58 | </div> |
|
59 | 59 | </div> |
|
60 |
|
|
|
60 | ||
|
61 | <div class="field"> | |
|
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 | ||
|
61 | 70 | <div class="field"> |
|
62 | 71 | <div class="label"> |
|
63 | 72 | <label for="name">${_('First Name')}:</label> |
@@ -154,10 +163,12 b'' | |||
|
154 | 163 | </tr> |
|
155 | 164 | %endfor |
|
156 | 165 | %else: |
|
166 | <div style="padding:5px 0px 10px 0px;"> | |
|
157 | 167 | ${_('No repositories yet')} |
|
158 | 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 | 170 | %endif |
|
171 | </div> | |
|
161 | 172 | %endif |
|
162 | 173 | </tbody> |
|
163 | 174 | </table> |
@@ -253,7 +253,7 b'' | |||
|
253 | 253 | <div class="fields"> |
|
254 | 254 | <div class="field"> |
|
255 | 255 | <div class="label label-checkbox"> |
|
256 | <label for="">${_('Create repositories')}:</label> | |
|
256 | <label for="create_repo_perm">${_('Create repositories')}:</label> | |
|
257 | 257 | </div> |
|
258 | 258 | <div class="checkboxes"> |
|
259 | 259 | ${h.checkbox('create_repo_perm',value=True)} |
@@ -34,7 +34,14 b'' | |||
|
34 | 34 | ${h.text('repo_name',class_="small")} |
|
35 | 35 | </div> |
|
36 | 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 | 45 | <div class="field"> |
|
39 | 46 | <div class="label label-textarea"> |
|
40 | 47 | <label for="description">${_('Description')}:</label> |
@@ -77,8 +77,6 b' class TestController(TestCase):' | |||
|
77 | 77 | self.assertEqual(response.session['rhodecode_user'].username, username) |
|
78 | 78 | return response.follow() |
|
79 | 79 | |
|
80 | ||
|
81 | ||
|
82 | 80 | def checkSessionFlash(self, response, msg): |
|
83 | 81 | self.assertTrue('flash' in response.session) |
|
84 | 82 | self.assertTrue(msg in response.session['flash'][0][1]) |
@@ -137,6 +137,7 b' class TestAdminSettingsController(TestCo' | |||
|
137 | 137 | params=dict(_method='put', |
|
138 | 138 | username='test_admin', |
|
139 | 139 | new_password=new_password, |
|
140 | password_confirmation = new_password, | |
|
140 | 141 | password='', |
|
141 | 142 | name=new_name, |
|
142 | 143 | lastname=new_lastname, |
@@ -160,6 +161,7 b' class TestAdminSettingsController(TestCo' | |||
|
160 | 161 | _method='put', |
|
161 | 162 | username='test_admin', |
|
162 | 163 | new_password=old_password, |
|
164 | password_confirmation = old_password, | |
|
163 | 165 | password='', |
|
164 | 166 | name=old_name, |
|
165 | 167 | lastname=old_lastname, |
@@ -186,6 +188,7 b' class TestAdminSettingsController(TestCo' | |||
|
186 | 188 | _method='put', |
|
187 | 189 | username='test_admin', |
|
188 | 190 | new_password='test12', |
|
191 | password_confirmation = 'test122', | |
|
189 | 192 | name='NewName', |
|
190 | 193 | lastname='NewLastname', |
|
191 | 194 | email=new_email,)) |
@@ -201,6 +204,7 b' class TestAdminSettingsController(TestCo' | |||
|
201 | 204 | _method='put', |
|
202 | 205 | username='test_admin', |
|
203 | 206 | new_password='test12', |
|
207 | password_confirmation = 'test122', | |
|
204 | 208 | name='NewName', |
|
205 | 209 | lastname='NewLastname', |
|
206 | 210 | email=new_email,)) |
@@ -16,12 +16,14 b' class TestAdminUsersController(TestContr' | |||
|
16 | 16 | self.log_user() |
|
17 | 17 | username = 'newtestuser' |
|
18 | 18 | password = 'test12' |
|
19 | password_confirmation = password | |
|
19 | 20 | name = 'name' |
|
20 | 21 | lastname = 'lastname' |
|
21 | 22 | email = 'mail@mail.com' |
|
22 | 23 | |
|
23 | 24 | response = self.app.post(url('users'), {'username':username, |
|
24 | 25 | 'password':password, |
|
26 | 'password_confirmation':password_confirmation, | |
|
25 | 27 | 'name':name, |
|
26 | 28 | 'active':True, |
|
27 | 29 | 'lastname':lastname, |
@@ -90,6 +92,7 b' class TestAdminUsersController(TestContr' | |||
|
90 | 92 | |
|
91 | 93 | response = self.app.post(url('users'), {'username':username, |
|
92 | 94 | 'password':password, |
|
95 | 'password_confirmation':password, | |
|
93 | 96 | 'name':name, |
|
94 | 97 | 'active':True, |
|
95 | 98 | 'lastname':lastname, |
@@ -48,7 +48,8 b' from rhodecode.tests import TESTS_TMP_PA' | |||
|
48 | 48 | from rhodecode.config.environment import load_environment |
|
49 | 49 | |
|
50 | 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 | 53 | load_environment(conf.global_conf, conf.local_conf) |
|
53 | 54 | |
|
54 | 55 | add_cache(conf) |
@@ -56,10 +57,13 b' add_cache(conf)' | |||
|
56 | 57 | USER = 'test_admin' |
|
57 | 58 | PASS = 'test12' |
|
58 | 59 | HOST = '127.0.0.1:5000' |
|
59 | DEBUG = True if sys.argv[1:] else False | |
|
60 | DEBUG = False | |
|
60 | 61 | print 'DEBUG:', DEBUG |
|
61 | 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 | 68 | class Command(object): |
|
65 | 69 | |
@@ -96,22 +100,15 b' def test_wrapp(func):' | |||
|
96 | 100 | return res |
|
97 | 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 | 104 | def create_test_user(force=True): |
|
107 | 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 | 109 | if force and user is not None: |
|
113 | 110 | print '\tremoving current user' |
|
114 |
for repo in |
|
|
111 | for repo in Repository.query().filter(Repository.user == user).all(): | |
|
115 | 112 | sa.delete(repo) |
|
116 | 113 | sa.delete(user) |
|
117 | 114 | sa.commit() |
@@ -134,9 +131,8 b' def create_test_user(force=True):' | |||
|
134 | 131 | |
|
135 | 132 | def create_test_repo(force=True): |
|
136 | 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 | 136 | if user is None: |
|
141 | 137 | raise Exception('user not found') |
|
142 | 138 | |
@@ -156,22 +152,17 b' def create_test_repo(force=True):' | |||
|
156 | 152 | |
|
157 | 153 | |
|
158 | 154 | def set_anonymous_access(enable=True): |
|
159 | sa = get_session() | |
|
160 | user = sa.query(User).filter(User.username == 'default').one() | |
|
161 | sa.expire(user) | |
|
155 | user = User.get_by_username('default') | |
|
162 | 156 | user.active = enable |
|
163 | 157 | sa.add(user) |
|
164 | 158 | sa.commit() |
|
165 | sa.remove() | |
|
166 | import time;time.sleep(3) | |
|
167 | 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 | 163 | def get_anonymous_access(): |
|
171 | sa = get_session() | |
|
172 | obj1 = sa.query(User).filter(User.username == 'default').one() | |
|
173 | sa.expire(obj1) | |
|
174 | return obj1.active | |
|
164 | user = User.get_by_username('default') | |
|
165 | return user.active | |
|
175 | 166 | |
|
176 | 167 | |
|
177 | 168 | #============================================================================== |
@@ -378,16 +369,15 b' def test_push_wrong_path():' | |||
|
378 | 369 | |
|
379 | 370 | @test_wrapp |
|
380 | 371 | def get_logs(): |
|
381 | sa = get_session() | |
|
382 | return len(sa.query(UserLog).all()) | |
|
372 | return UserLog.query().all() | |
|
383 | 373 | |
|
384 | 374 | @test_wrapp |
|
385 | 375 | def test_logs(initial): |
|
386 | sa = get_session() | |
|
387 | logs = sa.query(UserLog).all() | |
|
388 | operations = 7 | |
|
389 | if initial + operations != len(logs): | |
|
390 | raise Exception("missing number of logs %s vs %s" % (initial, len(logs))) | |
|
376 | logs = UserLog.query().all() | |
|
377 | operations = 4 | |
|
378 | if len(initial) + operations != len(logs): | |
|
379 | raise Exception("missing number of logs initial:%s vs current:%s" % \ | |
|
380 | (len(initial), len(logs))) | |
|
391 | 381 | |
|
392 | 382 | |
|
393 | 383 | if __name__ == '__main__': |
@@ -395,18 +385,17 b" if __name__ == '__main__':" | |||
|
395 | 385 | create_test_repo() |
|
396 | 386 | |
|
397 | 387 | initial_logs = get_logs() |
|
388 | print 'initial activity logs: %s' % len(initial_logs) | |
|
398 | 389 | |
|
399 |
|
|
|
390 | #test_push_modify_file() | |
|
400 | 391 | test_clone_with_credentials() |
|
401 | 392 | test_clone_wrong_credentials() |
|
402 | 393 | |
|
403 | ||
|
404 | 394 | test_push_new_file(commits=2, with_clone=True) |
|
405 | 395 | |
|
406 | 396 | test_clone_anonymous() |
|
407 | 397 | test_push_wrong_path() |
|
408 | 398 | |
|
409 | ||
|
410 | 399 | test_push_wrong_credentials() |
|
411 | 400 | |
|
412 | 401 | test_logs(initial_logs) |
General Comments 0
You need to be logged in to leave comments.
Login now