##// END OF EJS Templates
white space cleanup
marcink -
r2478:8eab8111 beta
parent child Browse files
Show More
@@ -1,219 +1,219 b''
1 1 """The base Controller API
2 2
3 3 Provides the BaseController class for subclassing.
4 4 """
5 5 import logging
6 6 import time
7 7 import traceback
8 8
9 9 from paste.auth.basic import AuthBasicAuthenticator
10 10 from paste.httpexceptions import HTTPUnauthorized, HTTPForbidden
11 11 from paste.httpheaders import WWW_AUTHENTICATE
12 12
13 13 from pylons import config, tmpl_context as c, request, session, url
14 14 from pylons.controllers import WSGIController
15 15 from pylons.controllers.util import redirect
16 16 from pylons.templating import render_mako as render
17 17
18 18 from rhodecode import __version__, BACKENDS
19 19
20 20 from rhodecode.lib.utils2 import str2bool, safe_unicode
21 21 from rhodecode.lib.auth import AuthUser, get_container_username, authfunc,\
22 22 HasPermissionAnyMiddleware, CookieStoreWrapper
23 23 from rhodecode.lib.utils import get_repo_slug, invalidate_cache
24 24 from rhodecode.model import meta
25 25
26 26 from rhodecode.model.db import Repository
27 27 from rhodecode.model.notification import NotificationModel
28 28 from rhodecode.model.scm import ScmModel
29 29
30 30 log = logging.getLogger(__name__)
31 31
32 32
33 33 def _get_ip_addr(environ):
34 34 proxy_key = 'HTTP_X_REAL_IP'
35 35 proxy_key2 = 'HTTP_X_FORWARDED_FOR'
36 36 def_key = 'REMOTE_ADDR'
37 37
38 38 return environ.get(proxy_key2,
39 39 environ.get(proxy_key, environ.get(def_key, '0.0.0.0'))
40 40 )
41 41
42 42
43 43 class BasicAuth(AuthBasicAuthenticator):
44 44
45 45 def __init__(self, realm, authfunc, auth_http_code=None):
46 46 self.realm = realm
47 47 self.authfunc = authfunc
48 48 self._rc_auth_http_code = auth_http_code
49 49
50 50 def build_authentication(self):
51 51 head = WWW_AUTHENTICATE.tuples('Basic realm="%s"' % self.realm)
52 52 if self._rc_auth_http_code and self._rc_auth_http_code == '403':
53 53 # return 403 if alternative http return code is specified in
54 54 # RhodeCode config
55 55 return HTTPForbidden(headers=head)
56 56 return HTTPUnauthorized(headers=head)
57 57
58 58
59 59 class BaseVCSController(object):
60 60
61 61 def __init__(self, application, config):
62 62 self.application = application
63 63 self.config = config
64 64 # base path of repo locations
65 65 self.basepath = self.config['base_path']
66 66 #authenticate this mercurial request using authfunc
67 67 self.authenticate = BasicAuth('', authfunc,
68 68 config.get('auth_ret_code'))
69 69 self.ipaddr = '0.0.0.0'
70 70
71 71 def _handle_request(self, environ, start_response):
72 72 raise NotImplementedError()
73 73
74 74 def _get_by_id(self, repo_name):
75 75 """
76 76 Get's a special pattern _<ID> from clone url and tries to replace it
77 77 with a repository_name for support of _<ID> non changable urls
78 78
79 79 :param repo_name:
80 80 """
81 81 try:
82 82 data = repo_name.split('/')
83 83 if len(data) >= 2:
84 84 by_id = data[1].split('_')
85 85 if len(by_id) == 2 and by_id[1].isdigit():
86 86 _repo_name = Repository.get(by_id[1]).repo_name
87 87 data[1] = _repo_name
88 88 except:
89 89 log.debug('Failed to extract repo_name from id %s' % (
90 90 traceback.format_exc()
91 91 )
92 92 )
93 93
94 94 return '/'.join(data)
95 95
96 96 def _invalidate_cache(self, repo_name):
97 97 """
98 98 Set's cache for this repository for invalidation on next access
99 99
100 100 :param repo_name: full repo name, also a cache key
101 101 """
102 102 invalidate_cache('get_repo_cached_%s' % repo_name)
103 103
104 104 def _check_permission(self, action, user, repo_name):
105 105 """
106 106 Checks permissions using action (push/pull) user and repository
107 107 name
108 108
109 109 :param action: push or pull action
110 110 :param user: user instance
111 111 :param repo_name: repository name
112 112 """
113 113 if action == 'push':
114 114 if not HasPermissionAnyMiddleware('repository.write',
115 115 'repository.admin')(user,
116 116 repo_name):
117 117 return False
118 118
119 119 else:
120 120 #any other action need at least read permission
121 121 if not HasPermissionAnyMiddleware('repository.read',
122 122 'repository.write',
123 123 'repository.admin')(user,
124 124 repo_name):
125 125 return False
126 126
127 127 return True
128 128
129 129 def _get_ip_addr(self, environ):
130 130 return _get_ip_addr(environ)
131 131
132 132 def __call__(self, environ, start_response):
133 133 start = time.time()
134 134 try:
135 135 return self._handle_request(environ, start_response)
136 136 finally:
137 137 log = logging.getLogger('rhodecode.' + self.__class__.__name__)
138 138 log.debug('Request time: %.3fs' % (time.time() - start))
139 139 meta.Session.remove()
140 140
141 141
142 142 class BaseController(WSGIController):
143 143
144 144 def __before__(self):
145 145 c.rhodecode_version = __version__
146 146 c.rhodecode_instanceid = config.get('instance_id')
147 147 c.rhodecode_name = config.get('rhodecode_title')
148 148 c.use_gravatar = str2bool(config.get('use_gravatar'))
149 149 c.ga_code = config.get('rhodecode_ga_code')
150 150 c.repo_name = get_repo_slug(request)
151 151 c.backends = BACKENDS.keys()
152 152 c.unread_notifications = NotificationModel()\
153 153 .get_unread_cnt_for_user(c.rhodecode_user.user_id)
154 154 self.cut_off_limit = int(config.get('cut_off_limit'))
155 155
156 156 self.sa = meta.Session
157 157 self.scm_model = ScmModel(self.sa)
158 158 self.ip_addr = ''
159 159
160 160 def __call__(self, environ, start_response):
161 161 """Invoke the Controller"""
162 162 # WSGIController.__call__ dispatches to the Controller method
163 163 # the request is routed to. This routing information is
164 164 # available in environ['pylons.routes_dict']
165 165 start = time.time()
166 166 try:
167 167 self.ip_addr = _get_ip_addr(environ)
168 168 # make sure that we update permissions each time we call controller
169 169 api_key = request.GET.get('api_key')
170 170 cookie_store = CookieStoreWrapper(session.get('rhodecode_user'))
171 171 user_id = cookie_store.get('user_id', None)
172 172 username = get_container_username(environ, config)
173 173 auth_user = AuthUser(user_id, api_key, username)
174 174 request.user = auth_user
175 175 self.rhodecode_user = c.rhodecode_user = auth_user
176 176 if not self.rhodecode_user.is_authenticated and \
177 177 self.rhodecode_user.user_id is not None:
178 178 self.rhodecode_user.set_authenticated(
179 179 cookie_store.get('is_authenticated')
180 180 )
181 181 log.info('User: %s accessed %s' % (
182 182 auth_user, safe_unicode(environ.get('PATH_INFO')))
183 183 )
184 184 return WSGIController.__call__(self, environ, start_response)
185 185 finally:
186 186 log.info('Request to %s time: %.3fs' % (
187 187 safe_unicode(environ.get('PATH_INFO')), time.time() - start)
188 188 )
189 189 meta.Session.remove()
190 190
191 191
192 192 class BaseRepoController(BaseController):
193 193 """
194 194 Base class for controllers responsible for loading all needed data for
195 195 repository loaded items are
196 196
197 197 c.rhodecode_repo: instance of scm repository
198 198 c.rhodecode_db_repo: instance of db
199 199 c.repository_followers: number of followers
200 200 c.repository_forks: number of forks
201 201 """
202 202
203 203 def __before__(self):
204 204 super(BaseRepoController, self).__before__()
205 205 if c.repo_name:
206 206
207 207 dbr = c.rhodecode_db_repo = Repository.get_by_repo_name(c.repo_name)
208 208 c.rhodecode_repo = c.rhodecode_db_repo.scm_instance
209 209
210 210 if c.rhodecode_repo is None:
211 211 log.error('%s this repository is present in database but it '
212 212 'cannot be created as an scm instance', c.repo_name)
213 213
214 214 redirect(url('home'))
215 215
216 216 # some globals counter for menu
217 217 c.repository_followers = self.scm_model.get_followers(dbr)
218 218 c.repository_forks = self.scm_model.get_forks(dbr)
219 c.repository_pull_requests = self.scm_model.get_pull_requests(dbr) No newline at end of file
219 c.repository_pull_requests = self.scm_model.get_pull_requests(dbr)
@@ -1,28 +1,28 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.db_1_4_0
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Database Models for RhodeCode <=1.4.X
7 7
8 8 :created_on: Apr 08, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 #TODO: replace that will db.py content after 1.5 Release
27 27
28 from rhodecode.model.db import * No newline at end of file
28 from rhodecode.model.db import *
@@ -1,15 +1,15 b''
1 1 """
2 2 Mercurial libs compatibility
3 3 """
4 4
5 5 from mercurial import archival, merge as hg_merge, patch, ui
6 6 from mercurial.commands import clone, nullid, pull
7 7 from mercurial.context import memctx, memfilectx
8 8 from mercurial.error import RepoError, RepoLookupError, Abort
9 9 from mercurial.hgweb.common import get_contact
10 10 from mercurial.localrepo import localrepository
11 11 from mercurial.match import match
12 12 from mercurial.mdiff import diffopts
13 13 from mercurial.node import hex
14 14 from mercurial.encoding import tolocal
15 from mercurial import discovery No newline at end of file
15 from mercurial import discovery
@@ -1,613 +1,613 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.user
4 4 ~~~~~~~~~~~~~~~~~~~~
5 5
6 6 users model for RhodeCode
7 7
8 8 :created_on: Apr 9, 2010
9 9 :author: marcink
10 10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import logging
27 27 import traceback
28 28
29 29 from pylons import url
30 30 from pylons.i18n.translation import _
31 31
32 32 from rhodecode.lib.utils2 import safe_unicode, generate_api_key
33 33 from rhodecode.lib.caching_query import FromCache
34 34
35 35 from rhodecode.model import BaseModel
36 36 from rhodecode.model.db import User, UserRepoToPerm, Repository, Permission, \
37 37 UserToPerm, UsersGroupRepoToPerm, UsersGroupToPerm, UsersGroupMember, \
38 38 Notification, RepoGroup, UserRepoGroupToPerm, UsersGroupRepoGroupToPerm, \
39 39 UserEmailMap
40 40 from rhodecode.lib.exceptions import DefaultUserException, \
41 41 UserOwnsReposException
42 42
43 43 from sqlalchemy.exc import DatabaseError
44 44
45 45 from sqlalchemy.orm import joinedload
46 46
47 47 log = logging.getLogger(__name__)
48 48
49 49
50 50 PERM_WEIGHTS = {
51 51 'repository.none': 0,
52 52 'repository.read': 1,
53 53 'repository.write': 3,
54 54 'repository.admin': 4,
55 55 'group.none': 0,
56 56 'group.read': 1,
57 57 'group.write': 3,
58 58 'group.admin': 4,
59 59 }
60 60
61 61
62 62 class UserModel(BaseModel):
63 63
64 64 def get(self, user_id, cache=False):
65 65 user = self.sa.query(User)
66 66 if cache:
67 67 user = user.options(FromCache("sql_cache_short",
68 68 "get_user_%s" % user_id))
69 69 return user.get(user_id)
70 70
71 71 def get_user(self, user):
72 72 return self._get_user(user)
73 73
74 74 def get_by_username(self, username, cache=False, case_insensitive=False):
75 75
76 76 if case_insensitive:
77 77 user = self.sa.query(User).filter(User.username.ilike(username))
78 78 else:
79 79 user = self.sa.query(User)\
80 80 .filter(User.username == username)
81 81 if cache:
82 82 user = user.options(FromCache("sql_cache_short",
83 83 "get_user_%s" % username))
84 84 return user.scalar()
85 85
86 86 def get_by_api_key(self, api_key, cache=False):
87 87 return User.get_by_api_key(api_key, cache)
88 88
89 89 def create(self, form_data):
90 90 from rhodecode.lib.auth import get_crypt_password
91 91 try:
92 92 new_user = User()
93 93 for k, v in form_data.items():
94 94 if k == 'password':
95 95 v = get_crypt_password(v)
96 96 setattr(new_user, k, v)
97 97
98 98 new_user.api_key = generate_api_key(form_data['username'])
99 99 self.sa.add(new_user)
100 100 return new_user
101 101 except:
102 102 log.error(traceback.format_exc())
103 103 raise
104 104
105 105 def create_or_update(self, username, password, email, name, lastname,
106 106 active=True, admin=False, ldap_dn=None):
107 107 """
108 108 Creates a new instance if not found, or updates current one
109 109
110 110 :param username:
111 111 :param password:
112 112 :param email:
113 113 :param active:
114 114 :param name:
115 115 :param lastname:
116 116 :param active:
117 117 :param admin:
118 118 :param ldap_dn:
119 119 """
120 120
121 121 from rhodecode.lib.auth import get_crypt_password
122 122
123 123 log.debug('Checking for %s account in RhodeCode database' % username)
124 124 user = User.get_by_username(username, case_insensitive=True)
125 125 if user is None:
126 126 log.debug('creating new user %s' % username)
127 127 new_user = User()
128 128 else:
129 129 log.debug('updating user %s' % username)
130 130 new_user = user
131 131
132 132 try:
133 133 new_user.username = username
134 134 new_user.admin = admin
135 135 new_user.password = get_crypt_password(password)
136 136 new_user.api_key = generate_api_key(username)
137 137 new_user.email = email
138 138 new_user.active = active
139 139 new_user.ldap_dn = safe_unicode(ldap_dn) if ldap_dn else None
140 140 new_user.name = name
141 141 new_user.lastname = lastname
142 142 self.sa.add(new_user)
143 143 return new_user
144 144 except (DatabaseError,):
145 145 log.error(traceback.format_exc())
146 146 raise
147 147
148 148 def create_for_container_auth(self, username, attrs):
149 149 """
150 150 Creates the given user if it's not already in the database
151 151
152 152 :param username:
153 153 :param attrs:
154 154 """
155 155 if self.get_by_username(username, case_insensitive=True) is None:
156 156
157 157 # autogenerate email for container account without one
158 158 generate_email = lambda usr: '%s@container_auth.account' % usr
159 159
160 160 try:
161 161 new_user = User()
162 162 new_user.username = username
163 163 new_user.password = None
164 164 new_user.api_key = generate_api_key(username)
165 165 new_user.email = attrs['email']
166 166 new_user.active = attrs.get('active', True)
167 167 new_user.name = attrs['name'] or generate_email(username)
168 168 new_user.lastname = attrs['lastname']
169 169
170 170 self.sa.add(new_user)
171 171 return new_user
172 172 except (DatabaseError,):
173 173 log.error(traceback.format_exc())
174 174 self.sa.rollback()
175 175 raise
176 176 log.debug('User %s already exists. Skipping creation of account'
177 177 ' for container auth.', username)
178 178 return None
179 179
180 180 def create_ldap(self, username, password, user_dn, attrs):
181 181 """
182 182 Checks if user is in database, if not creates this user marked
183 183 as ldap user
184 184
185 185 :param username:
186 186 :param password:
187 187 :param user_dn:
188 188 :param attrs:
189 189 """
190 190 from rhodecode.lib.auth import get_crypt_password
191 191 log.debug('Checking for such ldap account in RhodeCode database')
192 192 if self.get_by_username(username, case_insensitive=True) is None:
193 193
194 194 # autogenerate email for ldap account without one
195 195 generate_email = lambda usr: '%s@ldap.account' % usr
196 196
197 197 try:
198 198 new_user = User()
199 199 username = username.lower()
200 200 # add ldap account always lowercase
201 201 new_user.username = username
202 202 new_user.password = get_crypt_password(password)
203 203 new_user.api_key = generate_api_key(username)
204 204 new_user.email = attrs['email'] or generate_email(username)
205 205 new_user.active = attrs.get('active', True)
206 206 new_user.ldap_dn = safe_unicode(user_dn)
207 207 new_user.name = attrs['name']
208 208 new_user.lastname = attrs['lastname']
209 209
210 210 self.sa.add(new_user)
211 211 return new_user
212 212 except (DatabaseError,):
213 213 log.error(traceback.format_exc())
214 214 self.sa.rollback()
215 215 raise
216 216 log.debug('this %s user exists skipping creation of ldap account',
217 217 username)
218 218 return None
219 219
220 220 def create_registration(self, form_data):
221 221 from rhodecode.model.notification import NotificationModel
222 222
223 223 try:
224 224 form_data['admin'] = False
225 225 new_user = self.create(form_data)
226 226
227 227 self.sa.add(new_user)
228 228 self.sa.flush()
229 229
230 230 # notification to admins
231 231 subject = _('new user registration')
232 232 body = ('New user registration\n'
233 233 '---------------------\n'
234 234 '- Username: %s\n'
235 235 '- Full Name: %s\n'
236 236 '- Email: %s\n')
237 237 body = body % (new_user.username, new_user.full_name,
238 238 new_user.email)
239 239 edit_url = url('edit_user', id=new_user.user_id, qualified=True)
240 240 kw = {'registered_user_url': edit_url}
241 241 NotificationModel().create(created_by=new_user, subject=subject,
242 242 body=body, recipients=None,
243 243 type_=Notification.TYPE_REGISTRATION,
244 244 email_kwargs=kw)
245 245
246 246 except:
247 247 log.error(traceback.format_exc())
248 248 raise
249 249
250 250 def update(self, user_id, form_data):
251 251 try:
252 252 user = self.get(user_id, cache=False)
253 253 if user.username == 'default':
254 254 raise DefaultUserException(
255 255 _("You can't Edit this user since it's"
256 256 " crucial for entire application"))
257 257
258 258 for k, v in form_data.items():
259 259 if k == 'new_password' and v != '':
260 260 user.password = v
261 261 user.api_key = generate_api_key(user.username)
262 262 else:
263 263 setattr(user, k, v)
264 264
265 265 self.sa.add(user)
266 266 except:
267 267 log.error(traceback.format_exc())
268 268 raise
269 269
270 270 def update_my_account(self, user_id, form_data):
271 271 from rhodecode.lib.auth import get_crypt_password
272 272 try:
273 273 user = self.get(user_id, cache=False)
274 274 if user.username == 'default':
275 275 raise DefaultUserException(
276 276 _("You can't Edit this user since it's"
277 277 " crucial for entire application")
278 278 )
279 279 for k, v in form_data.items():
280 280 if k == 'new_password' and v != '':
281 281 user.password = get_crypt_password(v)
282 282 user.api_key = generate_api_key(user.username)
283 283 else:
284 284 if k not in ['admin', 'active']:
285 285 setattr(user, k, v)
286 286
287 287 self.sa.add(user)
288 288 except:
289 289 log.error(traceback.format_exc())
290 290 raise
291 291
292 292 def delete(self, user):
293 293 user = self._get_user(user)
294 294
295 295 try:
296 296 if user.username == 'default':
297 297 raise DefaultUserException(
298 298 _(u"You can't remove this user since it's"
299 299 " crucial for entire application")
300 300 )
301 301 if user.repositories:
302 302 repos = [x.repo_name for x in user.repositories]
303 303 raise UserOwnsReposException(
304 304 _(u'user "%s" still owns %s repositories and cannot be '
305 305 'removed. Switch owners or remove those repositories. %s')
306 306 % (user.username, len(repos), ', '.join(repos))
307 307 )
308 308 self.sa.delete(user)
309 309 except:
310 310 log.error(traceback.format_exc())
311 311 raise
312 312
313 313 def reset_password_link(self, data):
314 314 from rhodecode.lib.celerylib import tasks, run_task
315 315 run_task(tasks.send_password_link, data['email'])
316 316
317 317 def reset_password(self, data):
318 318 from rhodecode.lib.celerylib import tasks, run_task
319 319 run_task(tasks.reset_user_password, data['email'])
320 320
321 321 def fill_data(self, auth_user, user_id=None, api_key=None):
322 322 """
323 323 Fetches auth_user by user_id,or api_key if present.
324 324 Fills auth_user attributes with those taken from database.
325 325 Additionally set's is_authenitated if lookup fails
326 326 present in database
327 327
328 328 :param auth_user: instance of user to set attributes
329 329 :param user_id: user id to fetch by
330 330 :param api_key: api key to fetch by
331 331 """
332 332 if user_id is None and api_key is None:
333 333 raise Exception('You need to pass user_id or api_key')
334 334
335 335 try:
336 336 if api_key:
337 337 dbuser = self.get_by_api_key(api_key)
338 338 else:
339 339 dbuser = self.get(user_id)
340 340
341 341 if dbuser is not None and dbuser.active:
342 342 log.debug('filling %s data' % dbuser)
343 343 for k, v in dbuser.get_dict().items():
344 344 setattr(auth_user, k, v)
345 345 else:
346 346 return False
347 347
348 348 except:
349 349 log.error(traceback.format_exc())
350 350 auth_user.is_authenticated = False
351 351 return False
352 352
353 353 return True
354 354
355 355 def fill_perms(self, user):
356 356 """
357 357 Fills user permission attribute with permissions taken from database
358 358 works for permissions given for repositories, and for permissions that
359 359 are granted to groups
360 360
361 361 :param user: user instance to fill his perms
362 362 """
363 363 RK = 'repositories'
364 364 GK = 'repositories_groups'
365 365 GLOBAL = 'global'
366 366 user.permissions[RK] = {}
367 367 user.permissions[GK] = {}
368 368 user.permissions[GLOBAL] = set()
369 369
370 370 #======================================================================
371 371 # fetch default permissions
372 372 #======================================================================
373 373 default_user = User.get_by_username('default', cache=True)
374 374 default_user_id = default_user.user_id
375 375
376 376 default_repo_perms = Permission.get_default_perms(default_user_id)
377 377 default_repo_groups_perms = Permission.get_default_group_perms(default_user_id)
378 378
379 379 if user.is_admin:
380 380 #==================================================================
381 381 # admin user have all default rights for repositories
382 382 # and groups set to admin
383 383 #==================================================================
384 384 user.permissions[GLOBAL].add('hg.admin')
385 385
386 386 # repositories
387 387 for perm in default_repo_perms:
388 388 r_k = perm.UserRepoToPerm.repository.repo_name
389 389 p = 'repository.admin'
390 390 user.permissions[RK][r_k] = p
391 391
392 392 # repositories groups
393 393 for perm in default_repo_groups_perms:
394 394 rg_k = perm.UserRepoGroupToPerm.group.group_name
395 395 p = 'group.admin'
396 396 user.permissions[GK][rg_k] = p
397 397 return user
398 398
399 399 #==================================================================
400 400 # set default permissions first for repositories and groups
401 401 #==================================================================
402 402 uid = user.user_id
403 403
404 404 # default global permissions
405 405 default_global_perms = self.sa.query(UserToPerm)\
406 406 .filter(UserToPerm.user_id == default_user_id)
407 407
408 408 for perm in default_global_perms:
409 409 user.permissions[GLOBAL].add(perm.permission.permission_name)
410 410
411 411 # defaults for repositories, taken from default user
412 412 for perm in default_repo_perms:
413 413 r_k = perm.UserRepoToPerm.repository.repo_name
414 414 if perm.Repository.private and not (perm.Repository.user_id == uid):
415 415 # disable defaults for private repos,
416 416 p = 'repository.none'
417 417 elif perm.Repository.user_id == uid:
418 418 # set admin if owner
419 419 p = 'repository.admin'
420 420 else:
421 421 p = perm.Permission.permission_name
422 422
423 423 user.permissions[RK][r_k] = p
424 424
425 425 # defaults for repositories groups taken from default user permission
426 426 # on given group
427 427 for perm in default_repo_groups_perms:
428 428 rg_k = perm.UserRepoGroupToPerm.group.group_name
429 429 p = perm.Permission.permission_name
430 430 user.permissions[GK][rg_k] = p
431 431
432 432 #==================================================================
433 433 # overwrite defaults with user permissions if any found
434 434 #==================================================================
435 435
436 436 # user global permissions
437 437 user_perms = self.sa.query(UserToPerm)\
438 438 .options(joinedload(UserToPerm.permission))\
439 439 .filter(UserToPerm.user_id == uid).all()
440 440
441 441 for perm in user_perms:
442 442 user.permissions[GLOBAL].add(perm.permission.permission_name)
443 443
444 444 # user explicit permissions for repositories
445 445 user_repo_perms = \
446 446 self.sa.query(UserRepoToPerm, Permission, Repository)\
447 447 .join((Repository, UserRepoToPerm.repository_id == Repository.repo_id))\
448 448 .join((Permission, UserRepoToPerm.permission_id == Permission.permission_id))\
449 449 .filter(UserRepoToPerm.user_id == uid)\
450 450 .all()
451 451
452 452 for perm in user_repo_perms:
453 453 # set admin if owner
454 454 r_k = perm.UserRepoToPerm.repository.repo_name
455 455 if perm.Repository.user_id == uid:
456 456 p = 'repository.admin'
457 457 else:
458 458 p = perm.Permission.permission_name
459 459 user.permissions[RK][r_k] = p
460 460
461 461 # USER GROUP
462 462 #==================================================================
463 463 # check if user is part of user groups for this repository and
464 464 # fill in (or replace with higher) permissions
465 465 #==================================================================
466 466
467 467 # users group global
468 468 user_perms_from_users_groups = self.sa.query(UsersGroupToPerm)\
469 469 .options(joinedload(UsersGroupToPerm.permission))\
470 470 .join((UsersGroupMember, UsersGroupToPerm.users_group_id ==
471 471 UsersGroupMember.users_group_id))\
472 472 .filter(UsersGroupMember.user_id == uid).all()
473 473
474 474 for perm in user_perms_from_users_groups:
475 475 user.permissions[GLOBAL].add(perm.permission.permission_name)
476 476
477 477 # users group for repositories permissions
478 478 user_repo_perms_from_users_groups = \
479 479 self.sa.query(UsersGroupRepoToPerm, Permission, Repository,)\
480 480 .join((Repository, UsersGroupRepoToPerm.repository_id == Repository.repo_id))\
481 481 .join((Permission, UsersGroupRepoToPerm.permission_id == Permission.permission_id))\
482 482 .join((UsersGroupMember, UsersGroupRepoToPerm.users_group_id == UsersGroupMember.users_group_id))\
483 483 .filter(UsersGroupMember.user_id == uid)\
484 484 .all()
485 485
486 486 for perm in user_repo_perms_from_users_groups:
487 487 r_k = perm.UsersGroupRepoToPerm.repository.repo_name
488 488 p = perm.Permission.permission_name
489 489 cur_perm = user.permissions[RK][r_k]
490 490 # overwrite permission only if it's greater than permission
491 491 # given from other sources
492 492 if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
493 493 user.permissions[RK][r_k] = p
494 494
495 495 # REPO GROUP
496 496 #==================================================================
497 497 # get access for this user for repos group and override defaults
498 498 #==================================================================
499 499
500 500 # user explicit permissions for repository
501 501 user_repo_groups_perms = \
502 502 self.sa.query(UserRepoGroupToPerm, Permission, RepoGroup)\
503 503 .join((RepoGroup, UserRepoGroupToPerm.group_id == RepoGroup.group_id))\
504 504 .join((Permission, UserRepoGroupToPerm.permission_id == Permission.permission_id))\
505 505 .filter(UserRepoGroupToPerm.user_id == uid)\
506 506 .all()
507 507
508 508 for perm in user_repo_groups_perms:
509 509 rg_k = perm.UserRepoGroupToPerm.group.group_name
510 510 p = perm.Permission.permission_name
511 511 cur_perm = user.permissions[GK][rg_k]
512 512 if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
513 513 user.permissions[GK][rg_k] = p
514 514
515 515 # REPO GROUP + USER GROUP
516 516 #==================================================================
517 517 # check if user is part of user groups for this repo group and
518 518 # fill in (or replace with higher) permissions
519 519 #==================================================================
520 520
521 521 # users group for repositories permissions
522 522 user_repo_group_perms_from_users_groups = \
523 523 self.sa.query(UsersGroupRepoGroupToPerm, Permission, RepoGroup)\
524 524 .join((RepoGroup, UsersGroupRepoGroupToPerm.group_id == RepoGroup.group_id))\
525 525 .join((Permission, UsersGroupRepoGroupToPerm.permission_id == Permission.permission_id))\
526 526 .join((UsersGroupMember, UsersGroupRepoGroupToPerm.users_group_id == UsersGroupMember.users_group_id))\
527 527 .filter(UsersGroupMember.user_id == uid)\
528 528 .all()
529 529
530 530 for perm in user_repo_group_perms_from_users_groups:
531 531 g_k = perm.UsersGroupRepoGroupToPerm.group.group_name
532 532 p = perm.Permission.permission_name
533 533 cur_perm = user.permissions[GK][g_k]
534 534 # overwrite permission only if it's greater than permission
535 535 # given from other sources
536 536 if PERM_WEIGHTS[p] > PERM_WEIGHTS[cur_perm]:
537 537 user.permissions[GK][g_k] = p
538 538
539 539 return user
540 540
541 541 def has_perm(self, user, perm):
542 542 if not isinstance(perm, Permission):
543 543 raise Exception('perm needs to be an instance of Permission class '
544 544 'got %s instead' % type(perm))
545 545
546 546 user = self._get_user(user)
547 547
548 548 return UserToPerm.query().filter(UserToPerm.user == user)\
549 549 .filter(UserToPerm.permission == perm).scalar() is not None
550 550
551 551 def grant_perm(self, user, perm):
552 552 """
553 553 Grant user global permissions
554 554
555 555 :param user:
556 556 :param perm:
557 557 """
558 558 user = self._get_user(user)
559 559 perm = self._get_perm(perm)
560 560 # if this permission is already granted skip it
561 561 _perm = UserToPerm.query()\
562 562 .filter(UserToPerm.user == user)\
563 563 .filter(UserToPerm.permission == perm)\
564 564 .scalar()
565 565 if _perm:
566 566 return
567 567 new = UserToPerm()
568 568 new.user = user
569 569 new.permission = perm
570 570 self.sa.add(new)
571 571
572 572 def revoke_perm(self, user, perm):
573 573 """
574 574 Revoke users global permissions
575 575
576 576 :param user:
577 577 :param perm:
578 578 """
579 579 user = self._get_user(user)
580 580 perm = self._get_perm(perm)
581 581
582 582 obj = UserToPerm.query()\
583 583 .filter(UserToPerm.user == user)\
584 584 .filter(UserToPerm.permission == perm)\
585 585 .scalar()
586 586 if obj:
587 587 self.sa.delete(obj)
588 588
589 589 def add_extra_email(self, user, email):
590 590 """
591 591 Adds email address to UserEmailMap
592 592
593 593 :param user:
594 594 :param email:
595 595 """
596 596 user = self._get_user(user)
597 597 obj = UserEmailMap()
598 598 obj.user = user
599 599 obj.email = email
600 600 self.sa.add(obj)
601 601 return obj
602 602
603 603 def delete_extra_email(self, user, email_id):
604 604 """
605 605 Removes email address from UserEmailMap
606 606
607 607 :param user:
608 608 :param email_id:
609 609 """
610 610 user = self._get_user(user)
611 611 obj = UserEmailMap.query().get(email_id)
612 612 if obj:
613 self.sa.delete(obj) No newline at end of file
613 self.sa.delete(obj)
@@ -1,61 +1,61 b''
1 1 ## -*- coding: utf-8 -*-
2 2 ##usage:
3 3 ## <%namespace name="diff_block" file="/changeset/diff_block.html"/>
4 4 ## ${diff_block.diff_block(change)}
5 5 ##
6 6 <%def name="diff_block(change)">
7 7
8 8 %for op,filenode,diff,cs1,cs2,stat in change:
9 9 %if op !='removed':
10 10 <div id="${h.FID(filenode.changeset.raw_id,filenode.path)}_target" style="clear:both;margin-top:25px"></div>
11 11 <div id="${h.FID(filenode.changeset.raw_id,filenode.path)}" class="diffblock margined comm">
12 12 <div class="code-header">
13 13 <div class="changeset_header">
14 14 <div class="changeset_file">
15 15 ${h.link_to_if(change!='removed',h.safe_unicode(filenode.path),h.url('files_home',repo_name=c.repo_name,
16 16 revision=filenode.changeset.raw_id,f_path=h.safe_unicode(filenode.path)))}
17 17 </div>
18 18 <div class="diff-actions">
19 19 <a href="${h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(filenode.path),diff2=cs2,diff1=cs1,diff='diff',fulldiff=1)}" class="tooltip" title="${h.tooltip(_('diff'))}"><img class="icon" src="${h.url('/images/icons/page_white_go.png')}"/></a>
20 20 <a href="${h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(filenode.path),diff2=cs2,diff1=cs1,diff='raw')}" class="tooltip" title="${h.tooltip(_('raw diff'))}"><img class="icon" src="${h.url('/images/icons/page_white.png')}"/></a>
21 21 <a href="${h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(filenode.path),diff2=cs2,diff1=cs1,diff='download')}" class="tooltip" title="${h.tooltip(_('download diff'))}"><img class="icon" src="${h.url('/images/icons/page_white_get.png')}"/></a>
22 22 ${c.ignorews_url(request.GET, h.FID(filenode.changeset.raw_id,filenode.path))}
23 23 ${c.context_url(request.GET, h.FID(filenode.changeset.raw_id,filenode.path))}
24 24 </div>
25 25 <span style="float:right;margin-top:-3px">
26 26 <label>
27 27 ${_('show inline comments')}
28 28 ${h.checkbox('',checked="checked",class_="show-inline-comments",id_for=h.FID(filenode.changeset.raw_id,filenode.path))}
29 29 </label>
30 30 </span>
31 31 </div>
32 32 </div>
33 33 <div class="code-body">
34 34 <div class="full_f_path" path="${h.safe_unicode(filenode.path)}"></div>
35 35 ${diff|n}
36 36 </div>
37 37 </div>
38 38 %endif
39 39 %endfor
40 40
41 41 </%def>
42 42
43 43 <%def name="diff_block_simple(change)">
44 44
45 45 %for op,filenode_path,diff in change:
46 46 <div id="${h.FID('',filenode_path)}_target" style="clear:both;margin-top:25px"></div>
47 47 <div id="${h.FID('',filenode_path)}" class="diffblock margined comm">
48 48 <div class="code-header">
49 49 <div class="changeset_header">
50 50 <div class="changeset_file">
51 51 <a href="#">${h.safe_unicode(filenode_path)}</a>
52 52 </div>
53 53 </div>
54 54 </div>
55 55 <div class="code-body">
56 56 <div class="full_f_path" path="${h.safe_unicode(filenode_path)}"></div>
57 57 ${diff|n}
58 58 </div>
59 59 </div>
60 60 %endfor
61 </%def> No newline at end of file
61 </%def>
@@ -1,12 +1,12 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="main.html"/>
3 3
4 4 <h4>${subject}</h4>
5 5
6 6 ${body}
7 7
8 8 % if status_change is not None:
9 9 <div>
10 10 New status -> ${status_change}
11 11 </div>
12 % endif No newline at end of file
12 % endif
General Comments 0
You need to be logged in to leave comments. Login now