##// END OF EJS Templates
#48 rewrite action loggers into hooks with all changesets that are inside a push
marcink -
r654:7f5976da beta
parent child Browse files
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 user_action_mapper(ui, repo, hooktype, **kwargs)
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 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)
68 83
69 if user_log and not user_log.revision:
70 user_log.revision = str(repo['tip'])
71 sa.add(user_log)
72 sa.commit()
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 + ':'])
73 91
74 except Exception, e:
75 sa.rollback()
76 raise
77 finally:
78 meta.Session.remove()
92 revs = (str(repo[r]) for r in xrange(start, stop + 1))
93
94 action = action % ','.join(revs)
95
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 self.ipaddr = '0.0.0.0'
53 self.repository = None
54 self.username = None
55 self.action = None
52 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)
@@ -67,10 +76,14 b' class SimpleHg(object):'
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):
@@ -102,13 +116,11 b' class SimpleHg(object):'
102 116 (user, repo_name):
103 117 return HTTPForbidden()(environ, start_response)
104 118
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
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 #'listkeys': 'pull',
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,14 +205,19 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:
@@ -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_id = user.user_id
81 user_obj = user
81 82 elif isinstance(user, basestring):
82 user_id = UserModel(sa).get_by_username(user, cache=False).user_id
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 Exception, e:
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