##// END OF EJS Templates
dirty fix for https working.
marcink -
r203:be6d8aad default
parent child Browse files
Show More
@@ -1,70 +1,69
1 1 """Pylons middleware initialization"""
2 2 from beaker.middleware import SessionMiddleware
3 3 from paste.cascade import Cascade
4 4 from paste.registry import RegistryManager
5 5 from paste.urlparser import StaticURLParser
6 6 from paste.deploy.converters import asbool
7 7 from pylons.middleware import ErrorHandler, StatusCodeRedirect
8 8 from pylons.wsgiapp import PylonsApp
9 9 from routes.middleware import RoutesMiddleware
10 from paste.auth.basic import AuthBasicHandler
11 10 from pylons_app.lib.simplehg import SimpleHg
12 11 from pylons_app.config.environment import load_environment
13 12
14 13 def make_app(global_conf, full_stack=True, static_files=True, **app_conf):
15 14 """Create a Pylons WSGI application and return it
16 15
17 16 ``global_conf``
18 17 The inherited configuration for this application. Normally from
19 18 the [DEFAULT] section of the Paste ini file.
20 19
21 20 ``full_stack``
22 21 Whether or not this application provides a full WSGI stack (by
23 22 default, meaning it handles its own exceptions and errors).
24 23 Disable full_stack when this application is "managed" by
25 24 another WSGI middleware.
26 25
27 26 ``app_conf``
28 27 The application's local configuration. Normally specified in
29 28 the [app:<name>] section of the Paste ini file (where <name>
30 29 defaults to main).
31 30
32 31 """
33 32 # Configure the Pylons environment
34 33 config = load_environment(global_conf, app_conf)
35 34
36 35
37 36 # The Pylons WSGI app
38 37 app = PylonsApp(config=config)
39 38
40 39
41 40 # Routing/Session/Cache Middleware
42 41 app = RoutesMiddleware(app, config['routes.map'])
43 42 app = SessionMiddleware(app, config)
44 43
45 44 # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares)
46 45 app = SimpleHg(app, config)
47 46
48 47 if asbool(full_stack):
49 48 # Handle Python exceptions
50 49 app = ErrorHandler(app, global_conf, **config['pylons.errorware'])
51 50
52 51 # Display error documents for 401, 403, 404 status codes (and
53 52 # 500 when debug is disabled)
54 53 if asbool(config['debug']):
55 54 app = StatusCodeRedirect(app)
56 55 else:
57 56 app = StatusCodeRedirect(app, [400, 401, 403, 404, 500])
58 57
59 58 # Establish the Registry for this application
60 59 app = RegistryManager(app)
61 60
62 61 if asbool(static_files):
63 62 # Serve static files
64 63 static_app = StaticURLParser(config['pylons.paths']['static_files'])
65 64 app = Cascade([static_app, app])
66 65
67 66 app.config = config
68 67
69 68 return app
70 69
@@ -1,139 +1,141
1 1 #!/usr/bin/env python
2 2 # encoding: utf-8
3 3 #
4 4 # Copyright (c) 2010 marcink. All rights reserved.
5 5 #
6 6 """
7 7 Created on 2010-04-28
8 8
9 9 @author: marcink
10 10 SimpleHG middleware for handling mercurial protocol request (push/clone etc.)
11 11 It's implemented with basic auth function
12 12 """
13 13 from datetime import datetime
14 14 from mercurial.hgweb import hgweb
15 15 from mercurial.hgweb.request import wsgiapplication
16 16 from paste.auth.basic import AuthBasicAuthenticator
17 17 from paste.httpheaders import REMOTE_USER, AUTH_TYPE
18 18 from pylons_app.lib.auth import authfunc
19 19 from pylons_app.lib.utils import is_mercurial, make_ui, invalidate_cache
20 20 from pylons_app.model import meta
21 21 from pylons_app.model.db import UserLogs, Users
22 22 from webob.exc import HTTPNotFound
23 23 import logging
24 24 import os
25 25 log = logging.getLogger(__name__)
26 26
27 27 class SimpleHg(object):
28 28
29 29 def __init__(self, application, config):
30 30 self.application = application
31 31 self.config = config
32 32 #authenticate this mercurial request using
33 33 realm = '%s %s' % (config['hg_app_name'], 'mercurial repository')
34 34 self.authenticate = AuthBasicAuthenticator(realm, authfunc)
35 35
36 36 def __call__(self, environ, start_response):
37 #dirty fix for https
38 environ['wsgi.url_scheme'] = 'https'
37 39 if not is_mercurial(environ):
38 40 return self.application(environ, start_response)
39 41 else:
40 42 #===================================================================
41 43 # AUTHENTICATE THIS MERCURIAL REQUEST
42 44 #===================================================================
43 45 username = REMOTE_USER(environ)
44 46 if not username:
45 47 result = self.authenticate(environ)
46 48 if isinstance(result, str):
47 49 AUTH_TYPE.update(environ, 'basic')
48 50 REMOTE_USER.update(environ, result)
49 51 else:
50 52 return result.wsgi_application(environ, start_response)
51 53
52 54 try:
53 55 repo_name = environ['PATH_INFO'].split('/')[1]
54 56 except:
55 57 return HTTPNotFound()(environ, start_response)
56 58
57 59 #since we wrap into hgweb, just reset the path
58 60 environ['PATH_INFO'] = '/'
59 61 self.baseui = make_ui()
60 62 self.basepath = self.baseui.configitems('paths')[0][1]\
61 63 .replace('*', '')
62 64 self.repo_path = os.path.join(self.basepath, repo_name)
63 65 try:
64 66 app = wsgiapplication(self.__make_app)
65 67 except Exception as e:
66 68 return HTTPNotFound()(environ, start_response)
67 69
68 70 action = self.__get_action(environ)
69 71 #invalidate cache on push
70 72 if action == 'push':
71 73 self.__invalidate_cache(repo_name)
72 74
73 75 if action:
74 76 username = self.__get_environ_user(environ)
75 77 self.__log_user_action(username, action, repo_name)
76 78 return app(environ, start_response)
77 79
78 80 def __make_app(self):
79 81 hgserve = hgweb(self.repo_path)
80 82 return self.load_web_settings(hgserve)
81 83
82 84 def __get_environ_user(self, environ):
83 85 return environ.get('REMOTE_USER')
84 86
85 87 def __get_action(self, environ):
86 88 """
87 89 Maps mercurial request commands into a pull or push command.
88 90 @param environ:
89 91 """
90 92 mapping = {
91 93 'changegroup': 'pull',
92 94 'changegroupsubset': 'pull',
93 95 'unbundle': 'push',
94 96 'stream_out': 'pull',
95 97 }
96 98 for qry in environ['QUERY_STRING'].split('&'):
97 99 if qry.startswith('cmd'):
98 100 cmd = qry.split('=')[-1]
99 101 if mapping.has_key(cmd):
100 102 return mapping[cmd]
101 103
102 104 def __log_user_action(self, username, action, repo):
103 105 sa = meta.Session
104 106 try:
105 107 user = sa.query(Users)\
106 108 .filter(Users.username == username).one()
107 109 user_log = UserLogs()
108 110 user_log.user_id = user.user_id
109 111 user_log.action = action
110 112 user_log.repository = repo.replace('/', '')
111 113 user_log.action_date = datetime.now()
112 114 sa.add(user_log)
113 115 sa.commit()
114 116 log.info('Adding user %s, action %s on %s',
115 117 username, action, repo)
116 118 except Exception as e:
117 119 sa.rollback()
118 120 log.error('could not log user action:%s', str(e))
119 121
120 122 def __invalidate_cache(self, repo_name):
121 123 """we know that some change was made to repositories and we should
122 124 invalidate the cache to see the changes right away but only for
123 125 push requests"""
124 126 invalidate_cache('cached_repo_list')
125 127 invalidate_cache('full_changelog', repo_name)
126 128
127 129
128 130 def load_web_settings(self, hgserve):
129 131 repoui = make_ui(os.path.join(self.repo_path, '.hg', 'hgrc'), False)
130 132 #set the global ui for hgserve
131 133 hgserve.repo.ui = self.baseui
132 134
133 135 if repoui:
134 136 #set the repository based config
135 137 hgserve.repo.ui = repoui
136 138
137 139 return hgserve
138 140
139 141
General Comments 0
You need to be logged in to leave comments. Login now