##// END OF EJS Templates
better path extraction method....
marcink -
r2490:7a5eeafb beta
parent child Browse files
Show More
@@ -1,228 +1,236
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 ip = environ.get(proxy_key2)
38 ip = environ.get(proxy_key2)
39 if ip:
39 if ip:
40 return ip
40 return ip
41
41
42 ip = environ.get(proxy_key)
42 ip = environ.get(proxy_key)
43
43
44 if ip:
44 if ip:
45 return ip
45 return ip
46
46
47 ip = environ.get(def_key, '0.0.0.0')
47 ip = environ.get(def_key, '0.0.0.0')
48 return ip
48 return ip
49
49
50
50
51 def _get_access_path(environ):
52 path = environ.get('PATH_INFO')
53 org_req = environ.get('pylons.original_request')
54 if org_req:
55 path = org_req.environ.get('PATH_INFO')
56 return path
57
58
51 class BasicAuth(AuthBasicAuthenticator):
59 class BasicAuth(AuthBasicAuthenticator):
52
60
53 def __init__(self, realm, authfunc, auth_http_code=None):
61 def __init__(self, realm, authfunc, auth_http_code=None):
54 self.realm = realm
62 self.realm = realm
55 self.authfunc = authfunc
63 self.authfunc = authfunc
56 self._rc_auth_http_code = auth_http_code
64 self._rc_auth_http_code = auth_http_code
57
65
58 def build_authentication(self):
66 def build_authentication(self):
59 head = WWW_AUTHENTICATE.tuples('Basic realm="%s"' % self.realm)
67 head = WWW_AUTHENTICATE.tuples('Basic realm="%s"' % self.realm)
60 if self._rc_auth_http_code and self._rc_auth_http_code == '403':
68 if self._rc_auth_http_code and self._rc_auth_http_code == '403':
61 # return 403 if alternative http return code is specified in
69 # return 403 if alternative http return code is specified in
62 # RhodeCode config
70 # RhodeCode config
63 return HTTPForbidden(headers=head)
71 return HTTPForbidden(headers=head)
64 return HTTPUnauthorized(headers=head)
72 return HTTPUnauthorized(headers=head)
65
73
66
74
67 class BaseVCSController(object):
75 class BaseVCSController(object):
68
76
69 def __init__(self, application, config):
77 def __init__(self, application, config):
70 self.application = application
78 self.application = application
71 self.config = config
79 self.config = config
72 # base path of repo locations
80 # base path of repo locations
73 self.basepath = self.config['base_path']
81 self.basepath = self.config['base_path']
74 #authenticate this mercurial request using authfunc
82 #authenticate this mercurial request using authfunc
75 self.authenticate = BasicAuth('', authfunc,
83 self.authenticate = BasicAuth('', authfunc,
76 config.get('auth_ret_code'))
84 config.get('auth_ret_code'))
77 self.ipaddr = '0.0.0.0'
85 self.ipaddr = '0.0.0.0'
78
86
79 def _handle_request(self, environ, start_response):
87 def _handle_request(self, environ, start_response):
80 raise NotImplementedError()
88 raise NotImplementedError()
81
89
82 def _get_by_id(self, repo_name):
90 def _get_by_id(self, repo_name):
83 """
91 """
84 Get's a special pattern _<ID> from clone url and tries to replace it
92 Get's a special pattern _<ID> from clone url and tries to replace it
85 with a repository_name for support of _<ID> non changable urls
93 with a repository_name for support of _<ID> non changable urls
86
94
87 :param repo_name:
95 :param repo_name:
88 """
96 """
89 try:
97 try:
90 data = repo_name.split('/')
98 data = repo_name.split('/')
91 if len(data) >= 2:
99 if len(data) >= 2:
92 by_id = data[1].split('_')
100 by_id = data[1].split('_')
93 if len(by_id) == 2 and by_id[1].isdigit():
101 if len(by_id) == 2 and by_id[1].isdigit():
94 _repo_name = Repository.get(by_id[1]).repo_name
102 _repo_name = Repository.get(by_id[1]).repo_name
95 data[1] = _repo_name
103 data[1] = _repo_name
96 except:
104 except:
97 log.debug('Failed to extract repo_name from id %s' % (
105 log.debug('Failed to extract repo_name from id %s' % (
98 traceback.format_exc()
106 traceback.format_exc()
99 )
107 )
100 )
108 )
101
109
102 return '/'.join(data)
110 return '/'.join(data)
103
111
104 def _invalidate_cache(self, repo_name):
112 def _invalidate_cache(self, repo_name):
105 """
113 """
106 Set's cache for this repository for invalidation on next access
114 Set's cache for this repository for invalidation on next access
107
115
108 :param repo_name: full repo name, also a cache key
116 :param repo_name: full repo name, also a cache key
109 """
117 """
110 invalidate_cache('get_repo_cached_%s' % repo_name)
118 invalidate_cache('get_repo_cached_%s' % repo_name)
111
119
112 def _check_permission(self, action, user, repo_name):
120 def _check_permission(self, action, user, repo_name):
113 """
121 """
114 Checks permissions using action (push/pull) user and repository
122 Checks permissions using action (push/pull) user and repository
115 name
123 name
116
124
117 :param action: push or pull action
125 :param action: push or pull action
118 :param user: user instance
126 :param user: user instance
119 :param repo_name: repository name
127 :param repo_name: repository name
120 """
128 """
121 if action == 'push':
129 if action == 'push':
122 if not HasPermissionAnyMiddleware('repository.write',
130 if not HasPermissionAnyMiddleware('repository.write',
123 'repository.admin')(user,
131 'repository.admin')(user,
124 repo_name):
132 repo_name):
125 return False
133 return False
126
134
127 else:
135 else:
128 #any other action need at least read permission
136 #any other action need at least read permission
129 if not HasPermissionAnyMiddleware('repository.read',
137 if not HasPermissionAnyMiddleware('repository.read',
130 'repository.write',
138 'repository.write',
131 'repository.admin')(user,
139 'repository.admin')(user,
132 repo_name):
140 repo_name):
133 return False
141 return False
134
142
135 return True
143 return True
136
144
137 def _get_ip_addr(self, environ):
145 def _get_ip_addr(self, environ):
138 return _get_ip_addr(environ)
146 return _get_ip_addr(environ)
139
147
140 def __call__(self, environ, start_response):
148 def __call__(self, environ, start_response):
141 start = time.time()
149 start = time.time()
142 try:
150 try:
143 return self._handle_request(environ, start_response)
151 return self._handle_request(environ, start_response)
144 finally:
152 finally:
145 log = logging.getLogger('rhodecode.' + self.__class__.__name__)
153 log = logging.getLogger('rhodecode.' + self.__class__.__name__)
146 log.debug('Request time: %.3fs' % (time.time() - start))
154 log.debug('Request time: %.3fs' % (time.time() - start))
147 meta.Session.remove()
155 meta.Session.remove()
148
156
149
157
150 class BaseController(WSGIController):
158 class BaseController(WSGIController):
151
159
152 def __before__(self):
160 def __before__(self):
153 c.rhodecode_version = __version__
161 c.rhodecode_version = __version__
154 c.rhodecode_instanceid = config.get('instance_id')
162 c.rhodecode_instanceid = config.get('instance_id')
155 c.rhodecode_name = config.get('rhodecode_title')
163 c.rhodecode_name = config.get('rhodecode_title')
156 c.use_gravatar = str2bool(config.get('use_gravatar'))
164 c.use_gravatar = str2bool(config.get('use_gravatar'))
157 c.ga_code = config.get('rhodecode_ga_code')
165 c.ga_code = config.get('rhodecode_ga_code')
158 c.repo_name = get_repo_slug(request)
166 c.repo_name = get_repo_slug(request)
159 c.backends = BACKENDS.keys()
167 c.backends = BACKENDS.keys()
160 c.unread_notifications = NotificationModel()\
168 c.unread_notifications = NotificationModel()\
161 .get_unread_cnt_for_user(c.rhodecode_user.user_id)
169 .get_unread_cnt_for_user(c.rhodecode_user.user_id)
162 self.cut_off_limit = int(config.get('cut_off_limit'))
170 self.cut_off_limit = int(config.get('cut_off_limit'))
163
171
164 self.sa = meta.Session
172 self.sa = meta.Session
165 self.scm_model = ScmModel(self.sa)
173 self.scm_model = ScmModel(self.sa)
166 self.ip_addr = ''
174 self.ip_addr = ''
167
175
168 def __call__(self, environ, start_response):
176 def __call__(self, environ, start_response):
169 """Invoke the Controller"""
177 """Invoke the Controller"""
170 # WSGIController.__call__ dispatches to the Controller method
178 # WSGIController.__call__ dispatches to the Controller method
171 # the request is routed to. This routing information is
179 # the request is routed to. This routing information is
172 # available in environ['pylons.routes_dict']
180 # available in environ['pylons.routes_dict']
173 start = time.time()
181 start = time.time()
174 try:
182 try:
175 self.ip_addr = _get_ip_addr(environ)
183 self.ip_addr = _get_ip_addr(environ)
176 # make sure that we update permissions each time we call controller
184 # make sure that we update permissions each time we call controller
177 api_key = request.GET.get('api_key')
185 api_key = request.GET.get('api_key')
178 cookie_store = CookieStoreWrapper(session.get('rhodecode_user'))
186 cookie_store = CookieStoreWrapper(session.get('rhodecode_user'))
179 user_id = cookie_store.get('user_id', None)
187 user_id = cookie_store.get('user_id', None)
180 username = get_container_username(environ, config)
188 username = get_container_username(environ, config)
181 auth_user = AuthUser(user_id, api_key, username)
189 auth_user = AuthUser(user_id, api_key, username)
182 request.user = auth_user
190 request.user = auth_user
183 self.rhodecode_user = c.rhodecode_user = auth_user
191 self.rhodecode_user = c.rhodecode_user = auth_user
184 if not self.rhodecode_user.is_authenticated and \
192 if not self.rhodecode_user.is_authenticated and \
185 self.rhodecode_user.user_id is not None:
193 self.rhodecode_user.user_id is not None:
186 self.rhodecode_user.set_authenticated(
194 self.rhodecode_user.set_authenticated(
187 cookie_store.get('is_authenticated')
195 cookie_store.get('is_authenticated')
188 )
196 )
189 log.info('IP: %s User: %s accessed %s' % (
197 log.info('IP: %s User: %s accessed %s' % (
190 self.ip_addr, auth_user, safe_unicode(environ.get('PATH_INFO')))
198 self.ip_addr, auth_user, safe_unicode(_get_access_path(environ)))
191 )
199 )
192 return WSGIController.__call__(self, environ, start_response)
200 return WSGIController.__call__(self, environ, start_response)
193 finally:
201 finally:
194 log.info('IP: %s Request to %s time: %.3fs' % (
202 log.info('IP: %s Request to %s time: %.3fs' % (
195 _get_ip_addr(environ),
203 _get_ip_addr(environ),
196 safe_unicode(environ.get('PATH_INFO')), time.time() - start)
204 safe_unicode(_get_access_path(environ)), time.time() - start)
197 )
205 )
198 meta.Session.remove()
206 meta.Session.remove()
199
207
200
208
201 class BaseRepoController(BaseController):
209 class BaseRepoController(BaseController):
202 """
210 """
203 Base class for controllers responsible for loading all needed data for
211 Base class for controllers responsible for loading all needed data for
204 repository loaded items are
212 repository loaded items are
205
213
206 c.rhodecode_repo: instance of scm repository
214 c.rhodecode_repo: instance of scm repository
207 c.rhodecode_db_repo: instance of db
215 c.rhodecode_db_repo: instance of db
208 c.repository_followers: number of followers
216 c.repository_followers: number of followers
209 c.repository_forks: number of forks
217 c.repository_forks: number of forks
210 """
218 """
211
219
212 def __before__(self):
220 def __before__(self):
213 super(BaseRepoController, self).__before__()
221 super(BaseRepoController, self).__before__()
214 if c.repo_name:
222 if c.repo_name:
215
223
216 dbr = c.rhodecode_db_repo = Repository.get_by_repo_name(c.repo_name)
224 dbr = c.rhodecode_db_repo = Repository.get_by_repo_name(c.repo_name)
217 c.rhodecode_repo = c.rhodecode_db_repo.scm_instance
225 c.rhodecode_repo = c.rhodecode_db_repo.scm_instance
218
226
219 if c.rhodecode_repo is None:
227 if c.rhodecode_repo is None:
220 log.error('%s this repository is present in database but it '
228 log.error('%s this repository is present in database but it '
221 'cannot be created as an scm instance', c.repo_name)
229 'cannot be created as an scm instance', c.repo_name)
222
230
223 redirect(url('home'))
231 redirect(url('home'))
224
232
225 # some globals counter for menu
233 # some globals counter for menu
226 c.repository_followers = self.scm_model.get_followers(dbr)
234 c.repository_followers = self.scm_model.get_followers(dbr)
227 c.repository_forks = self.scm_model.get_forks(dbr)
235 c.repository_forks = self.scm_model.get_forks(dbr)
228 c.repository_pull_requests = self.scm_model.get_pull_requests(dbr)
236 c.repository_pull_requests = self.scm_model.get_pull_requests(dbr)
@@ -1,53 +1,55
1 ## -*- coding: utf-8 -*-
1 ## -*- coding: utf-8 -*-
2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2 <!DOCTYPE html>
3 <html xmlns="http://www.w3.org/1999/xhtml">
3 <html xmlns="http://www.w3.org/1999/xhtml">
4 <head>
4 <head>
5 <title>Error - ${c.error_message}</title>
5 <title>Error - ${c.error_message}</title>
6 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
6 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
7 <meta name="robots" content="index, nofollow"/>
8 <link rel="icon" href="${h.url('/images/icons/database_gear.png')}" type="image/png" />
9
10 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
7 %if c.redirect_time:
11 %if c.redirect_time:
8 <meta http-equiv="refresh" content="${c.redirect_time}; url=${c.url_redirect}"/>
12 <meta http-equiv="refresh" content="${c.redirect_time}; url=${c.url_redirect}"/>
9 %endif
13 %endif
10 <link rel="icon" href="${h.url("/images/hgicon.png")}" type="image/png" />
11 <meta name="robots" content="index, nofollow"/>
12
14
13 <!-- stylesheets -->
15 <!-- stylesheets -->
14 <link rel="stylesheet" type="text/css" href="${h.url('/css/style.css')}" media="screen" />
16 <link rel="stylesheet" type="text/css" href="${h.url('/css/style.css')}" media="screen" />
15 <style type="text/css">
17 <style type="text/css">
16 #main_div{
18 #main_div{
17 border: 0px solid #000;
19 border: 0px solid #000;
18 width: 500px;
20 width: 500px;
19 margin: auto;
21 margin: auto;
20 text-align: center;
22 text-align: center;
21 margin-top: 200px;
23 margin-top: 200px;
22 font-size: 1.6em;
24 font-size: 1.6em;
23 }
25 }
24 .error_message{
26 .error_message{
25 text-align: center;
27 text-align: center;
26 color:#003367;
28 color:#003367;
27 font-size: 1.6em;
29 font-size: 1.6em;
28 margin:10px;
30 margin:10px;
29 }
31 }
30 </style>
32 </style>
31
33
32 </head>
34 </head>
33 <body>
35 <body>
34
36
35 <div id="login">
37 <div id="login">
36 <div class="table">
38 <div class="table">
37 <div id="main_div">
39 <div id="main_div">
38 <div style="font-size:2.0em;margin: 10px">${c.rhodecode_name}</div>
40 <div style="font-size:2.0em;margin: 10px">${c.rhodecode_name}</div>
39 <h1 class="error_message">${c.error_message}</h1>
41 <h1 class="error_message">${c.error_message}</h1>
40
42
41 <p>${c.error_explanation}</p>
43 <p>${c.error_explanation}</p>
42
44
43 %if c.redirect_time:
45 %if c.redirect_time:
44 <p>${_('You will be redirected to %s in %s seconds') % (c.redirect_module,c.redirect_time)}</p>
46 <p>${_('You will be redirected to %s in %s seconds') % (c.redirect_module,c.redirect_time)}</p>
45 %endif
47 %endif
46
48
47 </div>
49 </div>
48 </div>
50 </div>
49 <!-- end login -->
51 <!-- end login -->
50 </div>
52 </div>
51 </body>
53 </body>
52
54
53 </html>
55 </html>
General Comments 0
You need to be logged in to leave comments. Login now