Show More
@@ -4,7 +4,7 b' from functools import wraps' | |||||
4 | from pylons import session, url |
|
4 | from pylons import session, url | |
5 | from pylons.controllers.util import abort, redirect |
|
5 | from pylons.controllers.util import abort, redirect | |
6 | from pylons_app.model import meta |
|
6 | from pylons_app.model import meta | |
7 |
from pylons_app.model.db import Users |
|
7 | from pylons_app.model.db import Users | |
8 | from sqlalchemy.exc import OperationalError |
|
8 | from sqlalchemy.exc import OperationalError | |
9 | from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound |
|
9 | from sqlalchemy.orm.exc import NoResultFound, MultipleResultsFound | |
10 | import crypt |
|
10 | import crypt | |
@@ -31,28 +31,6 b' def authfunc(environ, username, password' | |||||
31 | if user.active: |
|
31 | if user.active: | |
32 | if user.username == username and user.password == password_crypt: |
|
32 | if user.username == username and user.password == password_crypt: | |
33 | log.info('user %s authenticated correctly', username) |
|
33 | log.info('user %s authenticated correctly', username) | |
34 | if environ: |
|
|||
35 | http_accept = environ.get('HTTP_ACCEPT') |
|
|||
36 |
|
||||
37 | if http_accept.startswith('application/mercurial') or \ |
|
|||
38 | environ['PATH_INFO'].find('raw-file') != -1: |
|
|||
39 | repo = environ['PATH_INFO'] |
|
|||
40 | for qry in environ['QUERY_STRING'].split('&'): |
|
|||
41 | if qry.startswith('cmd'): |
|
|||
42 |
|
||||
43 | try: |
|
|||
44 | user_log = UserLogs() |
|
|||
45 | user_log.user_id = user.user_id |
|
|||
46 | user_log.action = qry |
|
|||
47 | user_log.repository = repo |
|
|||
48 | user_log.action_date = datetime.now() |
|
|||
49 | sa.add(user_log) |
|
|||
50 | sa.commit() |
|
|||
51 | log.info('Adding user %s, action %s', username, qry) |
|
|||
52 | except Exception as e: |
|
|||
53 | sa.rollback() |
|
|||
54 | log.error(e) |
|
|||
55 |
|
||||
56 | return True |
|
34 | return True | |
57 | else: |
|
35 | else: | |
58 | log.error('user %s is disabled', username) |
|
36 | log.error('user %s is disabled', username) |
@@ -10,16 +10,19 b' Created on 2010-04-28' | |||||
10 | SimpleHG middleware for handling mercurial protocol request (push/clone etc.) |
|
10 | SimpleHG middleware for handling mercurial protocol request (push/clone etc.) | |
11 | It's implemented with basic auth function |
|
11 | It's implemented with basic auth function | |
12 | """ |
|
12 | """ | |
13 |
|
13 | from datetime import datetime | ||
14 | from mercurial.hgweb import hgweb |
|
14 | from mercurial.hgweb import hgweb | |
15 | from mercurial.hgweb.request import wsgiapplication |
|
15 | from mercurial.hgweb.request import wsgiapplication | |
16 | from paste.auth.basic import AuthBasicAuthenticator |
|
16 | from paste.auth.basic import AuthBasicAuthenticator | |
17 | from paste.httpheaders import REMOTE_USER, AUTH_TYPE |
|
17 | from paste.httpheaders import REMOTE_USER, AUTH_TYPE | |
18 | from pylons_app.lib.utils import is_mercurial |
|
|||
19 | from pylons_app.lib.auth import authfunc |
|
18 | from pylons_app.lib.auth import authfunc | |
20 | from pylons_app.lib.utils import make_ui, invalidate_cache |
|
19 | from pylons_app.lib.utils import is_mercurial, make_ui, invalidate_cache | |
|
20 | from pylons_app.model import meta | |||
|
21 | from pylons_app.model.db import UserLogs, Users | |||
21 | from webob.exc import HTTPNotFound |
|
22 | from webob.exc import HTTPNotFound | |
|
23 | import logging | |||
22 | import os |
|
24 | import os | |
|
25 | log = logging.getLogger(__name__) | |||
23 |
|
26 | |||
24 | class SimpleHg(object): |
|
27 | class SimpleHg(object): | |
25 |
|
28 | |||
@@ -58,21 +61,70 b' class SimpleHg(object):' | |||||
58 | .replace('*', '') |
|
61 | .replace('*', '') | |
59 | self.repo_path = os.path.join(self.basepath, repo_name) |
|
62 | self.repo_path = os.path.join(self.basepath, repo_name) | |
60 | try: |
|
63 | try: | |
61 | app = wsgiapplication(self._make_app) |
|
64 | app = wsgiapplication(self.__make_app) | |
62 | except Exception as e: |
|
65 | except Exception as e: | |
63 | return HTTPNotFound()(environ, start_response) |
|
66 | return HTTPNotFound()(environ, start_response) | |
64 |
|
67 | |||
65 | """we know that some change was made to repositories and we should |
|
68 | action = self.__get_action(environ) | |
66 |
|
|
69 | #invalidate cache on push | |
67 | invalidate_cache('full_changelog', repo_name) |
|
70 | if action == 'push': | |
68 |
invalidate_cache( |
|
71 | self.__invalidate_cache(repo_name) | |
|
72 | ||||
|
73 | if action: | |||
|
74 | username = self.__get_environ_user(environ) | |||
|
75 | self.__log_user_action(username, action, repo_name) | |||
69 | return app(environ, start_response) |
|
76 | return app(environ, start_response) | |
70 |
|
77 | |||
71 | def _make_app(self): |
|
78 | def __make_app(self): | |
72 | hgserve = hgweb(self.repo_path) |
|
79 | hgserve = hgweb(self.repo_path) | |
73 | return self.load_web_settings(hgserve) |
|
80 | return self.load_web_settings(hgserve) | |
|
81 | ||||
|
82 | def __get_environ_user(self, environ): | |||
|
83 | return environ.get('REMOTE_USER') | |||
74 |
|
84 | |||
75 |
|
85 | def __get_action(self, environ): | ||
|
86 | """ | |||
|
87 | Maps mercurial request commands into a pull or push command. | |||
|
88 | @param environ: | |||
|
89 | """ | |||
|
90 | mapping = { | |||
|
91 | 'changegroup': 'pull', | |||
|
92 | 'changegroupsubset': 'pull', | |||
|
93 | 'unbundle': 'push', | |||
|
94 | 'stream_out': 'pull', | |||
|
95 | } | |||
|
96 | for qry in environ['QUERY_STRING'].split('&'): | |||
|
97 | if qry.startswith('cmd'): | |||
|
98 | cmd = qry.split('=')[-1] | |||
|
99 | if mapping.has_key(cmd): | |||
|
100 | return mapping[cmd] | |||
|
101 | ||||
|
102 | def __log_user_action(self, username, action, repo): | |||
|
103 | sa = meta.Session | |||
|
104 | try: | |||
|
105 | user = sa.query(Users)\ | |||
|
106 | .filter(Users.username == username).one() | |||
|
107 | user_log = UserLogs() | |||
|
108 | user_log.user_id = user.user_id | |||
|
109 | user_log.action = action | |||
|
110 | user_log.repository = repo.replace('/', '') | |||
|
111 | user_log.action_date = datetime.now() | |||
|
112 | sa.add(user_log) | |||
|
113 | sa.commit() | |||
|
114 | log.info('Adding user %s, action %s on %s', | |||
|
115 | username, action, repo) | |||
|
116 | except Exception as e: | |||
|
117 | sa.rollback() | |||
|
118 | log.error('could not log user action:%s', str(e)) | |||
|
119 | ||||
|
120 | def __invalidate_cache(self, repo_name): | |||
|
121 | """we know that some change was made to repositories and we should | |||
|
122 | invalidate the cache to see the changes right away but only for | |||
|
123 | push requests""" | |||
|
124 | invalidate_cache('cached_repo_list') | |||
|
125 | invalidate_cache('full_changelog', repo_name) | |||
|
126 | ||||
|
127 | ||||
76 | def load_web_settings(self, hgserve): |
|
128 | def load_web_settings(self, hgserve): | |
77 | repoui = make_ui(os.path.join(self.repo_path, '.hg', 'hgrc'), False) |
|
129 | repoui = make_ui(os.path.join(self.repo_path, '.hg', 'hgrc'), False) | |
78 | #set the global ui for hgserve |
|
130 | #set the global ui for hgserve |
@@ -108,7 +108,7 b' def invalidate_cache(name, *args):' | |||||
108 | region_invalidate(_get_repos_cached, None, *args) |
|
108 | region_invalidate(_get_repos_cached, None, *args) | |
109 |
|
109 | |||
110 | if name == 'full_changelog': |
|
110 | if name == 'full_changelog': | |
111 |
from pylons_app. |
|
111 | from pylons_app.lib.base import _full_changelog_cached | |
112 | region_invalidate(_full_changelog_cached, None, *args) |
|
112 | region_invalidate(_full_changelog_cached, None, *args) | |
113 |
|
113 | |||
114 | from vcs.backends.base import BaseChangeset |
|
114 | from vcs.backends.base import BaseChangeset |
General Comments 0
You need to be logged in to leave comments.
Login now