##// END OF EJS Templates
Add ip reference into BaseController
marcink -
r2374:be2163ef beta
parent child Browse files
Show More
@@ -1,213 +1,217 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):
34 proxy_key = 'HTTP_X_REAL_IP'
35 proxy_key2 = 'HTTP_X_FORWARDED_FOR'
36 def_key = 'REMOTE_ADDR'
37
38 return environ.get(proxy_key2,
39 environ.get(proxy_key, environ.get(def_key, '0.0.0.0'))
40 )
41
42
33 class BasicAuth(AuthBasicAuthenticator):
43 class BasicAuth(AuthBasicAuthenticator):
34
44
35 def __init__(self, realm, authfunc, auth_http_code=None):
45 def __init__(self, realm, authfunc, auth_http_code=None):
36 self.realm = realm
46 self.realm = realm
37 self.authfunc = authfunc
47 self.authfunc = authfunc
38 self._rc_auth_http_code = auth_http_code
48 self._rc_auth_http_code = auth_http_code
39
49
40 def build_authentication(self):
50 def build_authentication(self):
41 head = WWW_AUTHENTICATE.tuples('Basic realm="%s"' % self.realm)
51 head = WWW_AUTHENTICATE.tuples('Basic realm="%s"' % self.realm)
42 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':
43 # return 403 if alternative http return code is specified in
53 # return 403 if alternative http return code is specified in
44 # RhodeCode config
54 # RhodeCode config
45 return HTTPForbidden(headers=head)
55 return HTTPForbidden(headers=head)
46 return HTTPUnauthorized(headers=head)
56 return HTTPUnauthorized(headers=head)
47
57
48
58
49 class BaseVCSController(object):
59 class BaseVCSController(object):
50
60
51 def __init__(self, application, config):
61 def __init__(self, application, config):
52 self.application = application
62 self.application = application
53 self.config = config
63 self.config = config
54 # base path of repo locations
64 # base path of repo locations
55 self.basepath = self.config['base_path']
65 self.basepath = self.config['base_path']
56 #authenticate this mercurial request using authfunc
66 #authenticate this mercurial request using authfunc
57 self.authenticate = BasicAuth('', authfunc,
67 self.authenticate = BasicAuth('', authfunc,
58 config.get('auth_ret_code'))
68 config.get('auth_ret_code'))
59 self.ipaddr = '0.0.0.0'
69 self.ipaddr = '0.0.0.0'
60
70
61 def _handle_request(self, environ, start_response):
71 def _handle_request(self, environ, start_response):
62 raise NotImplementedError()
72 raise NotImplementedError()
63
73
64 def _get_by_id(self, repo_name):
74 def _get_by_id(self, repo_name):
65 """
75 """
66 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
67 with a repository_name for support of _<ID> non changable urls
77 with a repository_name for support of _<ID> non changable urls
68
78
69 :param repo_name:
79 :param repo_name:
70 """
80 """
71 try:
81 try:
72 data = repo_name.split('/')
82 data = repo_name.split('/')
73 if len(data) >= 2:
83 if len(data) >= 2:
74 by_id = data[1].split('_')
84 by_id = data[1].split('_')
75 if len(by_id) == 2 and by_id[1].isdigit():
85 if len(by_id) == 2 and by_id[1].isdigit():
76 _repo_name = Repository.get(by_id[1]).repo_name
86 _repo_name = Repository.get(by_id[1]).repo_name
77 data[1] = _repo_name
87 data[1] = _repo_name
78 except:
88 except:
79 log.debug('Failed to extract repo_name from id %s' % (
89 log.debug('Failed to extract repo_name from id %s' % (
80 traceback.format_exc()
90 traceback.format_exc()
81 )
91 )
82 )
92 )
83
93
84 return '/'.join(data)
94 return '/'.join(data)
85
95
86 def _invalidate_cache(self, repo_name):
96 def _invalidate_cache(self, repo_name):
87 """
97 """
88 Set's cache for this repository for invalidation on next access
98 Set's cache for this repository for invalidation on next access
89
99
90 :param repo_name: full repo name, also a cache key
100 :param repo_name: full repo name, also a cache key
91 """
101 """
92 invalidate_cache('get_repo_cached_%s' % repo_name)
102 invalidate_cache('get_repo_cached_%s' % repo_name)
93
103
94 def _check_permission(self, action, user, repo_name):
104 def _check_permission(self, action, user, repo_name):
95 """
105 """
96 Checks permissions using action (push/pull) user and repository
106 Checks permissions using action (push/pull) user and repository
97 name
107 name
98
108
99 :param action: push or pull action
109 :param action: push or pull action
100 :param user: user instance
110 :param user: user instance
101 :param repo_name: repository name
111 :param repo_name: repository name
102 """
112 """
103 if action == 'push':
113 if action == 'push':
104 if not HasPermissionAnyMiddleware('repository.write',
114 if not HasPermissionAnyMiddleware('repository.write',
105 'repository.admin')(user,
115 'repository.admin')(user,
106 repo_name):
116 repo_name):
107 return False
117 return False
108
118
109 else:
119 else:
110 #any other action need at least read permission
120 #any other action need at least read permission
111 if not HasPermissionAnyMiddleware('repository.read',
121 if not HasPermissionAnyMiddleware('repository.read',
112 'repository.write',
122 'repository.write',
113 'repository.admin')(user,
123 'repository.admin')(user,
114 repo_name):
124 repo_name):
115 return False
125 return False
116
126
117 return True
127 return True
118
128
119 def _get_ip_addr(self, environ):
129 def _get_ip_addr(self, environ):
120 proxy_key = 'HTTP_X_REAL_IP'
130 return _get_ip_addr(environ)
121 proxy_key2 = 'HTTP_X_FORWARDED_FOR'
122 def_key = 'REMOTE_ADDR'
123
124 return environ.get(proxy_key2,
125 environ.get(proxy_key,
126 environ.get(def_key, '0.0.0.0')
127 )
128 )
129
131
130 def __call__(self, environ, start_response):
132 def __call__(self, environ, start_response):
131 start = time.time()
133 start = time.time()
132 try:
134 try:
133 return self._handle_request(environ, start_response)
135 return self._handle_request(environ, start_response)
134 finally:
136 finally:
135 log = logging.getLogger('rhodecode.' + self.__class__.__name__)
137 log = logging.getLogger('rhodecode.' + self.__class__.__name__)
136 log.debug('Request time: %.3fs' % (time.time() - start))
138 log.debug('Request time: %.3fs' % (time.time() - start))
137 meta.Session.remove()
139 meta.Session.remove()
138
140
139
141
140 class BaseController(WSGIController):
142 class BaseController(WSGIController):
141
143
142 def __before__(self):
144 def __before__(self):
143 c.rhodecode_version = __version__
145 c.rhodecode_version = __version__
144 c.rhodecode_instanceid = config.get('instance_id')
146 c.rhodecode_instanceid = config.get('instance_id')
145 c.rhodecode_name = config.get('rhodecode_title')
147 c.rhodecode_name = config.get('rhodecode_title')
146 c.use_gravatar = str2bool(config.get('use_gravatar'))
148 c.use_gravatar = str2bool(config.get('use_gravatar'))
147 c.ga_code = config.get('rhodecode_ga_code')
149 c.ga_code = config.get('rhodecode_ga_code')
148 c.repo_name = get_repo_slug(request)
150 c.repo_name = get_repo_slug(request)
149 c.backends = BACKENDS.keys()
151 c.backends = BACKENDS.keys()
150 c.unread_notifications = NotificationModel()\
152 c.unread_notifications = NotificationModel()\
151 .get_unread_cnt_for_user(c.rhodecode_user.user_id)
153 .get_unread_cnt_for_user(c.rhodecode_user.user_id)
152 self.cut_off_limit = int(config.get('cut_off_limit'))
154 self.cut_off_limit = int(config.get('cut_off_limit'))
153
155
154 self.sa = meta.Session
156 self.sa = meta.Session
155 self.scm_model = ScmModel(self.sa)
157 self.scm_model = ScmModel(self.sa)
158 self.ip_addr = ''
156
159
157 def __call__(self, environ, start_response):
160 def __call__(self, environ, start_response):
158 """Invoke the Controller"""
161 """Invoke the Controller"""
159 # WSGIController.__call__ dispatches to the Controller method
162 # WSGIController.__call__ dispatches to the Controller method
160 # the request is routed to. This routing information is
163 # the request is routed to. This routing information is
161 # available in environ['pylons.routes_dict']
164 # available in environ['pylons.routes_dict']
162 start = time.time()
165 start = time.time()
163 try:
166 try:
167 self.ip_addr = _get_ip_addr(environ)
164 # make sure that we update permissions each time we call controller
168 # make sure that we update permissions each time we call controller
165 api_key = request.GET.get('api_key')
169 api_key = request.GET.get('api_key')
166 cookie_store = CookieStoreWrapper(session.get('rhodecode_user'))
170 cookie_store = CookieStoreWrapper(session.get('rhodecode_user'))
167 user_id = cookie_store.get('user_id', None)
171 user_id = cookie_store.get('user_id', None)
168 username = get_container_username(environ, config)
172 username = get_container_username(environ, config)
169 auth_user = AuthUser(user_id, api_key, username)
173 auth_user = AuthUser(user_id, api_key, username)
170 request.user = auth_user
174 request.user = auth_user
171 self.rhodecode_user = c.rhodecode_user = auth_user
175 self.rhodecode_user = c.rhodecode_user = auth_user
172 if not self.rhodecode_user.is_authenticated and \
176 if not self.rhodecode_user.is_authenticated and \
173 self.rhodecode_user.user_id is not None:
177 self.rhodecode_user.user_id is not None:
174 self.rhodecode_user.set_authenticated(
178 self.rhodecode_user.set_authenticated(
175 cookie_store.get('is_authenticated')
179 cookie_store.get('is_authenticated')
176 )
180 )
177 log.info('User: %s accessed %s' % (
181 log.info('User: %s accessed %s' % (
178 auth_user, safe_unicode(environ.get('PATH_INFO')))
182 auth_user, safe_unicode(environ.get('PATH_INFO')))
179 )
183 )
180 return WSGIController.__call__(self, environ, start_response)
184 return WSGIController.__call__(self, environ, start_response)
181 finally:
185 finally:
182 log.info('Request to %s time: %.3fs' % (
186 log.info('Request to %s time: %.3fs' % (
183 safe_unicode(environ.get('PATH_INFO')), time.time() - start)
187 safe_unicode(environ.get('PATH_INFO')), time.time() - start)
184 )
188 )
185 meta.Session.remove()
189 meta.Session.remove()
186
190
187
191
188 class BaseRepoController(BaseController):
192 class BaseRepoController(BaseController):
189 """
193 """
190 Base class for controllers responsible for loading all needed data for
194 Base class for controllers responsible for loading all needed data for
191 repository loaded items are
195 repository loaded items are
192
196
193 c.rhodecode_repo: instance of scm repository
197 c.rhodecode_repo: instance of scm repository
194 c.rhodecode_db_repo: instance of db
198 c.rhodecode_db_repo: instance of db
195 c.repository_followers: number of followers
199 c.repository_followers: number of followers
196 c.repository_forks: number of forks
200 c.repository_forks: number of forks
197 """
201 """
198
202
199 def __before__(self):
203 def __before__(self):
200 super(BaseRepoController, self).__before__()
204 super(BaseRepoController, self).__before__()
201 if c.repo_name:
205 if c.repo_name:
202
206
203 c.rhodecode_db_repo = Repository.get_by_repo_name(c.repo_name)
207 c.rhodecode_db_repo = Repository.get_by_repo_name(c.repo_name)
204 c.rhodecode_repo = c.rhodecode_db_repo.scm_instance
208 c.rhodecode_repo = c.rhodecode_db_repo.scm_instance
205
209
206 if c.rhodecode_repo is None:
210 if c.rhodecode_repo is None:
207 log.error('%s this repository is present in database but it '
211 log.error('%s this repository is present in database but it '
208 'cannot be created as an scm instance', c.repo_name)
212 'cannot be created as an scm instance', c.repo_name)
209
213
210 redirect(url('home'))
214 redirect(url('home'))
211
215
212 c.repository_followers = self.scm_model.get_followers(c.repo_name)
216 c.repository_followers = self.scm_model.get_followers(c.repo_name)
213 c.repository_forks = self.scm_model.get_forks(c.repo_name)
217 c.repository_forks = self.scm_model.get_forks(c.repo_name)
General Comments 0
You need to be logged in to leave comments. Login now