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