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