Show More
@@ -22,12 +22,12 b' Created on Aug 6, 2010' | |||||
22 |
|
22 | |||
23 | @author: marcink |
|
23 | @author: marcink | |
24 | """ |
|
24 | """ | |
25 |
|
25 | from mercurial.cmdutil import revrange | ||
26 | import sys |
|
26 | from mercurial.node import nullrev | |
|
27 | from rhodecode.lib import helpers as h | |||
|
28 | from rhodecode.lib.utils import action_logger | |||
27 | import os |
|
29 | import os | |
28 | from rhodecode.lib import helpers as h |
|
30 | import sys | |
29 | from rhodecode.model import meta |
|
|||
30 | from rhodecode.model.db import UserLog, User |
|
|||
31 |
|
31 | |||
32 | def repo_size(ui, repo, hooktype=None, **kwargs): |
|
32 | def repo_size(ui, repo, hooktype=None, **kwargs): | |
33 |
|
33 | |||
@@ -48,31 +48,52 b' def repo_size(ui, repo, hooktype=None, *' | |||||
48 | sys.stdout.write('Repository size .hg:%s repo:%s total:%s\n' \ |
|
48 | sys.stdout.write('Repository size .hg:%s repo:%s total:%s\n' \ | |
49 | % (size_hg_f, size_root_f, size_total_f)) |
|
49 | % (size_hg_f, size_root_f, size_total_f)) | |
50 |
|
50 | |||
51 |
|
|
51 | def log_pull_action(ui, repo, **kwargs): | |
|
52 | """ | |||
|
53 | Logs user last pull action | |||
|
54 | :param ui: | |||
|
55 | :param repo: | |||
|
56 | """ | |||
52 |
|
57 | |||
53 | def user_action_mapper(ui, repo, hooktype=None, **kwargs): |
|
58 | extra_params = dict(repo.ui.configitems('rhodecode_extras')) | |
|
59 | username = extra_params['username'] | |||
|
60 | repository = extra_params['repository'] | |||
|
61 | action = 'pull' | |||
|
62 | ||||
|
63 | action_logger(username, action, repository, extra_params['ip']) | |||
|
64 | ||||
|
65 | return 0 | |||
|
66 | ||||
|
67 | def log_push_action(ui, repo, **kwargs): | |||
54 | """ |
|
68 | """ | |
55 | Maps user last push action to new changeset id, from mercurial |
|
69 | Maps user last push action to new changeset id, from mercurial | |
56 | :param ui: |
|
70 | :param ui: | |
57 | :param repo: |
|
71 | :param repo: | |
58 | :param hooktype: |
|
|||
59 | """ |
|
72 | """ | |
60 |
|
73 | |||
61 | try: |
|
74 | extra_params = dict(repo.ui.configitems('rhodecode_extras')) | |
62 | sa = meta.Session() |
|
75 | username = extra_params['username'] | |
63 | username = kwargs['url'].split(':')[-1] |
|
76 | repository = extra_params['repository'] | |
64 | user_log = sa.query(UserLog)\ |
|
77 | action = 'push:%s' | |
65 | .filter(UserLog.user == sa.query(User)\ |
|
78 | node = kwargs['node'] | |
66 | .filter(User.username == username).one())\ |
|
79 | ||
67 | .order_by(UserLog.user_log_id.desc()).first() |
|
80 | def get_revs(repo, rev_opt): | |
|
81 | if rev_opt: | |||
|
82 | revs = revrange(repo, rev_opt) | |||
68 |
|
83 | |||
69 | if user_log and not user_log.revision: |
|
84 | if len(revs) == 0: | |
70 | user_log.revision = str(repo['tip']) |
|
85 | return (nullrev, nullrev) | |
71 | sa.add(user_log) |
|
86 | return (max(revs), min(revs)) | |
72 | sa.commit() |
|
87 | else: | |
|
88 | return (len(repo) - 1, 0) | |||
|
89 | ||||
|
90 | stop, start = get_revs(repo, [node + ':']) | |||
73 |
|
|
91 | ||
74 | except Exception, e: |
|
92 | revs = (str(repo[r]) for r in xrange(start, stop + 1)) | |
75 | sa.rollback() |
|
93 | ||
76 | raise |
|
94 | action = action % ','.join(revs) | |
77 | finally: |
|
95 | ||
78 | meta.Session.remove() |
|
96 | action_logger(username, action, repository, extra_params['ip']) | |
|
97 | ||||
|
98 | return 0 | |||
|
99 |
@@ -49,15 +49,24 b' class SimpleHg(object):' | |||||
49 | self.config = config |
|
49 | self.config = config | |
50 | #authenticate this mercurial request using |
|
50 | #authenticate this mercurial request using | |
51 | self.authenticate = AuthBasicAuthenticator('', authfunc) |
|
51 | self.authenticate = AuthBasicAuthenticator('', authfunc) | |
|
52 | self.ipaddr = '0.0.0.0' | |||
|
53 | self.repository = None | |||
|
54 | self.username = None | |||
|
55 | self.action = None | |||
52 |
|
56 | |||
53 | def __call__(self, environ, start_response): |
|
57 | def __call__(self, environ, start_response): | |
54 | if not is_mercurial(environ): |
|
58 | if not is_mercurial(environ): | |
55 | return self.application(environ, start_response) |
|
59 | return self.application(environ, start_response) | |
56 |
|
60 | |||
|
61 | proxy_key = 'HTTP_X_REAL_IP' | |||
|
62 | def_key = 'REMOTE_ADDR' | |||
|
63 | self.ipaddr = environ.get(proxy_key, environ.get(def_key, '0.0.0.0')) | |||
|
64 | ||||
57 | #=================================================================== |
|
65 | #=================================================================== | |
58 | # AUTHENTICATE THIS MERCURIAL REQUEST |
|
66 | # AUTHENTICATE THIS MERCURIAL REQUEST | |
59 | #=================================================================== |
|
67 | #=================================================================== | |
60 | username = REMOTE_USER(environ) |
|
68 | username = REMOTE_USER(environ) | |
|
69 | ||||
61 | if not username: |
|
70 | if not username: | |
62 | self.authenticate.realm = self.config['rhodecode_realm'] |
|
71 | self.authenticate.realm = self.config['rhodecode_realm'] | |
63 | result = self.authenticate(environ) |
|
72 | result = self.authenticate(environ) | |
@@ -67,10 +76,14 b' class SimpleHg(object):' | |||||
67 | else: |
|
76 | else: | |
68 | return result.wsgi_application(environ, start_response) |
|
77 | return result.wsgi_application(environ, start_response) | |
69 |
|
78 | |||
|
79 | #======================================================================= | |||
|
80 | # GET REPOSITORY | |||
|
81 | #======================================================================= | |||
70 | try: |
|
82 | try: | |
71 | repo_name = '/'.join(environ['PATH_INFO'].split('/')[1:]) |
|
83 | repo_name = '/'.join(environ['PATH_INFO'].split('/')[1:]) | |
72 | if repo_name.endswith('/'): |
|
84 | if repo_name.endswith('/'): | |
73 | repo_name = repo_name.rstrip('/') |
|
85 | repo_name = repo_name.rstrip('/') | |
|
86 | self.repository = repo_name | |||
74 | except: |
|
87 | except: | |
75 | log.error(traceback.format_exc()) |
|
88 | log.error(traceback.format_exc()) | |
76 | return HTTPInternalServerError()(environ, start_response) |
|
89 | return HTTPInternalServerError()(environ, start_response) | |
@@ -78,17 +91,18 b' class SimpleHg(object):' | |||||
78 | #=================================================================== |
|
91 | #=================================================================== | |
79 | # CHECK PERMISSIONS FOR THIS REQUEST |
|
92 | # CHECK PERMISSIONS FOR THIS REQUEST | |
80 | #=================================================================== |
|
93 | #=================================================================== | |
81 | action = self.__get_action(environ) |
|
94 | self.action = self.__get_action(environ) | |
82 | if action: |
|
95 | if self.action: | |
83 | username = self.__get_environ_user(environ) |
|
96 | username = self.__get_environ_user(environ) | |
84 | try: |
|
97 | try: | |
85 | user = self.__get_user(username) |
|
98 | user = self.__get_user(username) | |
|
99 | self.username = user.username | |||
86 | except: |
|
100 | except: | |
87 | log.error(traceback.format_exc()) |
|
101 | log.error(traceback.format_exc()) | |
88 | return HTTPInternalServerError()(environ, start_response) |
|
102 | return HTTPInternalServerError()(environ, start_response) | |
89 |
|
103 | |||
90 | #check permissions for this repository |
|
104 | #check permissions for this repository | |
91 | if action == 'push': |
|
105 | if self.action == 'push': | |
92 | if not HasPermissionAnyMiddleware('repository.write', |
|
106 | if not HasPermissionAnyMiddleware('repository.write', | |
93 | 'repository.admin')\ |
|
107 | 'repository.admin')\ | |
94 | (user, repo_name): |
|
108 | (user, repo_name): | |
@@ -102,13 +116,11 b' class SimpleHg(object):' | |||||
102 | (user, repo_name): |
|
116 | (user, repo_name): | |
103 | return HTTPForbidden()(environ, start_response) |
|
117 | return HTTPForbidden()(environ, start_response) | |
104 |
|
118 | |||
105 | #log action |
|
119 | self.extras = {'ip':self.ipaddr, | |
106 | if action in ('push', 'pull', 'clone'): |
|
120 | 'username':self.username, | |
107 | proxy_key = 'HTTP_X_REAL_IP' |
|
121 | 'action':self.action, | |
108 | def_key = 'REMOTE_ADDR' |
|
122 | 'repository':self.repository} | |
109 | ipaddr = environ.get(proxy_key, environ.get(def_key, '0.0.0.0')) |
|
123 | print self.extras | |
110 | self.__log_user_action(user, action, repo_name, ipaddr) |
|
|||
111 |
|
||||
112 | #=================================================================== |
|
124 | #=================================================================== | |
113 | # MERCURIAL REQUEST HANDLING |
|
125 | # MERCURIAL REQUEST HANDLING | |
114 | #=================================================================== |
|
126 | #=================================================================== | |
@@ -130,7 +142,7 b' class SimpleHg(object):' | |||||
130 | return HTTPInternalServerError()(environ, start_response) |
|
142 | return HTTPInternalServerError()(environ, start_response) | |
131 |
|
143 | |||
132 | #invalidate cache on push |
|
144 | #invalidate cache on push | |
133 | if action == 'push': |
|
145 | if self.action == 'push': | |
134 | self.__invalidate_cache(repo_name) |
|
146 | self.__invalidate_cache(repo_name) | |
135 | messages = [] |
|
147 | messages = [] | |
136 | messages.append('thank you for using rhodecode') |
|
148 | messages.append('thank you for using rhodecode') | |
@@ -157,7 +169,7 b' class SimpleHg(object):' | |||||
157 |
|
169 | |||
158 | def __make_app(self): |
|
170 | def __make_app(self): | |
159 | hgserve = hgweb(str(self.repo_path), baseui=self.baseui) |
|
171 | hgserve = hgweb(str(self.repo_path), baseui=self.baseui) | |
160 | return self.__load_web_settings(hgserve) |
|
172 | return self.__load_web_settings(hgserve, self.extras) | |
161 |
|
173 | |||
162 | def __get_environ_user(self, environ): |
|
174 | def __get_environ_user(self, environ): | |
163 | return environ.get('REMOTE_USER') |
|
175 | return environ.get('REMOTE_USER') | |
@@ -174,7 +186,7 b' class SimpleHg(object):' | |||||
174 | mapping = {'changegroup': 'pull', |
|
186 | mapping = {'changegroup': 'pull', | |
175 | 'changegroupsubset': 'pull', |
|
187 | 'changegroupsubset': 'pull', | |
176 | 'stream_out': 'pull', |
|
188 | 'stream_out': 'pull', | |
177 |
|
|
189 | 'listkeys': 'pull', | |
178 | 'unbundle': 'push', |
|
190 | 'unbundle': 'push', | |
179 | 'pushkey': 'push', } |
|
191 | 'pushkey': 'push', } | |
180 | for qry in environ['QUERY_STRING'].split('&'): |
|
192 | for qry in environ['QUERY_STRING'].split('&'): | |
@@ -185,9 +197,6 b' class SimpleHg(object):' | |||||
185 | else: |
|
197 | else: | |
186 | return cmd |
|
198 | return cmd | |
187 |
|
199 | |||
188 | def __log_user_action(self, user, action, repo, ipaddr): |
|
|||
189 | action_logger(user, action, repo, ipaddr) |
|
|||
190 |
|
||||
191 | def __invalidate_cache(self, repo_name): |
|
200 | def __invalidate_cache(self, repo_name): | |
192 | """we know that some change was made to repositories and we should |
|
201 | """we know that some change was made to repositories and we should | |
193 | invalidate the cache to see the changes right away but only for |
|
202 | invalidate the cache to see the changes right away but only for | |
@@ -196,14 +205,19 b' class SimpleHg(object):' | |||||
196 | invalidate_cache('full_changelog', repo_name) |
|
205 | invalidate_cache('full_changelog', repo_name) | |
197 |
|
206 | |||
198 |
|
207 | |||
199 | def __load_web_settings(self, hgserve): |
|
208 | def __load_web_settings(self, hgserve, extras={}): | |
200 | #set the global ui for hgserve instance passed |
|
209 | #set the global ui for hgserve instance passed | |
201 | hgserve.repo.ui = self.baseui |
|
210 | hgserve.repo.ui = self.baseui | |
202 |
|
211 | |||
203 | hgrc = os.path.join(self.repo_path, '.hg', 'hgrc') |
|
212 | hgrc = os.path.join(self.repo_path, '.hg', 'hgrc') | |
|
213 | ||||
|
214 | #inject some additional parameters that will be available in ui | |||
|
215 | #for hooks | |||
|
216 | for k, v in extras.items(): | |||
|
217 | hgserve.repo.ui.setconfig('rhodecode_extras', k, v) | |||
|
218 | ||||
204 | repoui = make_ui('file', hgrc, False) |
|
219 | repoui = make_ui('file', hgrc, False) | |
205 |
|
220 | |||
206 |
|
||||
207 | if repoui: |
|
221 | if repoui: | |
208 | #overwrite our ui instance with the section from hgrc file |
|
222 | #overwrite our ui instance with the section from hgrc file | |
209 | for section in ui_sections: |
|
223 | for section in ui_sections: |
@@ -35,6 +35,7 b' from vcs.backends.base import BaseChange' | |||||
35 | from vcs.backends.git import GitRepository |
|
35 | from vcs.backends.git import GitRepository | |
36 | from vcs.backends.hg import MercurialRepository |
|
36 | from vcs.backends.hg import MercurialRepository | |
37 | from vcs.utils.lazy import LazyProperty |
|
37 | from vcs.utils.lazy import LazyProperty | |
|
38 | import traceback | |||
38 | import datetime |
|
39 | import datetime | |
39 | import logging |
|
40 | import logging | |
40 | import os |
|
41 | import os | |
@@ -77,15 +78,15 b' def action_logger(user, action, repo, ip' | |||||
77 |
|
78 | |||
78 | try: |
|
79 | try: | |
79 | if hasattr(user, 'user_id'): |
|
80 | if hasattr(user, 'user_id'): | |
80 |
user_ |
|
81 | user_obj = user | |
81 | elif isinstance(user, basestring): |
|
82 | elif isinstance(user, basestring): | |
82 |
user_ |
|
83 | user_obj = UserModel(sa).get_by_username(user, cache=False) | |
83 | else: |
|
84 | else: | |
84 | raise Exception('You have to provide user object or username') |
|
85 | raise Exception('You have to provide user object or username') | |
85 |
|
86 | |||
86 | repo_name = repo.lstrip('/') |
|
87 | repo_name = repo.lstrip('/') | |
87 | user_log = UserLog() |
|
88 | user_log = UserLog() | |
88 | user_log.user_id = user_id |
|
89 | user_log.user_id = user_obj.user_id | |
89 | user_log.action = action |
|
90 | user_log.action = action | |
90 | user_log.repository_name = repo_name |
|
91 | user_log.repository_name = repo_name | |
91 | user_log.repository = RepoModel(sa).get(repo_name, cache=False) |
|
92 | user_log.repository = RepoModel(sa).get(repo_name, cache=False) | |
@@ -95,10 +96,10 b' def action_logger(user, action, repo, ip' | |||||
95 | sa.commit() |
|
96 | sa.commit() | |
96 |
|
97 | |||
97 | log.info('Adding user %s, action %s on %s', |
|
98 | log.info('Adding user %s, action %s on %s', | |
98 | user.username, action, repo) |
|
99 | user_obj.username, action, repo) | |
99 |
except |
|
100 | except: | |
|
101 | log.error(traceback.format_exc()) | |||
100 | sa.rollback() |
|
102 | sa.rollback() | |
101 | log.error('could not log user action:%s', str(e)) |
|
|||
102 |
|
103 | |||
103 | def get_repos(path, recursive=False, initial=False): |
|
104 | def get_repos(path, recursive=False, initial=False): | |
104 | """ |
|
105 | """ |
General Comments 0
You need to be logged in to leave comments.
Login now