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