##// END OF EJS Templates
merged upto rev 019026a8cf67
marcink -
r1639:95c3e33e merge default
parent child Browse files
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: "create_user"
79 args: {"username": "<username>",
80 "password": "<password>",
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 creates new users group. This command can be executed only using api_key
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 "active":"<bool>"}
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 = self.sa.query(UserFollowing)\
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 create_users_group(self, apiuser, name, active):
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 {'id':ug.users_group_id,
94 'msg':'created new users group %s' % name}
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 User
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 changed_name, '', self.sa)
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 self.LDAP_SERVER_ADDRESS,
67 self.LDAP_SERVER_PORT)
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.__dict__['SCOPE_' + search_scope]
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 ldap.set_option(ldap.OPT_X_TLS_CACERTDIR, '/etc/openldap/cacerts')
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 mail_port=None, ssl=False, tls=False, debug=False):
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, backref, joinedload, class_mapper, \
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 Session.query(cls).get(id_)
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 = Session.query(cls).get(id_)
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 Session.query(cls)\
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 = Session.query(cls)
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 = Session.query(cls)\
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 Session.query(cls).filter(cls.ui_key == key)
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 Session.query(cls).filter(cls.api_key == api_key).one()
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 = Session.query(cls)\
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 = Session.query(UsersGroup)\
383 .filter(UsersGroup.users_group_name == group_name)
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 = Session.query(cls)
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 members_list.append(UsersGroupMember(
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 Session.query(cls).filter(Repository.fork_id == repo_id)
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 = Session.query(RhodeCodeUi)\
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 Session.query(CacheInvalidation)\
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 = Session.query(CacheInvalidation)\
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 Session.query(Group).filter(Group.parent_group == self)
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 Session.query(Repository).filter(Repository.group == self)
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 self.parent_group else []
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 Session.query(cls).filter(cls.permission_name == key).scalar()
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 Session.query(cls).filter(cls.user_id == user_id)\
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 Session.query(cls).filter(cls.user_id == user_id)\
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 Session.query(cls).filter(cls.users_group_id ==
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 Session.query(cls).filter(cls.users_group_id == users_group_id)\
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 Session.query(cls).filter(cls.follows_repo_id == repo_id)
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 if value['password'] != value['password_confirmation']:
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 'invalid_password':_('invalid password'),
197 'invalid_login':_('invalid user name'),
198 'disabled_account':_('Your account is disabled')
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, ValidSettings]
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_id = v
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="users_group_name">${_('Group name')}:</label>
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="repo_group">${_('Group parent')}:</label>
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="users_group_name">${_('Group name')}:</label>
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="repo_group">${_('Group parent')}:</label>
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="checkbox-1">
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 for="destroy">${_('index build option')}:</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="checkbox-1">${_('build from scratch')}</label>
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 for="web_push_ssl">${_('Web')}:</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 for="web_push_ssl">${_('Hooks')}:</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 sa.query(Repository).filter(Repository.user == user).all():
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 # test_push_modify_file()
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