##// END OF EJS Templates
moved time measure of request to separate middleware for better results (the last one in stack)
marcink -
r3489:d997a314 beta
parent child Browse files
Show More
@@ -0,0 +1,47 b''
1 # -*- coding: utf-8 -*-
2 """
3 rhodecode.lib.middleware.wrapper
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5
6 request time mesuring app
7
8 :created_on: May 23, 2013
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
12 """
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
17 #
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
22 #
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 import time
26 import logging
27 from rhodecode.lib.base import _get_ip_addr, _get_access_path
28 from rhodecode.lib.utils2 import safe_unicode
29
30
31 class RequestWrapper(object):
32
33 def __init__(self, app, config):
34 self.application = app
35 self.config = config
36
37 def __call__(self, environ, start_response):
38 start = time.time()
39 try:
40 return self.application(environ, start_response)
41 finally:
42 log = logging.getLogger('rhodecode.' + self.__class__.__name__)
43 log.info('IP: %s Request to %s time: %.3fs' % (
44 _get_ip_addr(environ),
45 safe_unicode(_get_access_path(environ)), time.time() - start)
46 )
47
@@ -1,92 +1,93 b''
1 """Pylons middleware initialization"""
1 """Pylons middleware initialization"""
2
2
3 from beaker.middleware import SessionMiddleware
3 from beaker.middleware import SessionMiddleware
4 from routes.middleware import RoutesMiddleware
4 from routes.middleware import RoutesMiddleware
5 from paste.cascade import Cascade
5 from paste.cascade import Cascade
6 from paste.registry import RegistryManager
6 from paste.registry import RegistryManager
7 from paste.urlparser import StaticURLParser
7 from paste.urlparser import StaticURLParser
8 from paste.deploy.converters import asbool
8 from paste.deploy.converters import asbool
9 from paste.gzipper import make_gzip_middleware
9 from paste.gzipper import make_gzip_middleware
10
10
11 from pylons.middleware import ErrorHandler, StatusCodeRedirect
11 from pylons.middleware import ErrorHandler, StatusCodeRedirect
12 from pylons.wsgiapp import PylonsApp
12 from pylons.wsgiapp import PylonsApp
13
13
14 from rhodecode.lib.middleware.simplehg import SimpleHg
14 from rhodecode.lib.middleware.simplehg import SimpleHg
15 from rhodecode.lib.middleware.simplegit import SimpleGit
15 from rhodecode.lib.middleware.simplegit import SimpleGit
16 from rhodecode.lib.middleware.https_fixup import HttpsFixup
16 from rhodecode.lib.middleware.https_fixup import HttpsFixup
17 from rhodecode.config.environment import load_environment
17 from rhodecode.config.environment import load_environment
18 from rhodecode.lib.middleware.wrapper import RequestWrapper
18
19
19
20
20 def make_app(global_conf, full_stack=True, static_files=True, **app_conf):
21 def make_app(global_conf, full_stack=True, static_files=True, **app_conf):
21 """Create a Pylons WSGI application and return it
22 """Create a Pylons WSGI application and return it
22
23
23 ``global_conf``
24 ``global_conf``
24 The inherited configuration for this application. Normally from
25 The inherited configuration for this application. Normally from
25 the [DEFAULT] section of the Paste ini file.
26 the [DEFAULT] section of the Paste ini file.
26
27
27 ``full_stack``
28 ``full_stack``
28 Whether or not this application provides a full WSGI stack (by
29 Whether or not this application provides a full WSGI stack (by
29 default, meaning it handles its own exceptions and errors).
30 default, meaning it handles its own exceptions and errors).
30 Disable full_stack when this application is "managed" by
31 Disable full_stack when this application is "managed" by
31 another WSGI middleware.
32 another WSGI middleware.
32
33
33 ``app_conf``
34 ``app_conf``
34 The application's local configuration. Normally specified in
35 The application's local configuration. Normally specified in
35 the [app:<name>] section of the Paste ini file (where <name>
36 the [app:<name>] section of the Paste ini file (where <name>
36 defaults to main).
37 defaults to main).
37
38
38 """
39 """
39 # Configure the Pylons environment
40 # Configure the Pylons environment
40 config = load_environment(global_conf, app_conf)
41 config = load_environment(global_conf, app_conf)
41
42
42 # The Pylons WSGI app
43 # The Pylons WSGI app
43 app = PylonsApp(config=config)
44 app = PylonsApp(config=config)
44
45
45 # Routing/Session/Cache Middleware
46 # Routing/Session/Cache Middleware
46 app = RoutesMiddleware(app, config['routes.map'])
47 app = RoutesMiddleware(app, config['routes.map'])
47 app = SessionMiddleware(app, config)
48 app = SessionMiddleware(app, config)
48
49
49 # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares)
50 # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares)
50 if asbool(config['pdebug']):
51 if asbool(config['pdebug']):
51 from rhodecode.lib.profiler import ProfilingMiddleware
52 from rhodecode.lib.profiler import ProfilingMiddleware
52 app = ProfilingMiddleware(app)
53 app = ProfilingMiddleware(app)
53
54
54 if asbool(full_stack):
55 if asbool(full_stack):
55
56
56 from rhodecode.lib.middleware.sentry import Sentry
57 from rhodecode.lib.middleware.sentry import Sentry
57 from rhodecode.lib.middleware.errormator import Errormator
58 from rhodecode.lib.middleware.errormator import Errormator
58 if Errormator:
59 if Errormator:
59 app = Errormator(app, config)
60 app = Errormator(app, config)
60 elif Sentry:
61 elif Sentry:
61 app = Sentry(app, config)
62 app = Sentry(app, config)
62
63
63 # Handle Python exceptions
64 # Handle Python exceptions
64 app = ErrorHandler(app, global_conf, **config['pylons.errorware'])
65 app = ErrorHandler(app, global_conf, **config['pylons.errorware'])
65
66
66 # we want our low level middleware to get to the request ASAP. We don't
67 # we want our low level middleware to get to the request ASAP. We don't
67 # need any pylons stack middleware in them
68 # need any pylons stack middleware in them
68 app = SimpleHg(app, config)
69 app = SimpleHg(app, config)
69 app = SimpleGit(app, config)
70 app = SimpleGit(app, config)
70
71 app = RequestWrapper(app, config)
71 # Display error documents for 401, 403, 404 status codes (and
72 # Display error documents for 401, 403, 404 status codes (and
72 # 500 when debug is disabled)
73 # 500 when debug is disabled)
73 if asbool(config['debug']):
74 if asbool(config['debug']):
74 app = StatusCodeRedirect(app)
75 app = StatusCodeRedirect(app)
75 else:
76 else:
76 app = StatusCodeRedirect(app, [400, 401, 403, 404, 500])
77 app = StatusCodeRedirect(app, [400, 401, 403, 404, 500])
77
78
78 #enable https redirets based on HTTP_X_URL_SCHEME set by proxy
79 #enable https redirets based on HTTP_X_URL_SCHEME set by proxy
79 app = HttpsFixup(app, config)
80 app = HttpsFixup(app, config)
80
81
81 # Establish the Registry for this application
82 # Establish the Registry for this application
82 app = RegistryManager(app)
83 app = RegistryManager(app)
83
84
84 if asbool(static_files):
85 if asbool(static_files):
85 # Serve static files
86 # Serve static files
86 static_app = StaticURLParser(config['pylons.paths']['static_files'])
87 static_app = StaticURLParser(config['pylons.paths']['static_files'])
87 app = Cascade([static_app, app])
88 app = Cascade([static_app, app])
88 app = make_gzip_middleware(app, global_conf, compress_level=1)
89 app = make_gzip_middleware(app, global_conf, compress_level=1)
89
90
90 app.config = config
91 app.config = config
91
92
92 return app
93 return app
@@ -1,338 +1,333 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, AUTHORIZATION
11 from paste.httpheaders import WWW_AUTHENTICATE, AUTHORIZATION
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, AttributeDict,\
20 from rhodecode.lib.utils2 import str2bool, safe_unicode, AttributeDict,\
21 safe_str, safe_int
21 safe_str, safe_int
22 from rhodecode.lib.auth import AuthUser, get_container_username, authfunc,\
22 from rhodecode.lib.auth import AuthUser, get_container_username, authfunc,\
23 HasPermissionAnyMiddleware, CookieStoreWrapper
23 HasPermissionAnyMiddleware, CookieStoreWrapper
24 from rhodecode.lib.utils import get_repo_slug, invalidate_cache
24 from rhodecode.lib.utils import get_repo_slug, invalidate_cache
25 from rhodecode.model import meta
25 from rhodecode.model import meta
26
26
27 from rhodecode.model.db import Repository, RhodeCodeUi, User, RhodeCodeSetting
27 from rhodecode.model.db import Repository, RhodeCodeUi, User, RhodeCodeSetting
28 from rhodecode.model.notification import NotificationModel
28 from rhodecode.model.notification import NotificationModel
29 from rhodecode.model.scm import ScmModel
29 from rhodecode.model.scm import ScmModel
30 from rhodecode.model.meta import Session
30 from rhodecode.model.meta import Session
31
31
32 log = logging.getLogger(__name__)
32 log = logging.getLogger(__name__)
33
33
34
34
35 def _get_ip_addr(environ):
35 def _get_ip_addr(environ):
36 proxy_key = 'HTTP_X_REAL_IP'
36 proxy_key = 'HTTP_X_REAL_IP'
37 proxy_key2 = 'HTTP_X_FORWARDED_FOR'
37 proxy_key2 = 'HTTP_X_FORWARDED_FOR'
38 def_key = 'REMOTE_ADDR'
38 def_key = 'REMOTE_ADDR'
39
39
40 ip = environ.get(proxy_key)
40 ip = environ.get(proxy_key)
41 if ip:
41 if ip:
42 return ip
42 return ip
43
43
44 ip = environ.get(proxy_key2)
44 ip = environ.get(proxy_key2)
45 if ip:
45 if ip:
46 # HTTP_X_FORWARDED_FOR can have mutliple ips inside
46 # HTTP_X_FORWARDED_FOR can have mutliple ips inside
47 # the left-most being the original client, and each successive proxy
47 # the left-most being the original client, and each successive proxy
48 # that passed the request adding the IP address where it received the
48 # that passed the request adding the IP address where it received the
49 # request from.
49 # request from.
50 if ',' in ip:
50 if ',' in ip:
51 ip = ip.split(',')[0].strip()
51 ip = ip.split(',')[0].strip()
52 return ip
52 return ip
53
53
54 ip = environ.get(def_key, '0.0.0.0')
54 ip = environ.get(def_key, '0.0.0.0')
55 return ip
55 return ip
56
56
57
57
58 def _get_access_path(environ):
58 def _get_access_path(environ):
59 path = environ.get('PATH_INFO')
59 path = environ.get('PATH_INFO')
60 org_req = environ.get('pylons.original_request')
60 org_req = environ.get('pylons.original_request')
61 if org_req:
61 if org_req:
62 path = org_req.environ.get('PATH_INFO')
62 path = org_req.environ.get('PATH_INFO')
63 return path
63 return path
64
64
65
65
66 class BasicAuth(AuthBasicAuthenticator):
66 class BasicAuth(AuthBasicAuthenticator):
67
67
68 def __init__(self, realm, authfunc, auth_http_code=None):
68 def __init__(self, realm, authfunc, auth_http_code=None):
69 self.realm = realm
69 self.realm = realm
70 self.authfunc = authfunc
70 self.authfunc = authfunc
71 self._rc_auth_http_code = auth_http_code
71 self._rc_auth_http_code = auth_http_code
72
72
73 def build_authentication(self):
73 def build_authentication(self):
74 head = WWW_AUTHENTICATE.tuples('Basic realm="%s"' % self.realm)
74 head = WWW_AUTHENTICATE.tuples('Basic realm="%s"' % self.realm)
75 if self._rc_auth_http_code and self._rc_auth_http_code == '403':
75 if self._rc_auth_http_code and self._rc_auth_http_code == '403':
76 # return 403 if alternative http return code is specified in
76 # return 403 if alternative http return code is specified in
77 # RhodeCode config
77 # RhodeCode config
78 return HTTPForbidden(headers=head)
78 return HTTPForbidden(headers=head)
79 return HTTPUnauthorized(headers=head)
79 return HTTPUnauthorized(headers=head)
80
80
81 def authenticate(self, environ):
81 def authenticate(self, environ):
82 authorization = AUTHORIZATION(environ)
82 authorization = AUTHORIZATION(environ)
83 if not authorization:
83 if not authorization:
84 return self.build_authentication()
84 return self.build_authentication()
85 (authmeth, auth) = authorization.split(' ', 1)
85 (authmeth, auth) = authorization.split(' ', 1)
86 if 'basic' != authmeth.lower():
86 if 'basic' != authmeth.lower():
87 return self.build_authentication()
87 return self.build_authentication()
88 auth = auth.strip().decode('base64')
88 auth = auth.strip().decode('base64')
89 _parts = auth.split(':', 1)
89 _parts = auth.split(':', 1)
90 if len(_parts) == 2:
90 if len(_parts) == 2:
91 username, password = _parts
91 username, password = _parts
92 if self.authfunc(environ, username, password):
92 if self.authfunc(environ, username, password):
93 return username
93 return username
94 return self.build_authentication()
94 return self.build_authentication()
95
95
96 __call__ = authenticate
96 __call__ = authenticate
97
97
98
98
99 class BaseVCSController(object):
99 class BaseVCSController(object):
100
100
101 def __init__(self, application, config):
101 def __init__(self, application, config):
102 self.application = application
102 self.application = application
103 self.config = config
103 self.config = config
104 # base path of repo locations
104 # base path of repo locations
105 self.basepath = self.config['base_path']
105 self.basepath = self.config['base_path']
106 #authenticate this mercurial request using authfunc
106 #authenticate this mercurial request using authfunc
107 self.authenticate = BasicAuth('', authfunc,
107 self.authenticate = BasicAuth('', authfunc,
108 config.get('auth_ret_code'))
108 config.get('auth_ret_code'))
109 self.ip_addr = '0.0.0.0'
109 self.ip_addr = '0.0.0.0'
110
110
111 def _handle_request(self, environ, start_response):
111 def _handle_request(self, environ, start_response):
112 raise NotImplementedError()
112 raise NotImplementedError()
113
113
114 def _get_by_id(self, repo_name):
114 def _get_by_id(self, repo_name):
115 """
115 """
116 Get's a special pattern _<ID> from clone url and tries to replace it
116 Get's a special pattern _<ID> from clone url and tries to replace it
117 with a repository_name for support of _<ID> non changable urls
117 with a repository_name for support of _<ID> non changable urls
118
118
119 :param repo_name:
119 :param repo_name:
120 """
120 """
121 try:
121 try:
122 data = repo_name.split('/')
122 data = repo_name.split('/')
123 if len(data) >= 2:
123 if len(data) >= 2:
124 by_id = data[1].split('_')
124 by_id = data[1].split('_')
125 if len(by_id) == 2 and by_id[1].isdigit():
125 if len(by_id) == 2 and by_id[1].isdigit():
126 _repo_name = Repository.get(by_id[1]).repo_name
126 _repo_name = Repository.get(by_id[1]).repo_name
127 data[1] = _repo_name
127 data[1] = _repo_name
128 except:
128 except:
129 log.debug('Failed to extract repo_name from id %s' % (
129 log.debug('Failed to extract repo_name from id %s' % (
130 traceback.format_exc()
130 traceback.format_exc()
131 )
131 )
132 )
132 )
133
133
134 return '/'.join(data)
134 return '/'.join(data)
135
135
136 def _invalidate_cache(self, repo_name):
136 def _invalidate_cache(self, repo_name):
137 """
137 """
138 Set's cache for this repository for invalidation on next access
138 Set's cache for this repository for invalidation on next access
139
139
140 :param repo_name: full repo name, also a cache key
140 :param repo_name: full repo name, also a cache key
141 """
141 """
142 invalidate_cache('get_repo_cached_%s' % repo_name)
142 invalidate_cache('get_repo_cached_%s' % repo_name)
143
143
144 def _check_permission(self, action, user, repo_name, ip_addr=None):
144 def _check_permission(self, action, user, repo_name, ip_addr=None):
145 """
145 """
146 Checks permissions using action (push/pull) user and repository
146 Checks permissions using action (push/pull) user and repository
147 name
147 name
148
148
149 :param action: push or pull action
149 :param action: push or pull action
150 :param user: user instance
150 :param user: user instance
151 :param repo_name: repository name
151 :param repo_name: repository name
152 """
152 """
153 #check IP
153 #check IP
154 authuser = AuthUser(user_id=user.user_id, ip_addr=ip_addr)
154 authuser = AuthUser(user_id=user.user_id, ip_addr=ip_addr)
155 if not authuser.ip_allowed:
155 if not authuser.ip_allowed:
156 return False
156 return False
157 else:
157 else:
158 log.info('Access for IP:%s allowed' % (ip_addr))
158 log.info('Access for IP:%s allowed' % (ip_addr))
159 if action == 'push':
159 if action == 'push':
160 if not HasPermissionAnyMiddleware('repository.write',
160 if not HasPermissionAnyMiddleware('repository.write',
161 'repository.admin')(user,
161 'repository.admin')(user,
162 repo_name):
162 repo_name):
163 return False
163 return False
164
164
165 else:
165 else:
166 #any other action need at least read permission
166 #any other action need at least read permission
167 if not HasPermissionAnyMiddleware('repository.read',
167 if not HasPermissionAnyMiddleware('repository.read',
168 'repository.write',
168 'repository.write',
169 'repository.admin')(user,
169 'repository.admin')(user,
170 repo_name):
170 repo_name):
171 return False
171 return False
172
172
173 return True
173 return True
174
174
175 def _get_ip_addr(self, environ):
175 def _get_ip_addr(self, environ):
176 return _get_ip_addr(environ)
176 return _get_ip_addr(environ)
177
177
178 def _check_ssl(self, environ, start_response):
178 def _check_ssl(self, environ, start_response):
179 """
179 """
180 Checks the SSL check flag and returns False if SSL is not present
180 Checks the SSL check flag and returns False if SSL is not present
181 and required True otherwise
181 and required True otherwise
182 """
182 """
183 org_proto = environ['wsgi._org_proto']
183 org_proto = environ['wsgi._org_proto']
184 #check if we have SSL required ! if not it's a bad request !
184 #check if we have SSL required ! if not it's a bad request !
185 require_ssl = str2bool(RhodeCodeUi.get_by_key('push_ssl').ui_value)
185 require_ssl = str2bool(RhodeCodeUi.get_by_key('push_ssl').ui_value)
186 if require_ssl and org_proto == 'http':
186 if require_ssl and org_proto == 'http':
187 log.debug('proto is %s and SSL is required BAD REQUEST !'
187 log.debug('proto is %s and SSL is required BAD REQUEST !'
188 % org_proto)
188 % org_proto)
189 return False
189 return False
190 return True
190 return True
191
191
192 def _check_locking_state(self, environ, action, repo, user_id):
192 def _check_locking_state(self, environ, action, repo, user_id):
193 """
193 """
194 Checks locking on this repository, if locking is enabled and lock is
194 Checks locking on this repository, if locking is enabled and lock is
195 present returns a tuple of make_lock, locked, locked_by.
195 present returns a tuple of make_lock, locked, locked_by.
196 make_lock can have 3 states None (do nothing) True, make lock
196 make_lock can have 3 states None (do nothing) True, make lock
197 False release lock, This value is later propagated to hooks, which
197 False release lock, This value is later propagated to hooks, which
198 do the locking. Think about this as signals passed to hooks what to do.
198 do the locking. Think about this as signals passed to hooks what to do.
199
199
200 """
200 """
201 locked = False # defines that locked error should be thrown to user
201 locked = False # defines that locked error should be thrown to user
202 make_lock = None
202 make_lock = None
203 repo = Repository.get_by_repo_name(repo)
203 repo = Repository.get_by_repo_name(repo)
204 user = User.get(user_id)
204 user = User.get(user_id)
205
205
206 # this is kind of hacky, but due to how mercurial handles client-server
206 # this is kind of hacky, but due to how mercurial handles client-server
207 # server see all operation on changeset; bookmarks, phases and
207 # server see all operation on changeset; bookmarks, phases and
208 # obsolescence marker in different transaction, we don't want to check
208 # obsolescence marker in different transaction, we don't want to check
209 # locking on those
209 # locking on those
210 obsolete_call = environ['QUERY_STRING'] in ['cmd=listkeys',]
210 obsolete_call = environ['QUERY_STRING'] in ['cmd=listkeys',]
211 locked_by = repo.locked
211 locked_by = repo.locked
212 if repo and repo.enable_locking and not obsolete_call:
212 if repo and repo.enable_locking and not obsolete_call:
213 if action == 'push':
213 if action == 'push':
214 #check if it's already locked !, if it is compare users
214 #check if it's already locked !, if it is compare users
215 user_id, _date = repo.locked
215 user_id, _date = repo.locked
216 if user.user_id == user_id:
216 if user.user_id == user_id:
217 log.debug('Got push from user %s, now unlocking' % (user))
217 log.debug('Got push from user %s, now unlocking' % (user))
218 # unlock if we have push from user who locked
218 # unlock if we have push from user who locked
219 make_lock = False
219 make_lock = False
220 else:
220 else:
221 # we're not the same user who locked, ban with 423 !
221 # we're not the same user who locked, ban with 423 !
222 locked = True
222 locked = True
223 if action == 'pull':
223 if action == 'pull':
224 if repo.locked[0] and repo.locked[1]:
224 if repo.locked[0] and repo.locked[1]:
225 locked = True
225 locked = True
226 else:
226 else:
227 log.debug('Setting lock on repo %s by %s' % (repo, user))
227 log.debug('Setting lock on repo %s by %s' % (repo, user))
228 make_lock = True
228 make_lock = True
229
229
230 else:
230 else:
231 log.debug('Repository %s do not have locking enabled' % (repo))
231 log.debug('Repository %s do not have locking enabled' % (repo))
232 log.debug('FINAL locking values make_lock:%s,locked:%s,locked_by:%s'
232 log.debug('FINAL locking values make_lock:%s,locked:%s,locked_by:%s'
233 % (make_lock, locked, locked_by))
233 % (make_lock, locked, locked_by))
234 return make_lock, locked, locked_by
234 return make_lock, locked, locked_by
235
235
236 def __call__(self, environ, start_response):
236 def __call__(self, environ, start_response):
237 start = time.time()
237 start = time.time()
238 try:
238 try:
239 return self._handle_request(environ, start_response)
239 return self._handle_request(environ, start_response)
240 finally:
240 finally:
241 log = logging.getLogger('rhodecode.' + self.__class__.__name__)
241 log = logging.getLogger('rhodecode.' + self.__class__.__name__)
242 log.debug('Request time: %.3fs' % (time.time() - start))
242 log.debug('Request time: %.3fs' % (time.time() - start))
243 meta.Session.remove()
243 meta.Session.remove()
244
244
245
245
246 class BaseController(WSGIController):
246 class BaseController(WSGIController):
247
247
248 def __before__(self):
248 def __before__(self):
249 """
249 """
250 __before__ is called before controller methods and after __call__
250 __before__ is called before controller methods and after __call__
251 """
251 """
252 c.rhodecode_version = __version__
252 c.rhodecode_version = __version__
253 c.rhodecode_instanceid = config.get('instance_id')
253 c.rhodecode_instanceid = config.get('instance_id')
254 c.rhodecode_name = config.get('rhodecode_title')
254 c.rhodecode_name = config.get('rhodecode_title')
255 c.use_gravatar = str2bool(config.get('use_gravatar'))
255 c.use_gravatar = str2bool(config.get('use_gravatar'))
256 c.ga_code = config.get('rhodecode_ga_code')
256 c.ga_code = config.get('rhodecode_ga_code')
257 # Visual options
257 # Visual options
258 c.visual = AttributeDict({})
258 c.visual = AttributeDict({})
259 rc_config = RhodeCodeSetting.get_app_settings()
259 rc_config = RhodeCodeSetting.get_app_settings()
260
260
261 c.visual.show_public_icon = str2bool(rc_config.get('rhodecode_show_public_icon'))
261 c.visual.show_public_icon = str2bool(rc_config.get('rhodecode_show_public_icon'))
262 c.visual.show_private_icon = str2bool(rc_config.get('rhodecode_show_private_icon'))
262 c.visual.show_private_icon = str2bool(rc_config.get('rhodecode_show_private_icon'))
263 c.visual.stylify_metatags = str2bool(rc_config.get('rhodecode_stylify_metatags'))
263 c.visual.stylify_metatags = str2bool(rc_config.get('rhodecode_stylify_metatags'))
264 c.visual.lightweight_dashboard = str2bool(rc_config.get('rhodecode_lightweight_dashboard'))
264 c.visual.lightweight_dashboard = str2bool(rc_config.get('rhodecode_lightweight_dashboard'))
265 c.visual.lightweight_dashboard_items = safe_int(config.get('dashboard_items', 100))
265 c.visual.lightweight_dashboard_items = safe_int(config.get('dashboard_items', 100))
266 c.visual.repository_fields = str2bool(rc_config.get('rhodecode_repository_fields'))
266 c.visual.repository_fields = str2bool(rc_config.get('rhodecode_repository_fields'))
267
267
268 c.repo_name = get_repo_slug(request)
268 c.repo_name = get_repo_slug(request)
269 c.backends = BACKENDS.keys()
269 c.backends = BACKENDS.keys()
270 c.unread_notifications = NotificationModel()\
270 c.unread_notifications = NotificationModel()\
271 .get_unread_cnt_for_user(c.rhodecode_user.user_id)
271 .get_unread_cnt_for_user(c.rhodecode_user.user_id)
272 self.cut_off_limit = int(config.get('cut_off_limit'))
272 self.cut_off_limit = int(config.get('cut_off_limit'))
273
273
274 self.sa = meta.Session
274 self.sa = meta.Session
275 self.scm_model = ScmModel(self.sa)
275 self.scm_model = ScmModel(self.sa)
276
276
277 def __call__(self, environ, start_response):
277 def __call__(self, environ, start_response):
278 """Invoke the Controller"""
278 """Invoke the Controller"""
279 # WSGIController.__call__ dispatches to the Controller method
279 # WSGIController.__call__ dispatches to the Controller method
280 # the request is routed to. This routing information is
280 # the request is routed to. This routing information is
281 # available in environ['pylons.routes_dict']
281 # available in environ['pylons.routes_dict']
282 start = time.time()
283 try:
282 try:
284 self.ip_addr = _get_ip_addr(environ)
283 self.ip_addr = _get_ip_addr(environ)
285 # make sure that we update permissions each time we call controller
284 # make sure that we update permissions each time we call controller
286 api_key = request.GET.get('api_key')
285 api_key = request.GET.get('api_key')
287 cookie_store = CookieStoreWrapper(session.get('rhodecode_user'))
286 cookie_store = CookieStoreWrapper(session.get('rhodecode_user'))
288 user_id = cookie_store.get('user_id', None)
287 user_id = cookie_store.get('user_id', None)
289 username = get_container_username(environ, config)
288 username = get_container_username(environ, config)
290 auth_user = AuthUser(user_id, api_key, username, self.ip_addr)
289 auth_user = AuthUser(user_id, api_key, username, self.ip_addr)
291 request.user = auth_user
290 request.user = auth_user
292 self.rhodecode_user = c.rhodecode_user = auth_user
291 self.rhodecode_user = c.rhodecode_user = auth_user
293 if not self.rhodecode_user.is_authenticated and \
292 if not self.rhodecode_user.is_authenticated and \
294 self.rhodecode_user.user_id is not None:
293 self.rhodecode_user.user_id is not None:
295 self.rhodecode_user.set_authenticated(
294 self.rhodecode_user.set_authenticated(
296 cookie_store.get('is_authenticated')
295 cookie_store.get('is_authenticated')
297 )
296 )
298 log.info('IP: %s User: %s accessed %s' % (
297 log.info('IP: %s User: %s accessed %s' % (
299 self.ip_addr, auth_user, safe_unicode(_get_access_path(environ)))
298 self.ip_addr, auth_user, safe_unicode(_get_access_path(environ)))
300 )
299 )
301 return WSGIController.__call__(self, environ, start_response)
300 return WSGIController.__call__(self, environ, start_response)
302 finally:
301 finally:
303 log.info('IP: %s Request to %s time: %.3fs' % (
304 _get_ip_addr(environ),
305 safe_unicode(_get_access_path(environ)), time.time() - start)
306 )
307 meta.Session.remove()
302 meta.Session.remove()
308
303
309
304
310 class BaseRepoController(BaseController):
305 class BaseRepoController(BaseController):
311 """
306 """
312 Base class for controllers responsible for loading all needed data for
307 Base class for controllers responsible for loading all needed data for
313 repository loaded items are
308 repository loaded items are
314
309
315 c.rhodecode_repo: instance of scm repository
310 c.rhodecode_repo: instance of scm repository
316 c.rhodecode_db_repo: instance of db
311 c.rhodecode_db_repo: instance of db
317 c.repository_followers: number of followers
312 c.repository_followers: number of followers
318 c.repository_forks: number of forks
313 c.repository_forks: number of forks
319 """
314 """
320
315
321 def __before__(self):
316 def __before__(self):
322 super(BaseRepoController, self).__before__()
317 super(BaseRepoController, self).__before__()
323 if c.repo_name:
318 if c.repo_name:
324
319
325 dbr = c.rhodecode_db_repo = Repository.get_by_repo_name(c.repo_name)
320 dbr = c.rhodecode_db_repo = Repository.get_by_repo_name(c.repo_name)
326 c.rhodecode_repo = c.rhodecode_db_repo.scm_instance
321 c.rhodecode_repo = c.rhodecode_db_repo.scm_instance
327 # update last change according to VCS data
322 # update last change according to VCS data
328 dbr.update_changeset_cache(dbr.get_changeset())
323 dbr.update_changeset_cache(dbr.get_changeset())
329 if c.rhodecode_repo is None:
324 if c.rhodecode_repo is None:
330 log.error('%s this repository is present in database but it '
325 log.error('%s this repository is present in database but it '
331 'cannot be created as an scm instance', c.repo_name)
326 'cannot be created as an scm instance', c.repo_name)
332
327
333 redirect(url('home'))
328 redirect(url('home'))
334
329
335 # some globals counter for menu
330 # some globals counter for menu
336 c.repository_followers = self.scm_model.get_followers(dbr)
331 c.repository_followers = self.scm_model.get_followers(dbr)
337 c.repository_forks = self.scm_model.get_forks(dbr)
332 c.repository_forks = self.scm_model.get_forks(dbr)
338 c.repository_pull_requests = self.scm_model.get_pull_requests(dbr)
333 c.repository_pull_requests = self.scm_model.get_pull_requests(dbr)
General Comments 0
You need to be logged in to leave comments. Login now