##// END OF EJS Templates
acl: support evolve subcommands when checking for permissions.
marcink -
r3229:a91339bd default
parent child Browse files
Show More
@@ -1,152 +1,157 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2018 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 """
22 22 SimpleHG middleware for handling mercurial protocol request
23 23 (push/clone etc.). It's implemented with basic auth function
24 24 """
25 25
26 26 import logging
27 27 import urlparse
28 28 import urllib
29 29
30 30 from rhodecode.lib import utils
31 31 from rhodecode.lib.ext_json import json
32 32 from rhodecode.lib.middleware import simplevcs
33 33
34 34 log = logging.getLogger(__name__)
35 35
36 36
37 37 class SimpleHg(simplevcs.SimpleVCS):
38 38
39 39 SCM = 'hg'
40 40
41 41 def _get_repository_name(self, environ):
42 42 """
43 43 Gets repository name out of PATH_INFO header
44 44
45 45 :param environ: environ where PATH_INFO is stored
46 46 """
47 47 return environ['PATH_INFO'].strip('/')
48 48
49 49 _ACTION_MAPPING = {
50 50 'changegroup': 'pull',
51 51 'changegroupsubset': 'pull',
52 52 'getbundle': 'pull',
53 53 'stream_out': 'pull',
54 54 'listkeys': 'pull',
55 55 'between': 'pull',
56 56 'branchmap': 'pull',
57 57 'branches': 'pull',
58 58 'clonebundles': 'pull',
59 59 'capabilities': 'pull',
60 60 'debugwireargs': 'pull',
61 61 'heads': 'pull',
62 62 'lookup': 'pull',
63 63 'hello': 'pull',
64 64 'known': 'pull',
65 65
66 66 # largefiles
67 67 'putlfile': 'push',
68 68 'getlfile': 'pull',
69 69 'statlfile': 'pull',
70 70 'lheads': 'pull',
71 71
72 # evolve
73 'evoext_obshashrange_v1': 'pull',
74 'evoext_obshash': 'pull',
75 'evoext_obshash1': 'pull',
76
72 77 'unbundle': 'push',
73 78 'pushkey': 'push',
74 79 }
75 80
76 81 @classmethod
77 82 def _get_xarg_headers(cls, environ):
78 83 i = 1
79 84 chunks = [] # gather chunks stored in multiple 'hgarg_N'
80 85 while True:
81 86 head = environ.get('HTTP_X_HGARG_{}'.format(i))
82 87 if not head:
83 88 break
84 89 i += 1
85 90 chunks.append(urllib.unquote_plus(head))
86 91 full_arg = ''.join(chunks)
87 92 pref = 'cmds='
88 93 if full_arg.startswith(pref):
89 94 # strip the cmds= header defining our batch commands
90 95 full_arg = full_arg[len(pref):]
91 96 cmds = full_arg.split(';')
92 97 return cmds
93 98
94 99 @classmethod
95 100 def _get_batch_cmd(cls, environ):
96 101 """
97 102 Handle batch command send commands. Those are ';' separated commands
98 103 sent by batch command that server needs to execute. We need to extract
99 104 those, and map them to our ACTION_MAPPING to get all push/pull commands
100 105 specified in the batch
101 106 """
102 107 default = 'push'
103 108 batch_cmds = []
104 109 try:
105 110 cmds = cls._get_xarg_headers(environ)
106 111 for pair in cmds:
107 112 parts = pair.split(' ', 1)
108 113 if len(parts) != 2:
109 114 continue
110 115 # entry should be in a format `key ARGS`
111 116 cmd, args = parts
112 117 action = cls._ACTION_MAPPING.get(cmd, default)
113 118 batch_cmds.append(action)
114 119 except Exception:
115 120 log.exception('Failed to extract batch commands operations')
116 121
117 122 # in case we failed, (e.g malformed data) assume it's PUSH sub-command
118 123 # for safety
119 124 return batch_cmds or [default]
120 125
121 126 def _get_action(self, environ):
122 127 """
123 128 Maps mercurial request commands into a pull or push command.
124 129 In case of unknown/unexpected data, it returns 'push' to be safe.
125 130
126 131 :param environ:
127 132 """
128 133 default = 'push'
129 134 query = urlparse.parse_qs(environ['QUERY_STRING'],
130 135 keep_blank_values=True)
131 136
132 137 if 'cmd' in query:
133 138 cmd = query['cmd'][0]
134 139 if cmd == 'batch':
135 140 cmds = self._get_batch_cmd(environ)
136 141 if 'push' in cmds:
137 142 return 'push'
138 143 else:
139 144 return 'pull'
140 145 return self._ACTION_MAPPING.get(cmd, default)
141 146
142 147 return default
143 148
144 149 def _create_wsgi_app(self, repo_path, repo_name, config):
145 150 return self.scm_app.create_hg_wsgi_app(
146 151 repo_path, repo_name, config)
147 152
148 153 def _create_config(self, extras, repo_name):
149 154 config = utils.make_db_config(repo=repo_name)
150 155 config.set('rhodecode', 'RC_SCM_DATA', json.dumps(extras))
151 156
152 157 return config.serialize()
General Comments 0
You need to be logged in to leave comments. Login now