Show More
The requested changes are too big and content was truncated. Show full diff
@@ -1,261 +1,269 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | # -*- coding: utf-8 -*- | |
2 |
|
2 | |||
3 | # Copyright (C) 2016-2020 RhodeCode GmbH |
|
3 | # Copyright (C) 2016-2020 RhodeCode GmbH | |
4 | # |
|
4 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
5 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
6 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
7 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
8 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
9 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
12 | # GNU General Public License for more details. | |
13 | # |
|
13 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
14 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
16 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
17 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
20 | |||
21 | import os |
|
21 | import os | |
22 | import time |
|
22 | import time | |
23 | import errno |
|
23 | import errno | |
24 | import shutil |
|
|||
25 | import hashlib |
|
24 | import hashlib | |
26 |
|
25 | |||
27 | from rhodecode.lib.ext_json import json |
|
26 | from rhodecode.lib.ext_json import json | |
28 | from rhodecode.apps.file_store import utils |
|
27 | from rhodecode.apps.file_store import utils | |
29 | from rhodecode.apps.file_store.extensions import resolve_extensions |
|
28 | from rhodecode.apps.file_store.extensions import resolve_extensions | |
30 | from rhodecode.apps.file_store.exceptions import ( |
|
29 | from rhodecode.apps.file_store.exceptions import ( | |
31 | FileNotAllowedException, FileOverSizeException) |
|
30 | FileNotAllowedException, FileOverSizeException) | |
32 |
|
31 | |||
33 | METADATA_VER = 'v1' |
|
32 | METADATA_VER = 'v1' | |
34 |
|
33 | |||
35 |
|
34 | |||
36 | def safe_make_dirs(dir_path): |
|
35 | def safe_make_dirs(dir_path): | |
37 | if not os.path.exists(dir_path): |
|
36 | if not os.path.exists(dir_path): | |
38 | try: |
|
37 | try: | |
39 | os.makedirs(dir_path) |
|
38 | os.makedirs(dir_path) | |
40 | except OSError as e: |
|
39 | except OSError as e: | |
41 | if e.errno != errno.EEXIST: |
|
40 | if e.errno != errno.EEXIST: | |
42 | raise |
|
41 | raise | |
43 | return |
|
42 | return | |
44 |
|
43 | |||
45 |
|
44 | |||
46 | class LocalFileStorage(object): |
|
45 | class LocalFileStorage(object): | |
47 |
|
46 | |||
48 | @classmethod |
|
47 | @classmethod | |
49 | def apply_counter(cls, counter, filename): |
|
48 | def apply_counter(cls, counter, filename): | |
50 | name_counted = '%d-%s' % (counter, filename) |
|
49 | name_counted = '%d-%s' % (counter, filename) | |
51 | return name_counted |
|
50 | return name_counted | |
52 |
|
51 | |||
53 | @classmethod |
|
52 | @classmethod | |
54 | def resolve_name(cls, name, directory): |
|
53 | def resolve_name(cls, name, directory): | |
55 | """ |
|
54 | """ | |
56 | Resolves a unique name and the correct path. If a filename |
|
55 | Resolves a unique name and the correct path. If a filename | |
57 | for that path already exists then a numeric prefix with values > 0 will be |
|
56 | for that path already exists then a numeric prefix with values > 0 will be | |
58 | added, for example test.jpg -> 1-test.jpg etc. initially file would have 0 prefix. |
|
57 | added, for example test.jpg -> 1-test.jpg etc. initially file would have 0 prefix. | |
59 |
|
58 | |||
60 | :param name: base name of file |
|
59 | :param name: base name of file | |
61 | :param directory: absolute directory path |
|
60 | :param directory: absolute directory path | |
62 | """ |
|
61 | """ | |
63 |
|
62 | |||
64 | counter = 0 |
|
63 | counter = 0 | |
65 | while True: |
|
64 | while True: | |
66 | name_counted = cls.apply_counter(counter, name) |
|
65 | name_counted = cls.apply_counter(counter, name) | |
67 |
|
66 | |||
68 | # sub_store prefix to optimize disk usage, e.g some_path/ab/final_file |
|
67 | # sub_store prefix to optimize disk usage, e.g some_path/ab/final_file | |
69 | sub_store = cls._sub_store_from_filename(name_counted) |
|
68 | sub_store = cls._sub_store_from_filename(name_counted) | |
70 | sub_store_path = os.path.join(directory, sub_store) |
|
69 | sub_store_path = os.path.join(directory, sub_store) | |
71 | safe_make_dirs(sub_store_path) |
|
70 | safe_make_dirs(sub_store_path) | |
72 |
|
71 | |||
73 | path = os.path.join(sub_store_path, name_counted) |
|
72 | path = os.path.join(sub_store_path, name_counted) | |
74 | if not os.path.exists(path): |
|
73 | if not os.path.exists(path): | |
75 | return name_counted, path |
|
74 | return name_counted, path | |
76 | counter += 1 |
|
75 | counter += 1 | |
77 |
|
76 | |||
78 | @classmethod |
|
77 | @classmethod | |
79 | def _sub_store_from_filename(cls, filename): |
|
78 | def _sub_store_from_filename(cls, filename): | |
80 | return filename[:2] |
|
79 | return filename[:2] | |
81 |
|
80 | |||
82 | @classmethod |
|
81 | @classmethod | |
83 | def calculate_path_hash(cls, file_path): |
|
82 | def calculate_path_hash(cls, file_path): | |
84 | """ |
|
83 | """ | |
85 | Efficient calculation of file_path sha256 sum |
|
84 | Efficient calculation of file_path sha256 sum | |
86 |
|
85 | |||
87 | :param file_path: |
|
86 | :param file_path: | |
88 | :return: sha256sum |
|
87 | :return: sha256sum | |
89 | """ |
|
88 | """ | |
90 | digest = hashlib.sha256() |
|
89 | digest = hashlib.sha256() | |
91 | with open(file_path, 'rb') as f: |
|
90 | with open(file_path, 'rb') as f: | |
92 | for chunk in iter(lambda: f.read(1024 * 100), b""): |
|
91 | for chunk in iter(lambda: f.read(1024 * 100), b""): | |
93 | digest.update(chunk) |
|
92 | digest.update(chunk) | |
94 |
|
93 | |||
95 | return digest.hexdigest() |
|
94 | return digest.hexdigest() | |
96 |
|
95 | |||
97 | def __init__(self, base_path, extension_groups=None): |
|
96 | def __init__(self, base_path, extension_groups=None): | |
98 |
|
97 | |||
99 | """ |
|
98 | """ | |
100 | Local file storage |
|
99 | Local file storage | |
101 |
|
100 | |||
102 | :param base_path: the absolute base path where uploads are stored |
|
101 | :param base_path: the absolute base path where uploads are stored | |
103 | :param extension_groups: extensions string |
|
102 | :param extension_groups: extensions string | |
104 | """ |
|
103 | """ | |
105 |
|
104 | |||
106 | extension_groups = extension_groups or ['any'] |
|
105 | extension_groups = extension_groups or ['any'] | |
107 | self.base_path = base_path |
|
106 | self.base_path = base_path | |
108 | self.extensions = resolve_extensions([], groups=extension_groups) |
|
107 | self.extensions = resolve_extensions([], groups=extension_groups) | |
109 |
|
108 | |||
110 | def __repr__(self): |
|
109 | def __repr__(self): | |
111 | return '{}@{}'.format(self.__class__, self.base_path) |
|
110 | return '{}@{}'.format(self.__class__, self.base_path) | |
112 |
|
111 | |||
113 | def store_path(self, filename): |
|
112 | def store_path(self, filename): | |
114 | """ |
|
113 | """ | |
115 | Returns absolute file path of the filename, joined to the |
|
114 | Returns absolute file path of the filename, joined to the | |
116 | base_path. |
|
115 | base_path. | |
117 |
|
116 | |||
118 | :param filename: base name of file |
|
117 | :param filename: base name of file | |
119 | """ |
|
118 | """ | |
120 | prefix_dir = '' |
|
119 | prefix_dir = '' | |
121 | if '/' in filename: |
|
120 | if '/' in filename: | |
122 | prefix_dir, filename = filename.split('/') |
|
121 | prefix_dir, filename = filename.split('/') | |
123 | sub_store = self._sub_store_from_filename(filename) |
|
122 | sub_store = self._sub_store_from_filename(filename) | |
124 | else: |
|
123 | else: | |
125 | sub_store = self._sub_store_from_filename(filename) |
|
124 | sub_store = self._sub_store_from_filename(filename) | |
126 | return os.path.join(self.base_path, prefix_dir, sub_store, filename) |
|
125 | return os.path.join(self.base_path, prefix_dir, sub_store, filename) | |
127 |
|
126 | |||
128 | def delete(self, filename): |
|
127 | def delete(self, filename): | |
129 | """ |
|
128 | """ | |
130 | Deletes the filename. Filename is resolved with the |
|
129 | Deletes the filename. Filename is resolved with the | |
131 | absolute path based on base_path. If file does not exist, |
|
130 | absolute path based on base_path. If file does not exist, | |
132 | returns **False**, otherwise **True** |
|
131 | returns **False**, otherwise **True** | |
133 |
|
132 | |||
134 | :param filename: base name of file |
|
133 | :param filename: base name of file | |
135 | """ |
|
134 | """ | |
136 | if self.exists(filename): |
|
135 | if self.exists(filename): | |
137 | os.remove(self.store_path(filename)) |
|
136 | os.remove(self.store_path(filename)) | |
138 | return True |
|
137 | return True | |
139 | return False |
|
138 | return False | |
140 |
|
139 | |||
141 | def exists(self, filename): |
|
140 | def exists(self, filename): | |
142 | """ |
|
141 | """ | |
143 | Checks if file exists. Resolves filename's absolute |
|
142 | Checks if file exists. Resolves filename's absolute | |
144 | path based on base_path. |
|
143 | path based on base_path. | |
145 |
|
144 | |||
146 | :param filename: file_uid name of file, e.g 0-f62b2b2d-9708-4079-a071-ec3f958448d4.svg |
|
145 | :param filename: file_uid name of file, e.g 0-f62b2b2d-9708-4079-a071-ec3f958448d4.svg | |
147 | """ |
|
146 | """ | |
148 | return os.path.exists(self.store_path(filename)) |
|
147 | return os.path.exists(self.store_path(filename)) | |
149 |
|
148 | |||
150 | def filename_allowed(self, filename, extensions=None): |
|
149 | def filename_allowed(self, filename, extensions=None): | |
151 | """Checks if a filename has an allowed extension |
|
150 | """Checks if a filename has an allowed extension | |
152 |
|
151 | |||
153 | :param filename: base name of file |
|
152 | :param filename: base name of file | |
154 | :param extensions: iterable of extensions (or self.extensions) |
|
153 | :param extensions: iterable of extensions (or self.extensions) | |
155 | """ |
|
154 | """ | |
156 | _, ext = os.path.splitext(filename) |
|
155 | _, ext = os.path.splitext(filename) | |
157 | return self.extension_allowed(ext, extensions) |
|
156 | return self.extension_allowed(ext, extensions) | |
158 |
|
157 | |||
159 | def extension_allowed(self, ext, extensions=None): |
|
158 | def extension_allowed(self, ext, extensions=None): | |
160 | """ |
|
159 | """ | |
161 | Checks if an extension is permitted. Both e.g. ".jpg" and |
|
160 | Checks if an extension is permitted. Both e.g. ".jpg" and | |
162 | "jpg" can be passed in. Extension lookup is case-insensitive. |
|
161 | "jpg" can be passed in. Extension lookup is case-insensitive. | |
163 |
|
162 | |||
164 | :param ext: extension to check |
|
163 | :param ext: extension to check | |
165 | :param extensions: iterable of extensions to validate against (or self.extensions) |
|
164 | :param extensions: iterable of extensions to validate against (or self.extensions) | |
166 | """ |
|
165 | """ | |
167 | def normalize_ext(_ext): |
|
166 | def normalize_ext(_ext): | |
168 | if _ext.startswith('.'): |
|
167 | if _ext.startswith('.'): | |
169 | _ext = _ext[1:] |
|
168 | _ext = _ext[1:] | |
170 | return _ext.lower() |
|
169 | return _ext.lower() | |
171 |
|
170 | |||
172 | extensions = extensions or self.extensions |
|
171 | extensions = extensions or self.extensions | |
173 | if not extensions: |
|
172 | if not extensions: | |
174 | return True |
|
173 | return True | |
175 |
|
174 | |||
176 | ext = normalize_ext(ext) |
|
175 | ext = normalize_ext(ext) | |
177 |
|
176 | |||
178 | return ext in [normalize_ext(x) for x in extensions] |
|
177 | return ext in [normalize_ext(x) for x in extensions] | |
179 |
|
178 | |||
180 | def save_file(self, file_obj, filename, directory=None, extensions=None, |
|
179 | def save_file(self, file_obj, filename, directory=None, extensions=None, | |
181 | extra_metadata=None, max_filesize=None, randomized_name=True, **kwargs): |
|
180 | extra_metadata=None, max_filesize=None, randomized_name=True, **kwargs): | |
182 | """ |
|
181 | """ | |
183 | Saves a file object to the uploads location. |
|
182 | Saves a file object to the uploads location. | |
184 | Returns the resolved filename, i.e. the directory + |
|
183 | Returns the resolved filename, i.e. the directory + | |
185 | the (randomized/incremented) base name. |
|
184 | the (randomized/incremented) base name. | |
186 |
|
185 | |||
187 | :param file_obj: **cgi.FieldStorage** object (or similar) |
|
186 | :param file_obj: **cgi.FieldStorage** object (or similar) | |
188 | :param filename: original filename |
|
187 | :param filename: original filename | |
189 | :param directory: relative path of sub-directory |
|
188 | :param directory: relative path of sub-directory | |
190 | :param extensions: iterable of allowed extensions, if not default |
|
189 | :param extensions: iterable of allowed extensions, if not default | |
191 | :param max_filesize: maximum size of file that should be allowed |
|
190 | :param max_filesize: maximum size of file that should be allowed | |
192 | :param randomized_name: generate random generated UID or fixed based on the filename |
|
191 | :param randomized_name: generate random generated UID or fixed based on the filename | |
193 | :param extra_metadata: extra JSON metadata to store next to the file with .meta suffix |
|
192 | :param extra_metadata: extra JSON metadata to store next to the file with .meta suffix | |
194 |
|
193 | |||
195 | """ |
|
194 | """ | |
196 |
|
195 | |||
197 | extensions = extensions or self.extensions |
|
196 | extensions = extensions or self.extensions | |
198 |
|
197 | |||
199 | if not self.filename_allowed(filename, extensions): |
|
198 | if not self.filename_allowed(filename, extensions): | |
200 | raise FileNotAllowedException() |
|
199 | raise FileNotAllowedException() | |
201 |
|
200 | |||
202 | if directory: |
|
201 | if directory: | |
203 | dest_directory = os.path.join(self.base_path, directory) |
|
202 | dest_directory = os.path.join(self.base_path, directory) | |
204 | else: |
|
203 | else: | |
205 | dest_directory = self.base_path |
|
204 | dest_directory = self.base_path | |
206 |
|
205 | |||
207 | safe_make_dirs(dest_directory) |
|
206 | safe_make_dirs(dest_directory) | |
208 |
|
207 | |||
209 | uid_filename = utils.uid_filename(filename, randomized=randomized_name) |
|
208 | uid_filename = utils.uid_filename(filename, randomized=randomized_name) | |
210 |
|
209 | |||
211 | # resolve also produces special sub-dir for file optimized store |
|
210 | # resolve also produces special sub-dir for file optimized store | |
212 | filename, path = self.resolve_name(uid_filename, dest_directory) |
|
211 | filename, path = self.resolve_name(uid_filename, dest_directory) | |
213 | stored_file_dir = os.path.dirname(path) |
|
212 | stored_file_dir = os.path.dirname(path) | |
214 |
|
213 | |||
215 | file_obj.seek(0) |
|
214 | no_body_seek = kwargs.pop('no_body_seek', False) | |
|
215 | if no_body_seek: | |||
|
216 | pass | |||
|
217 | else: | |||
|
218 | file_obj.seek(0) | |||
216 |
|
219 | |||
217 | with open(path, "wb") as dest: |
|
220 | with open(path, "wb") as dest: | |
218 | shutil.copyfileobj(file_obj, dest) |
|
221 | length = 256 * 1024 | |
|
222 | while 1: | |||
|
223 | buf = file_obj.read(length) | |||
|
224 | if not buf: | |||
|
225 | break | |||
|
226 | dest.write(buf) | |||
219 |
|
227 | |||
220 | metadata = {} |
|
228 | metadata = {} | |
221 | if extra_metadata: |
|
229 | if extra_metadata: | |
222 | metadata = extra_metadata |
|
230 | metadata = extra_metadata | |
223 |
|
231 | |||
224 | size = os.stat(path).st_size |
|
232 | size = os.stat(path).st_size | |
225 |
|
233 | |||
226 | if max_filesize and size > max_filesize: |
|
234 | if max_filesize and size > max_filesize: | |
227 | # free up the copied file, and raise exc |
|
235 | # free up the copied file, and raise exc | |
228 | os.remove(path) |
|
236 | os.remove(path) | |
229 | raise FileOverSizeException() |
|
237 | raise FileOverSizeException() | |
230 |
|
238 | |||
231 | file_hash = self.calculate_path_hash(path) |
|
239 | file_hash = self.calculate_path_hash(path) | |
232 |
|
240 | |||
233 | metadata.update({ |
|
241 | metadata.update({ | |
234 | "filename": filename, |
|
242 | "filename": filename, | |
235 | "size": size, |
|
243 | "size": size, | |
236 | "time": time.time(), |
|
244 | "time": time.time(), | |
237 | "sha256": file_hash, |
|
245 | "sha256": file_hash, | |
238 | "meta_ver": METADATA_VER |
|
246 | "meta_ver": METADATA_VER | |
239 | }) |
|
247 | }) | |
240 |
|
248 | |||
241 | filename_meta = filename + '.meta' |
|
249 | filename_meta = filename + '.meta' | |
242 | with open(os.path.join(stored_file_dir, filename_meta), "wb") as dest_meta: |
|
250 | with open(os.path.join(stored_file_dir, filename_meta), "wb") as dest_meta: | |
243 | dest_meta.write(json.dumps(metadata)) |
|
251 | dest_meta.write(json.dumps(metadata)) | |
244 |
|
252 | |||
245 | if directory: |
|
253 | if directory: | |
246 | filename = os.path.join(directory, filename) |
|
254 | filename = os.path.join(directory, filename) | |
247 |
|
255 | |||
248 | return filename, metadata |
|
256 | return filename, metadata | |
249 |
|
257 | |||
250 | def get_metadata(self, filename): |
|
258 | def get_metadata(self, filename): | |
251 | """ |
|
259 | """ | |
252 | Reads JSON stored metadata for a file |
|
260 | Reads JSON stored metadata for a file | |
253 |
|
261 | |||
254 | :param filename: |
|
262 | :param filename: | |
255 | :return: |
|
263 | :return: | |
256 | """ |
|
264 | """ | |
257 | filename = self.store_path(filename) |
|
265 | filename = self.store_path(filename) | |
258 | filename_meta = filename + '.meta' |
|
266 | filename_meta = filename + '.meta' | |
259 |
|
267 | |||
260 | with open(filename_meta, "rb") as source_meta: |
|
268 | with open(filename_meta, "rb") as source_meta: | |
261 | return json.loads(source_meta.read()) |
|
269 | return json.loads(source_meta.read()) |
@@ -1,37 +1,40 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | # -*- coding: utf-8 -*- | |
2 |
|
2 | |||
3 | # Copyright (C) 2010-2020 RhodeCode GmbH |
|
3 | # Copyright (C) 2010-2020 RhodeCode GmbH | |
4 | # |
|
4 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
5 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
6 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
7 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
8 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
9 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
12 | # GNU General Public License for more details. | |
13 | # |
|
13 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
14 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
16 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
17 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
20 | |||
21 | from rhodecode.lib.ext_json import json |
|
21 | from rhodecode.lib.ext_json import json | |
22 |
|
22 | |||
23 |
|
23 | |||
24 | def pyramid_ext_json(info): |
|
24 | def pyramid_ext_json(info): | |
25 | """ |
|
25 | """ | |
26 | Custom json renderer for pyramid to use our ext_json lib |
|
26 | Custom json renderer for pyramid to use our ext_json lib | |
27 | """ |
|
27 | """ | |
28 | def _render(value, system): |
|
28 | def _render(value, system): | |
29 | request = system.get('request') |
|
29 | request = system.get('request') | |
|
30 | indent = None | |||
30 | if request is not None: |
|
31 | if request is not None: | |
31 | response = request.response |
|
32 | response = request.response | |
32 | ct = response.content_type |
|
33 | ct = response.content_type | |
33 | if ct == response.default_content_type: |
|
34 | if ct == response.default_content_type: | |
34 | response.content_type = 'application/json' |
|
35 | response.content_type = 'application/json' | |
35 | return json.dumps(value) |
|
36 | indent = getattr(request, 'ext_json_indent', None) | |
|
37 | ||||
|
38 | return json.dumps(value, indent=indent) | |||
36 |
|
39 | |||
37 | return _render |
|
40 | return _render |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
@@ -1,884 +1,887 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | # -*- coding: utf-8 -*- | |
2 |
|
2 | |||
3 | # Copyright (C) 2011-2020 RhodeCode GmbH |
|
3 | # Copyright (C) 2011-2020 RhodeCode GmbH | |
4 | # |
|
4 | # | |
5 | # This program is free software: you can redistribute it and/or modify |
|
5 | # This program is free software: you can redistribute it and/or modify | |
6 | # it under the terms of the GNU Affero General Public License, version 3 |
|
6 | # it under the terms of the GNU Affero General Public License, version 3 | |
7 | # (only), as published by the Free Software Foundation. |
|
7 | # (only), as published by the Free Software Foundation. | |
8 | # |
|
8 | # | |
9 | # This program is distributed in the hope that it will be useful, |
|
9 | # This program is distributed in the hope that it will be useful, | |
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | # GNU General Public License for more details. |
|
12 | # GNU General Public License for more details. | |
13 | # |
|
13 | # | |
14 | # You should have received a copy of the GNU Affero General Public License |
|
14 | # You should have received a copy of the GNU Affero General Public License | |
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
15 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
16 | # |
|
16 | # | |
17 | # This program is dual-licensed. If you wish to learn more about the |
|
17 | # This program is dual-licensed. If you wish to learn more about the | |
18 | # RhodeCode Enterprise Edition, including its added features, Support services, |
|
18 | # RhodeCode Enterprise Edition, including its added features, Support services, | |
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ |
|
19 | # and proprietary license terms, please see https://rhodecode.com/licenses/ | |
20 |
|
20 | |||
21 |
|
21 | |||
22 | """ |
|
22 | """ | |
23 | repo group model for RhodeCode |
|
23 | repo group model for RhodeCode | |
24 | """ |
|
24 | """ | |
25 |
|
25 | |||
26 | import os |
|
26 | import os | |
27 | import datetime |
|
27 | import datetime | |
28 | import itertools |
|
28 | import itertools | |
29 | import logging |
|
29 | import logging | |
30 | import shutil |
|
30 | import shutil | |
31 | import time |
|
31 | import time | |
32 | import traceback |
|
32 | import traceback | |
33 | import string |
|
33 | import string | |
34 |
|
34 | |||
35 | from zope.cachedescriptors.property import Lazy as LazyProperty |
|
35 | from zope.cachedescriptors.property import Lazy as LazyProperty | |
36 |
|
36 | |||
37 | from rhodecode import events |
|
37 | from rhodecode import events | |
38 | from rhodecode.model import BaseModel |
|
38 | from rhodecode.model import BaseModel | |
39 | from rhodecode.model.db import (_hash_key, func, or_, in_filter_generator, |
|
39 | from rhodecode.model.db import (_hash_key, func, or_, in_filter_generator, | |
40 | Session, RepoGroup, UserRepoGroupToPerm, User, Permission, UserGroupRepoGroupToPerm, |
|
40 | Session, RepoGroup, UserRepoGroupToPerm, User, Permission, UserGroupRepoGroupToPerm, | |
41 | UserGroup, Repository) |
|
41 | UserGroup, Repository) | |
42 | from rhodecode.model.settings import VcsSettingsModel, SettingsModel |
|
42 | from rhodecode.model.settings import VcsSettingsModel, SettingsModel | |
43 | from rhodecode.lib.caching_query import FromCache |
|
43 | from rhodecode.lib.caching_query import FromCache | |
44 | from rhodecode.lib.utils2 import action_logger_generic |
|
44 | from rhodecode.lib.utils2 import action_logger_generic | |
45 |
|
45 | |||
46 | log = logging.getLogger(__name__) |
|
46 | log = logging.getLogger(__name__) | |
47 |
|
47 | |||
48 |
|
48 | |||
49 | class RepoGroupModel(BaseModel): |
|
49 | class RepoGroupModel(BaseModel): | |
50 |
|
50 | |||
51 | cls = RepoGroup |
|
51 | cls = RepoGroup | |
52 | PERSONAL_GROUP_DESC = 'personal repo group of user `%(username)s`' |
|
52 | PERSONAL_GROUP_DESC = 'personal repo group of user `%(username)s`' | |
53 | PERSONAL_GROUP_PATTERN = '${username}' # default |
|
53 | PERSONAL_GROUP_PATTERN = '${username}' # default | |
54 |
|
54 | |||
55 | def _get_user_group(self, users_group): |
|
55 | def _get_user_group(self, users_group): | |
56 | return self._get_instance(UserGroup, users_group, |
|
56 | return self._get_instance(UserGroup, users_group, | |
57 | callback=UserGroup.get_by_group_name) |
|
57 | callback=UserGroup.get_by_group_name) | |
58 |
|
58 | |||
59 | def _get_repo_group(self, repo_group): |
|
59 | def _get_repo_group(self, repo_group): | |
60 | return self._get_instance(RepoGroup, repo_group, |
|
60 | return self._get_instance(RepoGroup, repo_group, | |
61 | callback=RepoGroup.get_by_group_name) |
|
61 | callback=RepoGroup.get_by_group_name) | |
62 |
|
62 | |||
|
63 | def get_repo_group(self, repo_group): | |||
|
64 | return self._get_repo_group(repo_group) | |||
|
65 | ||||
63 | @LazyProperty |
|
66 | @LazyProperty | |
64 | def repos_path(self): |
|
67 | def repos_path(self): | |
65 | """ |
|
68 | """ | |
66 | Gets the repositories root path from database |
|
69 | Gets the repositories root path from database | |
67 | """ |
|
70 | """ | |
68 |
|
71 | |||
69 | settings_model = VcsSettingsModel(sa=self.sa) |
|
72 | settings_model = VcsSettingsModel(sa=self.sa) | |
70 | return settings_model.get_repos_location() |
|
73 | return settings_model.get_repos_location() | |
71 |
|
74 | |||
72 | def get_by_group_name(self, repo_group_name, cache=None): |
|
75 | def get_by_group_name(self, repo_group_name, cache=None): | |
73 | repo = self.sa.query(RepoGroup) \ |
|
76 | repo = self.sa.query(RepoGroup) \ | |
74 | .filter(RepoGroup.group_name == repo_group_name) |
|
77 | .filter(RepoGroup.group_name == repo_group_name) | |
75 |
|
78 | |||
76 | if cache: |
|
79 | if cache: | |
77 | name_key = _hash_key(repo_group_name) |
|
80 | name_key = _hash_key(repo_group_name) | |
78 | repo = repo.options( |
|
81 | repo = repo.options( | |
79 | FromCache("sql_cache_short", "get_repo_group_%s" % name_key)) |
|
82 | FromCache("sql_cache_short", "get_repo_group_%s" % name_key)) | |
80 | return repo.scalar() |
|
83 | return repo.scalar() | |
81 |
|
84 | |||
82 | def get_default_create_personal_repo_group(self): |
|
85 | def get_default_create_personal_repo_group(self): | |
83 | value = SettingsModel().get_setting_by_name( |
|
86 | value = SettingsModel().get_setting_by_name( | |
84 | 'create_personal_repo_group') |
|
87 | 'create_personal_repo_group') | |
85 | return value.app_settings_value if value else None or False |
|
88 | return value.app_settings_value if value else None or False | |
86 |
|
89 | |||
87 | def get_personal_group_name_pattern(self): |
|
90 | def get_personal_group_name_pattern(self): | |
88 | value = SettingsModel().get_setting_by_name( |
|
91 | value = SettingsModel().get_setting_by_name( | |
89 | 'personal_repo_group_pattern') |
|
92 | 'personal_repo_group_pattern') | |
90 | val = value.app_settings_value if value else None |
|
93 | val = value.app_settings_value if value else None | |
91 | group_template = val or self.PERSONAL_GROUP_PATTERN |
|
94 | group_template = val or self.PERSONAL_GROUP_PATTERN | |
92 |
|
95 | |||
93 | group_template = group_template.lstrip('/') |
|
96 | group_template = group_template.lstrip('/') | |
94 | return group_template |
|
97 | return group_template | |
95 |
|
98 | |||
96 | def get_personal_group_name(self, user): |
|
99 | def get_personal_group_name(self, user): | |
97 | template = self.get_personal_group_name_pattern() |
|
100 | template = self.get_personal_group_name_pattern() | |
98 | return string.Template(template).safe_substitute( |
|
101 | return string.Template(template).safe_substitute( | |
99 | username=user.username, |
|
102 | username=user.username, | |
100 | user_id=user.user_id, |
|
103 | user_id=user.user_id, | |
101 | first_name=user.first_name, |
|
104 | first_name=user.first_name, | |
102 | last_name=user.last_name, |
|
105 | last_name=user.last_name, | |
103 | ) |
|
106 | ) | |
104 |
|
107 | |||
105 | def create_personal_repo_group(self, user, commit_early=True): |
|
108 | def create_personal_repo_group(self, user, commit_early=True): | |
106 | desc = self.PERSONAL_GROUP_DESC % {'username': user.username} |
|
109 | desc = self.PERSONAL_GROUP_DESC % {'username': user.username} | |
107 | personal_repo_group_name = self.get_personal_group_name(user) |
|
110 | personal_repo_group_name = self.get_personal_group_name(user) | |
108 |
|
111 | |||
109 | # create a new one |
|
112 | # create a new one | |
110 | RepoGroupModel().create( |
|
113 | RepoGroupModel().create( | |
111 | group_name=personal_repo_group_name, |
|
114 | group_name=personal_repo_group_name, | |
112 | group_description=desc, |
|
115 | group_description=desc, | |
113 | owner=user.username, |
|
116 | owner=user.username, | |
114 | personal=True, |
|
117 | personal=True, | |
115 | commit_early=commit_early) |
|
118 | commit_early=commit_early) | |
116 |
|
119 | |||
117 | def _create_default_perms(self, new_group): |
|
120 | def _create_default_perms(self, new_group): | |
118 | # create default permission |
|
121 | # create default permission | |
119 | default_perm = 'group.read' |
|
122 | default_perm = 'group.read' | |
120 | def_user = User.get_default_user() |
|
123 | def_user = User.get_default_user() | |
121 | for p in def_user.user_perms: |
|
124 | for p in def_user.user_perms: | |
122 | if p.permission.permission_name.startswith('group.'): |
|
125 | if p.permission.permission_name.startswith('group.'): | |
123 | default_perm = p.permission.permission_name |
|
126 | default_perm = p.permission.permission_name | |
124 | break |
|
127 | break | |
125 |
|
128 | |||
126 | repo_group_to_perm = UserRepoGroupToPerm() |
|
129 | repo_group_to_perm = UserRepoGroupToPerm() | |
127 | repo_group_to_perm.permission = Permission.get_by_key(default_perm) |
|
130 | repo_group_to_perm.permission = Permission.get_by_key(default_perm) | |
128 |
|
131 | |||
129 | repo_group_to_perm.group = new_group |
|
132 | repo_group_to_perm.group = new_group | |
130 | repo_group_to_perm.user_id = def_user.user_id |
|
133 | repo_group_to_perm.user_id = def_user.user_id | |
131 | return repo_group_to_perm |
|
134 | return repo_group_to_perm | |
132 |
|
135 | |||
133 | def _get_group_name_and_parent(self, group_name_full, repo_in_path=False, |
|
136 | def _get_group_name_and_parent(self, group_name_full, repo_in_path=False, | |
134 | get_object=False): |
|
137 | get_object=False): | |
135 | """ |
|
138 | """ | |
136 | Get's the group name and a parent group name from given group name. |
|
139 | Get's the group name and a parent group name from given group name. | |
137 | If repo_in_path is set to truth, we asume the full path also includes |
|
140 | If repo_in_path is set to truth, we asume the full path also includes | |
138 | repo name, in such case we clean the last element. |
|
141 | repo name, in such case we clean the last element. | |
139 |
|
142 | |||
140 | :param group_name_full: |
|
143 | :param group_name_full: | |
141 | """ |
|
144 | """ | |
142 | split_paths = 1 |
|
145 | split_paths = 1 | |
143 | if repo_in_path: |
|
146 | if repo_in_path: | |
144 | split_paths = 2 |
|
147 | split_paths = 2 | |
145 | _parts = group_name_full.rsplit(RepoGroup.url_sep(), split_paths) |
|
148 | _parts = group_name_full.rsplit(RepoGroup.url_sep(), split_paths) | |
146 |
|
149 | |||
147 | if repo_in_path and len(_parts) > 1: |
|
150 | if repo_in_path and len(_parts) > 1: | |
148 | # such case last element is the repo_name |
|
151 | # such case last element is the repo_name | |
149 | _parts.pop(-1) |
|
152 | _parts.pop(-1) | |
150 | group_name_cleaned = _parts[-1] # just the group name |
|
153 | group_name_cleaned = _parts[-1] # just the group name | |
151 | parent_repo_group_name = None |
|
154 | parent_repo_group_name = None | |
152 |
|
155 | |||
153 | if len(_parts) > 1: |
|
156 | if len(_parts) > 1: | |
154 | parent_repo_group_name = _parts[0] |
|
157 | parent_repo_group_name = _parts[0] | |
155 |
|
158 | |||
156 | parent_group = None |
|
159 | parent_group = None | |
157 | if parent_repo_group_name: |
|
160 | if parent_repo_group_name: | |
158 | parent_group = RepoGroup.get_by_group_name(parent_repo_group_name) |
|
161 | parent_group = RepoGroup.get_by_group_name(parent_repo_group_name) | |
159 |
|
162 | |||
160 | if get_object: |
|
163 | if get_object: | |
161 | return group_name_cleaned, parent_repo_group_name, parent_group |
|
164 | return group_name_cleaned, parent_repo_group_name, parent_group | |
162 |
|
165 | |||
163 | return group_name_cleaned, parent_repo_group_name |
|
166 | return group_name_cleaned, parent_repo_group_name | |
164 |
|
167 | |||
165 | def check_exist_filesystem(self, group_name, exc_on_failure=True): |
|
168 | def check_exist_filesystem(self, group_name, exc_on_failure=True): | |
166 | create_path = os.path.join(self.repos_path, group_name) |
|
169 | create_path = os.path.join(self.repos_path, group_name) | |
167 | log.debug('creating new group in %s', create_path) |
|
170 | log.debug('creating new group in %s', create_path) | |
168 |
|
171 | |||
169 | if os.path.isdir(create_path): |
|
172 | if os.path.isdir(create_path): | |
170 | if exc_on_failure: |
|
173 | if exc_on_failure: | |
171 | abs_create_path = os.path.abspath(create_path) |
|
174 | abs_create_path = os.path.abspath(create_path) | |
172 | raise Exception('Directory `{}` already exists !'.format(abs_create_path)) |
|
175 | raise Exception('Directory `{}` already exists !'.format(abs_create_path)) | |
173 | return False |
|
176 | return False | |
174 | return True |
|
177 | return True | |
175 |
|
178 | |||
176 | def _create_group(self, group_name): |
|
179 | def _create_group(self, group_name): | |
177 | """ |
|
180 | """ | |
178 | makes repository group on filesystem |
|
181 | makes repository group on filesystem | |
179 |
|
182 | |||
180 | :param repo_name: |
|
183 | :param repo_name: | |
181 | :param parent_id: |
|
184 | :param parent_id: | |
182 | """ |
|
185 | """ | |
183 |
|
186 | |||
184 | self.check_exist_filesystem(group_name) |
|
187 | self.check_exist_filesystem(group_name) | |
185 | create_path = os.path.join(self.repos_path, group_name) |
|
188 | create_path = os.path.join(self.repos_path, group_name) | |
186 | log.debug('creating new group in %s', create_path) |
|
189 | log.debug('creating new group in %s', create_path) | |
187 | os.makedirs(create_path, mode=0o755) |
|
190 | os.makedirs(create_path, mode=0o755) | |
188 | log.debug('created group in %s', create_path) |
|
191 | log.debug('created group in %s', create_path) | |
189 |
|
192 | |||
190 | def _rename_group(self, old, new): |
|
193 | def _rename_group(self, old, new): | |
191 | """ |
|
194 | """ | |
192 | Renames a group on filesystem |
|
195 | Renames a group on filesystem | |
193 |
|
196 | |||
194 | :param group_name: |
|
197 | :param group_name: | |
195 | """ |
|
198 | """ | |
196 |
|
199 | |||
197 | if old == new: |
|
200 | if old == new: | |
198 | log.debug('skipping group rename') |
|
201 | log.debug('skipping group rename') | |
199 | return |
|
202 | return | |
200 |
|
203 | |||
201 | log.debug('renaming repository group from %s to %s', old, new) |
|
204 | log.debug('renaming repository group from %s to %s', old, new) | |
202 |
|
205 | |||
203 | old_path = os.path.join(self.repos_path, old) |
|
206 | old_path = os.path.join(self.repos_path, old) | |
204 | new_path = os.path.join(self.repos_path, new) |
|
207 | new_path = os.path.join(self.repos_path, new) | |
205 |
|
208 | |||
206 | log.debug('renaming repos paths from %s to %s', old_path, new_path) |
|
209 | log.debug('renaming repos paths from %s to %s', old_path, new_path) | |
207 |
|
210 | |||
208 | if os.path.isdir(new_path): |
|
211 | if os.path.isdir(new_path): | |
209 | raise Exception('Was trying to rename to already ' |
|
212 | raise Exception('Was trying to rename to already ' | |
210 | 'existing dir %s' % new_path) |
|
213 | 'existing dir %s' % new_path) | |
211 | shutil.move(old_path, new_path) |
|
214 | shutil.move(old_path, new_path) | |
212 |
|
215 | |||
213 | def _delete_filesystem_group(self, group, force_delete=False): |
|
216 | def _delete_filesystem_group(self, group, force_delete=False): | |
214 | """ |
|
217 | """ | |
215 | Deletes a group from a filesystem |
|
218 | Deletes a group from a filesystem | |
216 |
|
219 | |||
217 | :param group: instance of group from database |
|
220 | :param group: instance of group from database | |
218 | :param force_delete: use shutil rmtree to remove all objects |
|
221 | :param force_delete: use shutil rmtree to remove all objects | |
219 | """ |
|
222 | """ | |
220 | paths = group.full_path.split(RepoGroup.url_sep()) |
|
223 | paths = group.full_path.split(RepoGroup.url_sep()) | |
221 | paths = os.sep.join(paths) |
|
224 | paths = os.sep.join(paths) | |
222 |
|
225 | |||
223 | rm_path = os.path.join(self.repos_path, paths) |
|
226 | rm_path = os.path.join(self.repos_path, paths) | |
224 | log.info("Removing group %s", rm_path) |
|
227 | log.info("Removing group %s", rm_path) | |
225 | # delete only if that path really exists |
|
228 | # delete only if that path really exists | |
226 | if os.path.isdir(rm_path): |
|
229 | if os.path.isdir(rm_path): | |
227 | if force_delete: |
|
230 | if force_delete: | |
228 | shutil.rmtree(rm_path) |
|
231 | shutil.rmtree(rm_path) | |
229 | else: |
|
232 | else: | |
230 | # archive that group` |
|
233 | # archive that group` | |
231 | _now = datetime.datetime.now() |
|
234 | _now = datetime.datetime.now() | |
232 | _ms = str(_now.microsecond).rjust(6, '0') |
|
235 | _ms = str(_now.microsecond).rjust(6, '0') | |
233 | _d = 'rm__%s_GROUP_%s' % ( |
|
236 | _d = 'rm__%s_GROUP_%s' % ( | |
234 | _now.strftime('%Y%m%d_%H%M%S_' + _ms), group.name) |
|
237 | _now.strftime('%Y%m%d_%H%M%S_' + _ms), group.name) | |
235 | shutil.move(rm_path, os.path.join(self.repos_path, _d)) |
|
238 | shutil.move(rm_path, os.path.join(self.repos_path, _d)) | |
236 |
|
239 | |||
237 | def create(self, group_name, group_description, owner, just_db=False, |
|
240 | def create(self, group_name, group_description, owner, just_db=False, | |
238 | copy_permissions=False, personal=None, commit_early=True): |
|
241 | copy_permissions=False, personal=None, commit_early=True): | |
239 |
|
242 | |||
240 | (group_name_cleaned, |
|
243 | (group_name_cleaned, | |
241 | parent_group_name) = RepoGroupModel()._get_group_name_and_parent(group_name) |
|
244 | parent_group_name) = RepoGroupModel()._get_group_name_and_parent(group_name) | |
242 |
|
245 | |||
243 | parent_group = None |
|
246 | parent_group = None | |
244 | if parent_group_name: |
|
247 | if parent_group_name: | |
245 | parent_group = self._get_repo_group(parent_group_name) |
|
248 | parent_group = self._get_repo_group(parent_group_name) | |
246 | if not parent_group: |
|
249 | if not parent_group: | |
247 | # we tried to create a nested group, but the parent is not |
|
250 | # we tried to create a nested group, but the parent is not | |
248 | # existing |
|
251 | # existing | |
249 | raise ValueError( |
|
252 | raise ValueError( | |
250 | 'Parent group `%s` given in `%s` group name ' |
|
253 | 'Parent group `%s` given in `%s` group name ' | |
251 | 'is not yet existing.' % (parent_group_name, group_name)) |
|
254 | 'is not yet existing.' % (parent_group_name, group_name)) | |
252 |
|
255 | |||
253 | # because we are doing a cleanup, we need to check if such directory |
|
256 | # because we are doing a cleanup, we need to check if such directory | |
254 | # already exists. If we don't do that we can accidentally delete |
|
257 | # already exists. If we don't do that we can accidentally delete | |
255 | # existing directory via cleanup that can cause data issues, since |
|
258 | # existing directory via cleanup that can cause data issues, since | |
256 | # delete does a folder rename to special syntax later cleanup |
|
259 | # delete does a folder rename to special syntax later cleanup | |
257 | # functions can delete this |
|
260 | # functions can delete this | |
258 | cleanup_group = self.check_exist_filesystem(group_name, |
|
261 | cleanup_group = self.check_exist_filesystem(group_name, | |
259 | exc_on_failure=False) |
|
262 | exc_on_failure=False) | |
260 | user = self._get_user(owner) |
|
263 | user = self._get_user(owner) | |
261 | if not user: |
|
264 | if not user: | |
262 | raise ValueError('Owner %s not found as rhodecode user', owner) |
|
265 | raise ValueError('Owner %s not found as rhodecode user', owner) | |
263 |
|
266 | |||
264 | try: |
|
267 | try: | |
265 | new_repo_group = RepoGroup() |
|
268 | new_repo_group = RepoGroup() | |
266 | new_repo_group.user = user |
|
269 | new_repo_group.user = user | |
267 | new_repo_group.group_description = group_description or group_name |
|
270 | new_repo_group.group_description = group_description or group_name | |
268 | new_repo_group.parent_group = parent_group |
|
271 | new_repo_group.parent_group = parent_group | |
269 | new_repo_group.group_name = group_name |
|
272 | new_repo_group.group_name = group_name | |
270 | new_repo_group.personal = personal |
|
273 | new_repo_group.personal = personal | |
271 |
|
274 | |||
272 | self.sa.add(new_repo_group) |
|
275 | self.sa.add(new_repo_group) | |
273 |
|
276 | |||
274 | # create an ADMIN permission for owner except if we're super admin, |
|
277 | # create an ADMIN permission for owner except if we're super admin, | |
275 | # later owner should go into the owner field of groups |
|
278 | # later owner should go into the owner field of groups | |
276 | if not user.is_admin: |
|
279 | if not user.is_admin: | |
277 | self.grant_user_permission(repo_group=new_repo_group, |
|
280 | self.grant_user_permission(repo_group=new_repo_group, | |
278 | user=owner, perm='group.admin') |
|
281 | user=owner, perm='group.admin') | |
279 |
|
282 | |||
280 | if parent_group and copy_permissions: |
|
283 | if parent_group and copy_permissions: | |
281 | # copy permissions from parent |
|
284 | # copy permissions from parent | |
282 | user_perms = UserRepoGroupToPerm.query() \ |
|
285 | user_perms = UserRepoGroupToPerm.query() \ | |
283 | .filter(UserRepoGroupToPerm.group == parent_group).all() |
|
286 | .filter(UserRepoGroupToPerm.group == parent_group).all() | |
284 |
|
287 | |||
285 | group_perms = UserGroupRepoGroupToPerm.query() \ |
|
288 | group_perms = UserGroupRepoGroupToPerm.query() \ | |
286 | .filter(UserGroupRepoGroupToPerm.group == parent_group).all() |
|
289 | .filter(UserGroupRepoGroupToPerm.group == parent_group).all() | |
287 |
|
290 | |||
288 | for perm in user_perms: |
|
291 | for perm in user_perms: | |
289 | # don't copy over the permission for user who is creating |
|
292 | # don't copy over the permission for user who is creating | |
290 | # this group, if he is not super admin he get's admin |
|
293 | # this group, if he is not super admin he get's admin | |
291 | # permission set above |
|
294 | # permission set above | |
292 | if perm.user != user or user.is_admin: |
|
295 | if perm.user != user or user.is_admin: | |
293 | UserRepoGroupToPerm.create( |
|
296 | UserRepoGroupToPerm.create( | |
294 | perm.user, new_repo_group, perm.permission) |
|
297 | perm.user, new_repo_group, perm.permission) | |
295 |
|
298 | |||
296 | for perm in group_perms: |
|
299 | for perm in group_perms: | |
297 | UserGroupRepoGroupToPerm.create( |
|
300 | UserGroupRepoGroupToPerm.create( | |
298 | perm.users_group, new_repo_group, perm.permission) |
|
301 | perm.users_group, new_repo_group, perm.permission) | |
299 | else: |
|
302 | else: | |
300 | perm_obj = self._create_default_perms(new_repo_group) |
|
303 | perm_obj = self._create_default_perms(new_repo_group) | |
301 | self.sa.add(perm_obj) |
|
304 | self.sa.add(perm_obj) | |
302 |
|
305 | |||
303 | # now commit the changes, earlier so we are sure everything is in |
|
306 | # now commit the changes, earlier so we are sure everything is in | |
304 | # the database. |
|
307 | # the database. | |
305 | if commit_early: |
|
308 | if commit_early: | |
306 | self.sa.commit() |
|
309 | self.sa.commit() | |
307 | if not just_db: |
|
310 | if not just_db: | |
308 | self._create_group(new_repo_group.group_name) |
|
311 | self._create_group(new_repo_group.group_name) | |
309 |
|
312 | |||
310 | # trigger the post hook |
|
313 | # trigger the post hook | |
311 | from rhodecode.lib import hooks_base |
|
314 | from rhodecode.lib import hooks_base | |
312 | repo_group = RepoGroup.get_by_group_name(group_name) |
|
315 | repo_group = RepoGroup.get_by_group_name(group_name) | |
313 |
|
316 | |||
314 | # update repo group commit caches initially |
|
317 | # update repo group commit caches initially | |
315 | repo_group.update_commit_cache() |
|
318 | repo_group.update_commit_cache() | |
316 |
|
319 | |||
317 | hooks_base.create_repository_group( |
|
320 | hooks_base.create_repository_group( | |
318 | created_by=user.username, **repo_group.get_dict()) |
|
321 | created_by=user.username, **repo_group.get_dict()) | |
319 |
|
322 | |||
320 | # Trigger create event. |
|
323 | # Trigger create event. | |
321 | events.trigger(events.RepoGroupCreateEvent(repo_group)) |
|
324 | events.trigger(events.RepoGroupCreateEvent(repo_group)) | |
322 |
|
325 | |||
323 | return new_repo_group |
|
326 | return new_repo_group | |
324 | except Exception: |
|
327 | except Exception: | |
325 | self.sa.rollback() |
|
328 | self.sa.rollback() | |
326 | log.exception('Exception occurred when creating repository group, ' |
|
329 | log.exception('Exception occurred when creating repository group, ' | |
327 | 'doing cleanup...') |
|
330 | 'doing cleanup...') | |
328 | # rollback things manually ! |
|
331 | # rollback things manually ! | |
329 | repo_group = RepoGroup.get_by_group_name(group_name) |
|
332 | repo_group = RepoGroup.get_by_group_name(group_name) | |
330 | if repo_group: |
|
333 | if repo_group: | |
331 | RepoGroup.delete(repo_group.group_id) |
|
334 | RepoGroup.delete(repo_group.group_id) | |
332 | self.sa.commit() |
|
335 | self.sa.commit() | |
333 | if cleanup_group: |
|
336 | if cleanup_group: | |
334 | RepoGroupModel()._delete_filesystem_group(repo_group) |
|
337 | RepoGroupModel()._delete_filesystem_group(repo_group) | |
335 | raise |
|
338 | raise | |
336 |
|
339 | |||
337 | def update_permissions( |
|
340 | def update_permissions( | |
338 | self, repo_group, perm_additions=None, perm_updates=None, |
|
341 | self, repo_group, perm_additions=None, perm_updates=None, | |
339 | perm_deletions=None, recursive=None, check_perms=True, |
|
342 | perm_deletions=None, recursive=None, check_perms=True, | |
340 | cur_user=None): |
|
343 | cur_user=None): | |
341 | from rhodecode.model.repo import RepoModel |
|
344 | from rhodecode.model.repo import RepoModel | |
342 | from rhodecode.lib.auth import HasUserGroupPermissionAny |
|
345 | from rhodecode.lib.auth import HasUserGroupPermissionAny | |
343 |
|
346 | |||
344 | if not perm_additions: |
|
347 | if not perm_additions: | |
345 | perm_additions = [] |
|
348 | perm_additions = [] | |
346 | if not perm_updates: |
|
349 | if not perm_updates: | |
347 | perm_updates = [] |
|
350 | perm_updates = [] | |
348 | if not perm_deletions: |
|
351 | if not perm_deletions: | |
349 | perm_deletions = [] |
|
352 | perm_deletions = [] | |
350 |
|
353 | |||
351 | req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin') |
|
354 | req_perms = ('usergroup.read', 'usergroup.write', 'usergroup.admin') | |
352 |
|
355 | |||
353 | changes = { |
|
356 | changes = { | |
354 | 'added': [], |
|
357 | 'added': [], | |
355 | 'updated': [], |
|
358 | 'updated': [], | |
356 | 'deleted': [], |
|
359 | 'deleted': [], | |
357 | 'default_user_changed': None |
|
360 | 'default_user_changed': None | |
358 | } |
|
361 | } | |
359 |
|
362 | |||
360 | def _set_perm_user(obj, user, perm): |
|
363 | def _set_perm_user(obj, user, perm): | |
361 | if isinstance(obj, RepoGroup): |
|
364 | if isinstance(obj, RepoGroup): | |
362 | self.grant_user_permission( |
|
365 | self.grant_user_permission( | |
363 | repo_group=obj, user=user, perm=perm) |
|
366 | repo_group=obj, user=user, perm=perm) | |
364 | elif isinstance(obj, Repository): |
|
367 | elif isinstance(obj, Repository): | |
365 | # private repos will not allow to change the default |
|
368 | # private repos will not allow to change the default | |
366 | # permissions using recursive mode |
|
369 | # permissions using recursive mode | |
367 | if obj.private and user == User.DEFAULT_USER: |
|
370 | if obj.private and user == User.DEFAULT_USER: | |
368 | return |
|
371 | return | |
369 |
|
372 | |||
370 | # we set group permission but we have to switch to repo |
|
373 | # we set group permission but we have to switch to repo | |
371 | # permission |
|
374 | # permission | |
372 | perm = perm.replace('group.', 'repository.') |
|
375 | perm = perm.replace('group.', 'repository.') | |
373 | RepoModel().grant_user_permission( |
|
376 | RepoModel().grant_user_permission( | |
374 | repo=obj, user=user, perm=perm) |
|
377 | repo=obj, user=user, perm=perm) | |
375 |
|
378 | |||
376 | def _set_perm_group(obj, users_group, perm): |
|
379 | def _set_perm_group(obj, users_group, perm): | |
377 | if isinstance(obj, RepoGroup): |
|
380 | if isinstance(obj, RepoGroup): | |
378 | self.grant_user_group_permission( |
|
381 | self.grant_user_group_permission( | |
379 | repo_group=obj, group_name=users_group, perm=perm) |
|
382 | repo_group=obj, group_name=users_group, perm=perm) | |
380 | elif isinstance(obj, Repository): |
|
383 | elif isinstance(obj, Repository): | |
381 | # we set group permission but we have to switch to repo |
|
384 | # we set group permission but we have to switch to repo | |
382 | # permission |
|
385 | # permission | |
383 | perm = perm.replace('group.', 'repository.') |
|
386 | perm = perm.replace('group.', 'repository.') | |
384 | RepoModel().grant_user_group_permission( |
|
387 | RepoModel().grant_user_group_permission( | |
385 | repo=obj, group_name=users_group, perm=perm) |
|
388 | repo=obj, group_name=users_group, perm=perm) | |
386 |
|
389 | |||
387 | def _revoke_perm_user(obj, user): |
|
390 | def _revoke_perm_user(obj, user): | |
388 | if isinstance(obj, RepoGroup): |
|
391 | if isinstance(obj, RepoGroup): | |
389 | self.revoke_user_permission(repo_group=obj, user=user) |
|
392 | self.revoke_user_permission(repo_group=obj, user=user) | |
390 | elif isinstance(obj, Repository): |
|
393 | elif isinstance(obj, Repository): | |
391 | RepoModel().revoke_user_permission(repo=obj, user=user) |
|
394 | RepoModel().revoke_user_permission(repo=obj, user=user) | |
392 |
|
395 | |||
393 | def _revoke_perm_group(obj, user_group): |
|
396 | def _revoke_perm_group(obj, user_group): | |
394 | if isinstance(obj, RepoGroup): |
|
397 | if isinstance(obj, RepoGroup): | |
395 | self.revoke_user_group_permission( |
|
398 | self.revoke_user_group_permission( | |
396 | repo_group=obj, group_name=user_group) |
|
399 | repo_group=obj, group_name=user_group) | |
397 | elif isinstance(obj, Repository): |
|
400 | elif isinstance(obj, Repository): | |
398 | RepoModel().revoke_user_group_permission( |
|
401 | RepoModel().revoke_user_group_permission( | |
399 | repo=obj, group_name=user_group) |
|
402 | repo=obj, group_name=user_group) | |
400 |
|
403 | |||
401 | # start updates |
|
404 | # start updates | |
402 | log.debug('Now updating permissions for %s in recursive mode:%s', |
|
405 | log.debug('Now updating permissions for %s in recursive mode:%s', | |
403 | repo_group, recursive) |
|
406 | repo_group, recursive) | |
404 |
|
407 | |||
405 | # initialize check function, we'll call that multiple times |
|
408 | # initialize check function, we'll call that multiple times | |
406 | has_group_perm = HasUserGroupPermissionAny(*req_perms) |
|
409 | has_group_perm = HasUserGroupPermissionAny(*req_perms) | |
407 |
|
410 | |||
408 | for obj in repo_group.recursive_groups_and_repos(): |
|
411 | for obj in repo_group.recursive_groups_and_repos(): | |
409 | # iterated obj is an instance of a repos group or repository in |
|
412 | # iterated obj is an instance of a repos group or repository in | |
410 | # that group, recursive option can be: none, repos, groups, all |
|
413 | # that group, recursive option can be: none, repos, groups, all | |
411 | if recursive == 'all': |
|
414 | if recursive == 'all': | |
412 | obj = obj |
|
415 | obj = obj | |
413 | elif recursive == 'repos': |
|
416 | elif recursive == 'repos': | |
414 | # skip groups, other than this one |
|
417 | # skip groups, other than this one | |
415 | if isinstance(obj, RepoGroup) and not obj == repo_group: |
|
418 | if isinstance(obj, RepoGroup) and not obj == repo_group: | |
416 | continue |
|
419 | continue | |
417 | elif recursive == 'groups': |
|
420 | elif recursive == 'groups': | |
418 | # skip repos |
|
421 | # skip repos | |
419 | if isinstance(obj, Repository): |
|
422 | if isinstance(obj, Repository): | |
420 | continue |
|
423 | continue | |
421 | else: # recursive == 'none': |
|
424 | else: # recursive == 'none': | |
422 | # DEFAULT option - don't apply to iterated objects |
|
425 | # DEFAULT option - don't apply to iterated objects | |
423 | # also we do a break at the end of this loop. if we are not |
|
426 | # also we do a break at the end of this loop. if we are not | |
424 | # in recursive mode |
|
427 | # in recursive mode | |
425 | obj = repo_group |
|
428 | obj = repo_group | |
426 |
|
429 | |||
427 | change_obj = obj.get_api_data() |
|
430 | change_obj = obj.get_api_data() | |
428 |
|
431 | |||
429 | # update permissions |
|
432 | # update permissions | |
430 | for member_id, perm, member_type in perm_updates: |
|
433 | for member_id, perm, member_type in perm_updates: | |
431 | member_id = int(member_id) |
|
434 | member_id = int(member_id) | |
432 | if member_type == 'user': |
|
435 | if member_type == 'user': | |
433 | member_name = User.get(member_id).username |
|
436 | member_name = User.get(member_id).username | |
434 | if isinstance(obj, RepoGroup) and obj == repo_group and member_name == User.DEFAULT_USER: |
|
437 | if isinstance(obj, RepoGroup) and obj == repo_group and member_name == User.DEFAULT_USER: | |
435 | # NOTE(dan): detect if we changed permissions for default user |
|
438 | # NOTE(dan): detect if we changed permissions for default user | |
436 | perm_obj = self.sa.query(UserRepoGroupToPerm) \ |
|
439 | perm_obj = self.sa.query(UserRepoGroupToPerm) \ | |
437 | .filter(UserRepoGroupToPerm.user_id == member_id) \ |
|
440 | .filter(UserRepoGroupToPerm.user_id == member_id) \ | |
438 | .filter(UserRepoGroupToPerm.group == repo_group) \ |
|
441 | .filter(UserRepoGroupToPerm.group == repo_group) \ | |
439 | .scalar() |
|
442 | .scalar() | |
440 | if perm_obj and perm_obj.permission.permission_name != perm: |
|
443 | if perm_obj and perm_obj.permission.permission_name != perm: | |
441 | changes['default_user_changed'] = True |
|
444 | changes['default_user_changed'] = True | |
442 |
|
445 | |||
443 | # this updates also current one if found |
|
446 | # this updates also current one if found | |
444 | _set_perm_user(obj, user=member_id, perm=perm) |
|
447 | _set_perm_user(obj, user=member_id, perm=perm) | |
445 | elif member_type == 'user_group': |
|
448 | elif member_type == 'user_group': | |
446 | member_name = UserGroup.get(member_id).users_group_name |
|
449 | member_name = UserGroup.get(member_id).users_group_name | |
447 | if not check_perms or has_group_perm(member_name, |
|
450 | if not check_perms or has_group_perm(member_name, | |
448 | user=cur_user): |
|
451 | user=cur_user): | |
449 | _set_perm_group(obj, users_group=member_id, perm=perm) |
|
452 | _set_perm_group(obj, users_group=member_id, perm=perm) | |
450 | else: |
|
453 | else: | |
451 | raise ValueError("member_type must be 'user' or 'user_group' " |
|
454 | raise ValueError("member_type must be 'user' or 'user_group' " | |
452 | "got {} instead".format(member_type)) |
|
455 | "got {} instead".format(member_type)) | |
453 |
|
456 | |||
454 | changes['updated'].append( |
|
457 | changes['updated'].append( | |
455 | {'change_obj': change_obj, 'type': member_type, |
|
458 | {'change_obj': change_obj, 'type': member_type, | |
456 | 'id': member_id, 'name': member_name, 'new_perm': perm}) |
|
459 | 'id': member_id, 'name': member_name, 'new_perm': perm}) | |
457 |
|
460 | |||
458 | # set new permissions |
|
461 | # set new permissions | |
459 | for member_id, perm, member_type in perm_additions: |
|
462 | for member_id, perm, member_type in perm_additions: | |
460 | member_id = int(member_id) |
|
463 | member_id = int(member_id) | |
461 | if member_type == 'user': |
|
464 | if member_type == 'user': | |
462 | member_name = User.get(member_id).username |
|
465 | member_name = User.get(member_id).username | |
463 | _set_perm_user(obj, user=member_id, perm=perm) |
|
466 | _set_perm_user(obj, user=member_id, perm=perm) | |
464 | elif member_type == 'user_group': |
|
467 | elif member_type == 'user_group': | |
465 | # check if we have permissions to alter this usergroup |
|
468 | # check if we have permissions to alter this usergroup | |
466 | member_name = UserGroup.get(member_id).users_group_name |
|
469 | member_name = UserGroup.get(member_id).users_group_name | |
467 | if not check_perms or has_group_perm(member_name, |
|
470 | if not check_perms or has_group_perm(member_name, | |
468 | user=cur_user): |
|
471 | user=cur_user): | |
469 | _set_perm_group(obj, users_group=member_id, perm=perm) |
|
472 | _set_perm_group(obj, users_group=member_id, perm=perm) | |
470 | else: |
|
473 | else: | |
471 | raise ValueError("member_type must be 'user' or 'user_group' " |
|
474 | raise ValueError("member_type must be 'user' or 'user_group' " | |
472 | "got {} instead".format(member_type)) |
|
475 | "got {} instead".format(member_type)) | |
473 |
|
476 | |||
474 | changes['added'].append( |
|
477 | changes['added'].append( | |
475 | {'change_obj': change_obj, 'type': member_type, |
|
478 | {'change_obj': change_obj, 'type': member_type, | |
476 | 'id': member_id, 'name': member_name, 'new_perm': perm}) |
|
479 | 'id': member_id, 'name': member_name, 'new_perm': perm}) | |
477 |
|
480 | |||
478 | # delete permissions |
|
481 | # delete permissions | |
479 | for member_id, perm, member_type in perm_deletions: |
|
482 | for member_id, perm, member_type in perm_deletions: | |
480 | member_id = int(member_id) |
|
483 | member_id = int(member_id) | |
481 | if member_type == 'user': |
|
484 | if member_type == 'user': | |
482 | member_name = User.get(member_id).username |
|
485 | member_name = User.get(member_id).username | |
483 | _revoke_perm_user(obj, user=member_id) |
|
486 | _revoke_perm_user(obj, user=member_id) | |
484 | elif member_type == 'user_group': |
|
487 | elif member_type == 'user_group': | |
485 | # check if we have permissions to alter this usergroup |
|
488 | # check if we have permissions to alter this usergroup | |
486 | member_name = UserGroup.get(member_id).users_group_name |
|
489 | member_name = UserGroup.get(member_id).users_group_name | |
487 | if not check_perms or has_group_perm(member_name, |
|
490 | if not check_perms or has_group_perm(member_name, | |
488 | user=cur_user): |
|
491 | user=cur_user): | |
489 | _revoke_perm_group(obj, user_group=member_id) |
|
492 | _revoke_perm_group(obj, user_group=member_id) | |
490 | else: |
|
493 | else: | |
491 | raise ValueError("member_type must be 'user' or 'user_group' " |
|
494 | raise ValueError("member_type must be 'user' or 'user_group' " | |
492 | "got {} instead".format(member_type)) |
|
495 | "got {} instead".format(member_type)) | |
493 |
|
496 | |||
494 | changes['deleted'].append( |
|
497 | changes['deleted'].append( | |
495 | {'change_obj': change_obj, 'type': member_type, |
|
498 | {'change_obj': change_obj, 'type': member_type, | |
496 | 'id': member_id, 'name': member_name, 'new_perm': perm}) |
|
499 | 'id': member_id, 'name': member_name, 'new_perm': perm}) | |
497 |
|
500 | |||
498 | # if it's not recursive call for all,repos,groups |
|
501 | # if it's not recursive call for all,repos,groups | |
499 | # break the loop and don't proceed with other changes |
|
502 | # break the loop and don't proceed with other changes | |
500 | if recursive not in ['all', 'repos', 'groups']: |
|
503 | if recursive not in ['all', 'repos', 'groups']: | |
501 | break |
|
504 | break | |
502 |
|
505 | |||
503 | return changes |
|
506 | return changes | |
504 |
|
507 | |||
505 | def update(self, repo_group, form_data): |
|
508 | def update(self, repo_group, form_data): | |
506 | try: |
|
509 | try: | |
507 | repo_group = self._get_repo_group(repo_group) |
|
510 | repo_group = self._get_repo_group(repo_group) | |
508 | old_path = repo_group.full_path |
|
511 | old_path = repo_group.full_path | |
509 |
|
512 | |||
510 | # change properties |
|
513 | # change properties | |
511 | if 'group_description' in form_data: |
|
514 | if 'group_description' in form_data: | |
512 | repo_group.group_description = form_data['group_description'] |
|
515 | repo_group.group_description = form_data['group_description'] | |
513 |
|
516 | |||
514 | if 'enable_locking' in form_data: |
|
517 | if 'enable_locking' in form_data: | |
515 | repo_group.enable_locking = form_data['enable_locking'] |
|
518 | repo_group.enable_locking = form_data['enable_locking'] | |
516 |
|
519 | |||
517 | if 'group_parent_id' in form_data: |
|
520 | if 'group_parent_id' in form_data: | |
518 | parent_group = ( |
|
521 | parent_group = ( | |
519 | self._get_repo_group(form_data['group_parent_id'])) |
|
522 | self._get_repo_group(form_data['group_parent_id'])) | |
520 | repo_group.group_parent_id = ( |
|
523 | repo_group.group_parent_id = ( | |
521 | parent_group.group_id if parent_group else None) |
|
524 | parent_group.group_id if parent_group else None) | |
522 | repo_group.parent_group = parent_group |
|
525 | repo_group.parent_group = parent_group | |
523 |
|
526 | |||
524 | # mikhail: to update the full_path, we have to explicitly |
|
527 | # mikhail: to update the full_path, we have to explicitly | |
525 | # update group_name |
|
528 | # update group_name | |
526 | group_name = form_data.get('group_name', repo_group.name) |
|
529 | group_name = form_data.get('group_name', repo_group.name) | |
527 | repo_group.group_name = repo_group.get_new_name(group_name) |
|
530 | repo_group.group_name = repo_group.get_new_name(group_name) | |
528 |
|
531 | |||
529 | new_path = repo_group.full_path |
|
532 | new_path = repo_group.full_path | |
530 |
|
533 | |||
531 | if 'user' in form_data: |
|
534 | if 'user' in form_data: | |
532 | repo_group.user = User.get_by_username(form_data['user']) |
|
535 | repo_group.user = User.get_by_username(form_data['user']) | |
533 |
|
536 | |||
534 | self.sa.add(repo_group) |
|
537 | self.sa.add(repo_group) | |
535 |
|
538 | |||
536 | # iterate over all members of this groups and do fixes |
|
539 | # iterate over all members of this groups and do fixes | |
537 | # set locking if given |
|
540 | # set locking if given | |
538 | # if obj is a repoGroup also fix the name of the group according |
|
541 | # if obj is a repoGroup also fix the name of the group according | |
539 | # to the parent |
|
542 | # to the parent | |
540 | # if obj is a Repo fix it's name |
|
543 | # if obj is a Repo fix it's name | |
541 | # this can be potentially heavy operation |
|
544 | # this can be potentially heavy operation | |
542 | for obj in repo_group.recursive_groups_and_repos(): |
|
545 | for obj in repo_group.recursive_groups_and_repos(): | |
543 | # set the value from it's parent |
|
546 | # set the value from it's parent | |
544 | obj.enable_locking = repo_group.enable_locking |
|
547 | obj.enable_locking = repo_group.enable_locking | |
545 | if isinstance(obj, RepoGroup): |
|
548 | if isinstance(obj, RepoGroup): | |
546 | new_name = obj.get_new_name(obj.name) |
|
549 | new_name = obj.get_new_name(obj.name) | |
547 | log.debug('Fixing group %s to new name %s', |
|
550 | log.debug('Fixing group %s to new name %s', | |
548 | obj.group_name, new_name) |
|
551 | obj.group_name, new_name) | |
549 | obj.group_name = new_name |
|
552 | obj.group_name = new_name | |
550 |
|
553 | |||
551 | elif isinstance(obj, Repository): |
|
554 | elif isinstance(obj, Repository): | |
552 | # we need to get all repositories from this new group and |
|
555 | # we need to get all repositories from this new group and | |
553 | # rename them accordingly to new group path |
|
556 | # rename them accordingly to new group path | |
554 | new_name = obj.get_new_name(obj.just_name) |
|
557 | new_name = obj.get_new_name(obj.just_name) | |
555 | log.debug('Fixing repo %s to new name %s', |
|
558 | log.debug('Fixing repo %s to new name %s', | |
556 | obj.repo_name, new_name) |
|
559 | obj.repo_name, new_name) | |
557 | obj.repo_name = new_name |
|
560 | obj.repo_name = new_name | |
558 |
|
561 | |||
559 | self.sa.add(obj) |
|
562 | self.sa.add(obj) | |
560 |
|
563 | |||
561 | self._rename_group(old_path, new_path) |
|
564 | self._rename_group(old_path, new_path) | |
562 |
|
565 | |||
563 | # Trigger update event. |
|
566 | # Trigger update event. | |
564 | events.trigger(events.RepoGroupUpdateEvent(repo_group)) |
|
567 | events.trigger(events.RepoGroupUpdateEvent(repo_group)) | |
565 |
|
568 | |||
566 | return repo_group |
|
569 | return repo_group | |
567 | except Exception: |
|
570 | except Exception: | |
568 | log.error(traceback.format_exc()) |
|
571 | log.error(traceback.format_exc()) | |
569 | raise |
|
572 | raise | |
570 |
|
573 | |||
571 | def delete(self, repo_group, force_delete=False, fs_remove=True): |
|
574 | def delete(self, repo_group, force_delete=False, fs_remove=True): | |
572 | repo_group = self._get_repo_group(repo_group) |
|
575 | repo_group = self._get_repo_group(repo_group) | |
573 | if not repo_group: |
|
576 | if not repo_group: | |
574 | return False |
|
577 | return False | |
575 | try: |
|
578 | try: | |
576 | self.sa.delete(repo_group) |
|
579 | self.sa.delete(repo_group) | |
577 | if fs_remove: |
|
580 | if fs_remove: | |
578 | self._delete_filesystem_group(repo_group, force_delete) |
|
581 | self._delete_filesystem_group(repo_group, force_delete) | |
579 | else: |
|
582 | else: | |
580 | log.debug('skipping removal from filesystem') |
|
583 | log.debug('skipping removal from filesystem') | |
581 |
|
584 | |||
582 | # Trigger delete event. |
|
585 | # Trigger delete event. | |
583 | events.trigger(events.RepoGroupDeleteEvent(repo_group)) |
|
586 | events.trigger(events.RepoGroupDeleteEvent(repo_group)) | |
584 | return True |
|
587 | return True | |
585 |
|
588 | |||
586 | except Exception: |
|
589 | except Exception: | |
587 | log.error('Error removing repo_group %s', repo_group) |
|
590 | log.error('Error removing repo_group %s', repo_group) | |
588 | raise |
|
591 | raise | |
589 |
|
592 | |||
590 | def grant_user_permission(self, repo_group, user, perm): |
|
593 | def grant_user_permission(self, repo_group, user, perm): | |
591 | """ |
|
594 | """ | |
592 | Grant permission for user on given repository group, or update |
|
595 | Grant permission for user on given repository group, or update | |
593 | existing one if found |
|
596 | existing one if found | |
594 |
|
597 | |||
595 | :param repo_group: Instance of RepoGroup, repositories_group_id, |
|
598 | :param repo_group: Instance of RepoGroup, repositories_group_id, | |
596 | or repositories_group name |
|
599 | or repositories_group name | |
597 | :param user: Instance of User, user_id or username |
|
600 | :param user: Instance of User, user_id or username | |
598 | :param perm: Instance of Permission, or permission_name |
|
601 | :param perm: Instance of Permission, or permission_name | |
599 | """ |
|
602 | """ | |
600 |
|
603 | |||
601 | repo_group = self._get_repo_group(repo_group) |
|
604 | repo_group = self._get_repo_group(repo_group) | |
602 | user = self._get_user(user) |
|
605 | user = self._get_user(user) | |
603 | permission = self._get_perm(perm) |
|
606 | permission = self._get_perm(perm) | |
604 |
|
607 | |||
605 | # check if we have that permission already |
|
608 | # check if we have that permission already | |
606 | obj = self.sa.query(UserRepoGroupToPerm)\ |
|
609 | obj = self.sa.query(UserRepoGroupToPerm)\ | |
607 | .filter(UserRepoGroupToPerm.user == user)\ |
|
610 | .filter(UserRepoGroupToPerm.user == user)\ | |
608 | .filter(UserRepoGroupToPerm.group == repo_group)\ |
|
611 | .filter(UserRepoGroupToPerm.group == repo_group)\ | |
609 | .scalar() |
|
612 | .scalar() | |
610 | if obj is None: |
|
613 | if obj is None: | |
611 | # create new ! |
|
614 | # create new ! | |
612 | obj = UserRepoGroupToPerm() |
|
615 | obj = UserRepoGroupToPerm() | |
613 | obj.group = repo_group |
|
616 | obj.group = repo_group | |
614 | obj.user = user |
|
617 | obj.user = user | |
615 | obj.permission = permission |
|
618 | obj.permission = permission | |
616 | self.sa.add(obj) |
|
619 | self.sa.add(obj) | |
617 | log.debug('Granted perm %s to %s on %s', perm, user, repo_group) |
|
620 | log.debug('Granted perm %s to %s on %s', perm, user, repo_group) | |
618 | action_logger_generic( |
|
621 | action_logger_generic( | |
619 | 'granted permission: {} to user: {} on repogroup: {}'.format( |
|
622 | 'granted permission: {} to user: {} on repogroup: {}'.format( | |
620 | perm, user, repo_group), namespace='security.repogroup') |
|
623 | perm, user, repo_group), namespace='security.repogroup') | |
621 | return obj |
|
624 | return obj | |
622 |
|
625 | |||
623 | def revoke_user_permission(self, repo_group, user): |
|
626 | def revoke_user_permission(self, repo_group, user): | |
624 | """ |
|
627 | """ | |
625 | Revoke permission for user on given repository group |
|
628 | Revoke permission for user on given repository group | |
626 |
|
629 | |||
627 | :param repo_group: Instance of RepoGroup, repositories_group_id, |
|
630 | :param repo_group: Instance of RepoGroup, repositories_group_id, | |
628 | or repositories_group name |
|
631 | or repositories_group name | |
629 | :param user: Instance of User, user_id or username |
|
632 | :param user: Instance of User, user_id or username | |
630 | """ |
|
633 | """ | |
631 |
|
634 | |||
632 | repo_group = self._get_repo_group(repo_group) |
|
635 | repo_group = self._get_repo_group(repo_group) | |
633 | user = self._get_user(user) |
|
636 | user = self._get_user(user) | |
634 |
|
637 | |||
635 | obj = self.sa.query(UserRepoGroupToPerm)\ |
|
638 | obj = self.sa.query(UserRepoGroupToPerm)\ | |
636 | .filter(UserRepoGroupToPerm.user == user)\ |
|
639 | .filter(UserRepoGroupToPerm.user == user)\ | |
637 | .filter(UserRepoGroupToPerm.group == repo_group)\ |
|
640 | .filter(UserRepoGroupToPerm.group == repo_group)\ | |
638 | .scalar() |
|
641 | .scalar() | |
639 | if obj: |
|
642 | if obj: | |
640 | self.sa.delete(obj) |
|
643 | self.sa.delete(obj) | |
641 | log.debug('Revoked perm on %s on %s', repo_group, user) |
|
644 | log.debug('Revoked perm on %s on %s', repo_group, user) | |
642 | action_logger_generic( |
|
645 | action_logger_generic( | |
643 | 'revoked permission from user: {} on repogroup: {}'.format( |
|
646 | 'revoked permission from user: {} on repogroup: {}'.format( | |
644 | user, repo_group), namespace='security.repogroup') |
|
647 | user, repo_group), namespace='security.repogroup') | |
645 |
|
648 | |||
646 | def grant_user_group_permission(self, repo_group, group_name, perm): |
|
649 | def grant_user_group_permission(self, repo_group, group_name, perm): | |
647 | """ |
|
650 | """ | |
648 | Grant permission for user group on given repository group, or update |
|
651 | Grant permission for user group on given repository group, or update | |
649 | existing one if found |
|
652 | existing one if found | |
650 |
|
653 | |||
651 | :param repo_group: Instance of RepoGroup, repositories_group_id, |
|
654 | :param repo_group: Instance of RepoGroup, repositories_group_id, | |
652 | or repositories_group name |
|
655 | or repositories_group name | |
653 | :param group_name: Instance of UserGroup, users_group_id, |
|
656 | :param group_name: Instance of UserGroup, users_group_id, | |
654 | or user group name |
|
657 | or user group name | |
655 | :param perm: Instance of Permission, or permission_name |
|
658 | :param perm: Instance of Permission, or permission_name | |
656 | """ |
|
659 | """ | |
657 | repo_group = self._get_repo_group(repo_group) |
|
660 | repo_group = self._get_repo_group(repo_group) | |
658 | group_name = self._get_user_group(group_name) |
|
661 | group_name = self._get_user_group(group_name) | |
659 | permission = self._get_perm(perm) |
|
662 | permission = self._get_perm(perm) | |
660 |
|
663 | |||
661 | # check if we have that permission already |
|
664 | # check if we have that permission already | |
662 | obj = self.sa.query(UserGroupRepoGroupToPerm)\ |
|
665 | obj = self.sa.query(UserGroupRepoGroupToPerm)\ | |
663 | .filter(UserGroupRepoGroupToPerm.group == repo_group)\ |
|
666 | .filter(UserGroupRepoGroupToPerm.group == repo_group)\ | |
664 | .filter(UserGroupRepoGroupToPerm.users_group == group_name)\ |
|
667 | .filter(UserGroupRepoGroupToPerm.users_group == group_name)\ | |
665 | .scalar() |
|
668 | .scalar() | |
666 |
|
669 | |||
667 | if obj is None: |
|
670 | if obj is None: | |
668 | # create new |
|
671 | # create new | |
669 | obj = UserGroupRepoGroupToPerm() |
|
672 | obj = UserGroupRepoGroupToPerm() | |
670 |
|
673 | |||
671 | obj.group = repo_group |
|
674 | obj.group = repo_group | |
672 | obj.users_group = group_name |
|
675 | obj.users_group = group_name | |
673 | obj.permission = permission |
|
676 | obj.permission = permission | |
674 | self.sa.add(obj) |
|
677 | self.sa.add(obj) | |
675 | log.debug('Granted perm %s to %s on %s', perm, group_name, repo_group) |
|
678 | log.debug('Granted perm %s to %s on %s', perm, group_name, repo_group) | |
676 | action_logger_generic( |
|
679 | action_logger_generic( | |
677 | 'granted permission: {} to usergroup: {} on repogroup: {}'.format( |
|
680 | 'granted permission: {} to usergroup: {} on repogroup: {}'.format( | |
678 | perm, group_name, repo_group), namespace='security.repogroup') |
|
681 | perm, group_name, repo_group), namespace='security.repogroup') | |
679 | return obj |
|
682 | return obj | |
680 |
|
683 | |||
681 | def revoke_user_group_permission(self, repo_group, group_name): |
|
684 | def revoke_user_group_permission(self, repo_group, group_name): | |
682 | """ |
|
685 | """ | |
683 | Revoke permission for user group on given repository group |
|
686 | Revoke permission for user group on given repository group | |
684 |
|
687 | |||
685 | :param repo_group: Instance of RepoGroup, repositories_group_id, |
|
688 | :param repo_group: Instance of RepoGroup, repositories_group_id, | |
686 | or repositories_group name |
|
689 | or repositories_group name | |
687 | :param group_name: Instance of UserGroup, users_group_id, |
|
690 | :param group_name: Instance of UserGroup, users_group_id, | |
688 | or user group name |
|
691 | or user group name | |
689 | """ |
|
692 | """ | |
690 | repo_group = self._get_repo_group(repo_group) |
|
693 | repo_group = self._get_repo_group(repo_group) | |
691 | group_name = self._get_user_group(group_name) |
|
694 | group_name = self._get_user_group(group_name) | |
692 |
|
695 | |||
693 | obj = self.sa.query(UserGroupRepoGroupToPerm)\ |
|
696 | obj = self.sa.query(UserGroupRepoGroupToPerm)\ | |
694 | .filter(UserGroupRepoGroupToPerm.group == repo_group)\ |
|
697 | .filter(UserGroupRepoGroupToPerm.group == repo_group)\ | |
695 | .filter(UserGroupRepoGroupToPerm.users_group == group_name)\ |
|
698 | .filter(UserGroupRepoGroupToPerm.users_group == group_name)\ | |
696 | .scalar() |
|
699 | .scalar() | |
697 | if obj: |
|
700 | if obj: | |
698 | self.sa.delete(obj) |
|
701 | self.sa.delete(obj) | |
699 | log.debug('Revoked perm to %s on %s', repo_group, group_name) |
|
702 | log.debug('Revoked perm to %s on %s', repo_group, group_name) | |
700 | action_logger_generic( |
|
703 | action_logger_generic( | |
701 | 'revoked permission from usergroup: {} on repogroup: {}'.format( |
|
704 | 'revoked permission from usergroup: {} on repogroup: {}'.format( | |
702 | group_name, repo_group), namespace='security.repogroup') |
|
705 | group_name, repo_group), namespace='security.repogroup') | |
703 |
|
706 | |||
704 | @classmethod |
|
707 | @classmethod | |
705 | def update_commit_cache(cls, repo_groups=None): |
|
708 | def update_commit_cache(cls, repo_groups=None): | |
706 | if not repo_groups: |
|
709 | if not repo_groups: | |
707 | repo_groups = RepoGroup.getAll() |
|
710 | repo_groups = RepoGroup.getAll() | |
708 | for repo_group in repo_groups: |
|
711 | for repo_group in repo_groups: | |
709 | repo_group.update_commit_cache() |
|
712 | repo_group.update_commit_cache() | |
710 |
|
713 | |||
711 | def get_repo_groups_as_dict(self, repo_group_list=None, admin=False, |
|
714 | def get_repo_groups_as_dict(self, repo_group_list=None, admin=False, | |
712 | super_user_actions=False): |
|
715 | super_user_actions=False): | |
713 |
|
716 | |||
714 | from pyramid.threadlocal import get_current_request |
|
717 | from pyramid.threadlocal import get_current_request | |
715 | _render = get_current_request().get_partial_renderer( |
|
718 | _render = get_current_request().get_partial_renderer( | |
716 | 'rhodecode:templates/data_table/_dt_elements.mako') |
|
719 | 'rhodecode:templates/data_table/_dt_elements.mako') | |
717 | c = _render.get_call_context() |
|
720 | c = _render.get_call_context() | |
718 | h = _render.get_helpers() |
|
721 | h = _render.get_helpers() | |
719 |
|
722 | |||
720 | def quick_menu(repo_group_name): |
|
723 | def quick_menu(repo_group_name): | |
721 | return _render('quick_repo_group_menu', repo_group_name) |
|
724 | return _render('quick_repo_group_menu', repo_group_name) | |
722 |
|
725 | |||
723 | def repo_group_lnk(repo_group_name): |
|
726 | def repo_group_lnk(repo_group_name): | |
724 | return _render('repo_group_name', repo_group_name) |
|
727 | return _render('repo_group_name', repo_group_name) | |
725 |
|
728 | |||
726 | def last_change(last_change): |
|
729 | def last_change(last_change): | |
727 | if admin and isinstance(last_change, datetime.datetime) and not last_change.tzinfo: |
|
730 | if admin and isinstance(last_change, datetime.datetime) and not last_change.tzinfo: | |
728 | ts = time.time() |
|
731 | ts = time.time() | |
729 | utc_offset = (datetime.datetime.fromtimestamp(ts) |
|
732 | utc_offset = (datetime.datetime.fromtimestamp(ts) | |
730 | - datetime.datetime.utcfromtimestamp(ts)).total_seconds() |
|
733 | - datetime.datetime.utcfromtimestamp(ts)).total_seconds() | |
731 | last_change = last_change + datetime.timedelta(seconds=utc_offset) |
|
734 | last_change = last_change + datetime.timedelta(seconds=utc_offset) | |
732 | return _render("last_change", last_change) |
|
735 | return _render("last_change", last_change) | |
733 |
|
736 | |||
734 | def desc(desc, personal): |
|
737 | def desc(desc, personal): | |
735 | return _render( |
|
738 | return _render( | |
736 | 'repo_group_desc', desc, personal, c.visual.stylify_metatags) |
|
739 | 'repo_group_desc', desc, personal, c.visual.stylify_metatags) | |
737 |
|
740 | |||
738 | def repo_group_actions(repo_group_id, repo_group_name, gr_count): |
|
741 | def repo_group_actions(repo_group_id, repo_group_name, gr_count): | |
739 | return _render( |
|
742 | return _render( | |
740 | 'repo_group_actions', repo_group_id, repo_group_name, gr_count) |
|
743 | 'repo_group_actions', repo_group_id, repo_group_name, gr_count) | |
741 |
|
744 | |||
742 | def repo_group_name(repo_group_name, children_groups): |
|
745 | def repo_group_name(repo_group_name, children_groups): | |
743 | return _render("repo_group_name", repo_group_name, children_groups) |
|
746 | return _render("repo_group_name", repo_group_name, children_groups) | |
744 |
|
747 | |||
745 | def user_profile(username): |
|
748 | def user_profile(username): | |
746 | return _render('user_profile', username) |
|
749 | return _render('user_profile', username) | |
747 |
|
750 | |||
748 | repo_group_data = [] |
|
751 | repo_group_data = [] | |
749 | for group in repo_group_list: |
|
752 | for group in repo_group_list: | |
750 | # NOTE(marcink): because we use only raw column we need to load it like that |
|
753 | # NOTE(marcink): because we use only raw column we need to load it like that | |
751 | changeset_cache = RepoGroup._load_changeset_cache( |
|
754 | changeset_cache = RepoGroup._load_changeset_cache( | |
752 | '', group._changeset_cache) |
|
755 | '', group._changeset_cache) | |
753 | last_commit_change = RepoGroup._load_commit_change(changeset_cache) |
|
756 | last_commit_change = RepoGroup._load_commit_change(changeset_cache) | |
754 | row = { |
|
757 | row = { | |
755 | "menu": quick_menu(group.group_name), |
|
758 | "menu": quick_menu(group.group_name), | |
756 | "name": repo_group_lnk(group.group_name), |
|
759 | "name": repo_group_lnk(group.group_name), | |
757 | "name_raw": group.group_name, |
|
760 | "name_raw": group.group_name, | |
758 |
|
761 | |||
759 | "last_change": last_change(last_commit_change), |
|
762 | "last_change": last_change(last_commit_change), | |
760 |
|
763 | |||
761 | "last_changeset": "", |
|
764 | "last_changeset": "", | |
762 | "last_changeset_raw": "", |
|
765 | "last_changeset_raw": "", | |
763 |
|
766 | |||
764 | "desc": desc(h.escape(group.group_description), group.personal), |
|
767 | "desc": desc(h.escape(group.group_description), group.personal), | |
765 | "top_level_repos": 0, |
|
768 | "top_level_repos": 0, | |
766 | "owner": user_profile(group.User.username) |
|
769 | "owner": user_profile(group.User.username) | |
767 | } |
|
770 | } | |
768 | if admin: |
|
771 | if admin: | |
769 | repo_count = group.repositories.count() |
|
772 | repo_count = group.repositories.count() | |
770 | children_groups = map( |
|
773 | children_groups = map( | |
771 | h.safe_unicode, |
|
774 | h.safe_unicode, | |
772 | itertools.chain((g.name for g in group.parents), |
|
775 | itertools.chain((g.name for g in group.parents), | |
773 | (x.name for x in [group]))) |
|
776 | (x.name for x in [group]))) | |
774 | row.update({ |
|
777 | row.update({ | |
775 | "action": repo_group_actions( |
|
778 | "action": repo_group_actions( | |
776 | group.group_id, group.group_name, repo_count), |
|
779 | group.group_id, group.group_name, repo_count), | |
777 | "top_level_repos": repo_count, |
|
780 | "top_level_repos": repo_count, | |
778 | "name": repo_group_name(group.group_name, children_groups), |
|
781 | "name": repo_group_name(group.group_name, children_groups), | |
779 |
|
782 | |||
780 | }) |
|
783 | }) | |
781 | repo_group_data.append(row) |
|
784 | repo_group_data.append(row) | |
782 |
|
785 | |||
783 | return repo_group_data |
|
786 | return repo_group_data | |
784 |
|
787 | |||
785 | def get_repo_groups_data_table( |
|
788 | def get_repo_groups_data_table( | |
786 | self, draw, start, limit, |
|
789 | self, draw, start, limit, | |
787 | search_q, order_by, order_dir, |
|
790 | search_q, order_by, order_dir, | |
788 | auth_user, repo_group_id): |
|
791 | auth_user, repo_group_id): | |
789 | from rhodecode.model.scm import RepoGroupList |
|
792 | from rhodecode.model.scm import RepoGroupList | |
790 |
|
793 | |||
791 | _perms = ['group.read', 'group.write', 'group.admin'] |
|
794 | _perms = ['group.read', 'group.write', 'group.admin'] | |
792 | repo_groups = RepoGroup.query() \ |
|
795 | repo_groups = RepoGroup.query() \ | |
793 | .filter(RepoGroup.group_parent_id == repo_group_id) \ |
|
796 | .filter(RepoGroup.group_parent_id == repo_group_id) \ | |
794 | .all() |
|
797 | .all() | |
795 | auth_repo_group_list = RepoGroupList( |
|
798 | auth_repo_group_list = RepoGroupList( | |
796 | repo_groups, perm_set=_perms, |
|
799 | repo_groups, perm_set=_perms, | |
797 | extra_kwargs=dict(user=auth_user)) |
|
800 | extra_kwargs=dict(user=auth_user)) | |
798 |
|
801 | |||
799 | allowed_ids = [-1] |
|
802 | allowed_ids = [-1] | |
800 | for repo_group in auth_repo_group_list: |
|
803 | for repo_group in auth_repo_group_list: | |
801 | allowed_ids.append(repo_group.group_id) |
|
804 | allowed_ids.append(repo_group.group_id) | |
802 |
|
805 | |||
803 | repo_groups_data_total_count = RepoGroup.query() \ |
|
806 | repo_groups_data_total_count = RepoGroup.query() \ | |
804 | .filter(RepoGroup.group_parent_id == repo_group_id) \ |
|
807 | .filter(RepoGroup.group_parent_id == repo_group_id) \ | |
805 | .filter(or_( |
|
808 | .filter(or_( | |
806 | # generate multiple IN to fix limitation problems |
|
809 | # generate multiple IN to fix limitation problems | |
807 | *in_filter_generator(RepoGroup.group_id, allowed_ids)) |
|
810 | *in_filter_generator(RepoGroup.group_id, allowed_ids)) | |
808 | ) \ |
|
811 | ) \ | |
809 | .count() |
|
812 | .count() | |
810 |
|
813 | |||
811 | base_q = Session.query( |
|
814 | base_q = Session.query( | |
812 | RepoGroup.group_name, |
|
815 | RepoGroup.group_name, | |
813 | RepoGroup.group_name_hash, |
|
816 | RepoGroup.group_name_hash, | |
814 | RepoGroup.group_description, |
|
817 | RepoGroup.group_description, | |
815 | RepoGroup.group_id, |
|
818 | RepoGroup.group_id, | |
816 | RepoGroup.personal, |
|
819 | RepoGroup.personal, | |
817 | RepoGroup.updated_on, |
|
820 | RepoGroup.updated_on, | |
818 | RepoGroup._changeset_cache, |
|
821 | RepoGroup._changeset_cache, | |
819 | User, |
|
822 | User, | |
820 | ) \ |
|
823 | ) \ | |
821 | .filter(RepoGroup.group_parent_id == repo_group_id) \ |
|
824 | .filter(RepoGroup.group_parent_id == repo_group_id) \ | |
822 | .filter(or_( |
|
825 | .filter(or_( | |
823 | # generate multiple IN to fix limitation problems |
|
826 | # generate multiple IN to fix limitation problems | |
824 | *in_filter_generator(RepoGroup.group_id, allowed_ids)) |
|
827 | *in_filter_generator(RepoGroup.group_id, allowed_ids)) | |
825 | ) \ |
|
828 | ) \ | |
826 | .join(User, User.user_id == RepoGroup.user_id) \ |
|
829 | .join(User, User.user_id == RepoGroup.user_id) \ | |
827 | .group_by(RepoGroup, User) |
|
830 | .group_by(RepoGroup, User) | |
828 |
|
831 | |||
829 | repo_groups_data_total_filtered_count = base_q.count() |
|
832 | repo_groups_data_total_filtered_count = base_q.count() | |
830 |
|
833 | |||
831 | sort_defined = False |
|
834 | sort_defined = False | |
832 |
|
835 | |||
833 | if order_by == 'group_name': |
|
836 | if order_by == 'group_name': | |
834 | sort_col = func.lower(RepoGroup.group_name) |
|
837 | sort_col = func.lower(RepoGroup.group_name) | |
835 | sort_defined = True |
|
838 | sort_defined = True | |
836 | elif order_by == 'user_username': |
|
839 | elif order_by == 'user_username': | |
837 | sort_col = User.username |
|
840 | sort_col = User.username | |
838 | else: |
|
841 | else: | |
839 | sort_col = getattr(RepoGroup, order_by, None) |
|
842 | sort_col = getattr(RepoGroup, order_by, None) | |
840 |
|
843 | |||
841 | if sort_defined or sort_col: |
|
844 | if sort_defined or sort_col: | |
842 | if order_dir == 'asc': |
|
845 | if order_dir == 'asc': | |
843 | sort_col = sort_col.asc() |
|
846 | sort_col = sort_col.asc() | |
844 | else: |
|
847 | else: | |
845 | sort_col = sort_col.desc() |
|
848 | sort_col = sort_col.desc() | |
846 |
|
849 | |||
847 | base_q = base_q.order_by(sort_col) |
|
850 | base_q = base_q.order_by(sort_col) | |
848 | base_q = base_q.offset(start).limit(limit) |
|
851 | base_q = base_q.offset(start).limit(limit) | |
849 |
|
852 | |||
850 | repo_group_list = base_q.all() |
|
853 | repo_group_list = base_q.all() | |
851 |
|
854 | |||
852 | repo_groups_data = RepoGroupModel().get_repo_groups_as_dict( |
|
855 | repo_groups_data = RepoGroupModel().get_repo_groups_as_dict( | |
853 | repo_group_list=repo_group_list, admin=False) |
|
856 | repo_group_list=repo_group_list, admin=False) | |
854 |
|
857 | |||
855 | data = ({ |
|
858 | data = ({ | |
856 | 'draw': draw, |
|
859 | 'draw': draw, | |
857 | 'data': repo_groups_data, |
|
860 | 'data': repo_groups_data, | |
858 | 'recordsTotal': repo_groups_data_total_count, |
|
861 | 'recordsTotal': repo_groups_data_total_count, | |
859 | 'recordsFiltered': repo_groups_data_total_filtered_count, |
|
862 | 'recordsFiltered': repo_groups_data_total_filtered_count, | |
860 | }) |
|
863 | }) | |
861 | return data |
|
864 | return data | |
862 |
|
865 | |||
863 | def _get_defaults(self, repo_group_name): |
|
866 | def _get_defaults(self, repo_group_name): | |
864 | repo_group = RepoGroup.get_by_group_name(repo_group_name) |
|
867 | repo_group = RepoGroup.get_by_group_name(repo_group_name) | |
865 |
|
868 | |||
866 | if repo_group is None: |
|
869 | if repo_group is None: | |
867 | return None |
|
870 | return None | |
868 |
|
871 | |||
869 | defaults = repo_group.get_dict() |
|
872 | defaults = repo_group.get_dict() | |
870 | defaults['repo_group_name'] = repo_group.name |
|
873 | defaults['repo_group_name'] = repo_group.name | |
871 | defaults['repo_group_description'] = repo_group.group_description |
|
874 | defaults['repo_group_description'] = repo_group.group_description | |
872 | defaults['repo_group_enable_locking'] = repo_group.enable_locking |
|
875 | defaults['repo_group_enable_locking'] = repo_group.enable_locking | |
873 |
|
876 | |||
874 | # we use -1 as this is how in HTML, we mark an empty group |
|
877 | # we use -1 as this is how in HTML, we mark an empty group | |
875 | defaults['repo_group'] = defaults['group_parent_id'] or -1 |
|
878 | defaults['repo_group'] = defaults['group_parent_id'] or -1 | |
876 |
|
879 | |||
877 | # fill owner |
|
880 | # fill owner | |
878 | if repo_group.user: |
|
881 | if repo_group.user: | |
879 | defaults.update({'user': repo_group.user.username}) |
|
882 | defaults.update({'user': repo_group.user.username}) | |
880 | else: |
|
883 | else: | |
881 | replacement_user = User.get_first_super_admin().username |
|
884 | replacement_user = User.get_first_super_admin().username | |
882 | defaults.update({'user': replacement_user}) |
|
885 | defaults.update({'user': replacement_user}) | |
883 |
|
886 | |||
884 | return defaults |
|
887 | return defaults |
@@ -1,403 +1,405 b'' | |||||
1 |
|
1 | |||
2 | /****************************************************************************** |
|
2 | /****************************************************************************** | |
3 | * * |
|
3 | * * | |
4 | * DO NOT CHANGE THIS FILE MANUALLY * |
|
4 | * DO NOT CHANGE THIS FILE MANUALLY * | |
5 | * * |
|
5 | * * | |
6 | * * |
|
6 | * * | |
7 | * This file is automatically generated when the app starts up with * |
|
7 | * This file is automatically generated when the app starts up with * | |
8 | * generate_js_files = true * |
|
8 | * generate_js_files = true * | |
9 | * * |
|
9 | * * | |
10 | * To add a route here pass jsroute=True to the route definition in the app * |
|
10 | * To add a route here pass jsroute=True to the route definition in the app * | |
11 | * * |
|
11 | * * | |
12 | ******************************************************************************/ |
|
12 | ******************************************************************************/ | |
13 | function registerRCRoutes() { |
|
13 | function registerRCRoutes() { | |
14 | // routes registration |
|
14 | // routes registration | |
15 | pyroutes.register('admin_audit_log_entry', '/_admin/audit_logs/%(audit_log_id)s', ['audit_log_id']); |
|
15 | pyroutes.register('admin_audit_log_entry', '/_admin/audit_logs/%(audit_log_id)s', ['audit_log_id']); | |
16 | pyroutes.register('admin_audit_logs', '/_admin/audit_logs', []); |
|
16 | pyroutes.register('admin_audit_logs', '/_admin/audit_logs', []); | |
17 | pyroutes.register('admin_defaults_repositories', '/_admin/defaults/repositories', []); |
|
17 | pyroutes.register('admin_defaults_repositories', '/_admin/defaults/repositories', []); | |
18 | pyroutes.register('admin_defaults_repositories_update', '/_admin/defaults/repositories/update', []); |
|
18 | pyroutes.register('admin_defaults_repositories_update', '/_admin/defaults/repositories/update', []); | |
19 | pyroutes.register('admin_home', '/_admin', []); |
|
19 | pyroutes.register('admin_home', '/_admin', []); | |
20 | pyroutes.register('admin_permissions_application', '/_admin/permissions/application', []); |
|
20 | pyroutes.register('admin_permissions_application', '/_admin/permissions/application', []); | |
21 | pyroutes.register('admin_permissions_application_update', '/_admin/permissions/application/update', []); |
|
21 | pyroutes.register('admin_permissions_application_update', '/_admin/permissions/application/update', []); | |
22 | pyroutes.register('admin_permissions_auth_token_access', '/_admin/permissions/auth_token_access', []); |
|
22 | pyroutes.register('admin_permissions_auth_token_access', '/_admin/permissions/auth_token_access', []); | |
23 | pyroutes.register('admin_permissions_branch', '/_admin/permissions/branch', []); |
|
23 | pyroutes.register('admin_permissions_branch', '/_admin/permissions/branch', []); | |
24 | pyroutes.register('admin_permissions_branch_update', '/_admin/permissions/branch/update', []); |
|
24 | pyroutes.register('admin_permissions_branch_update', '/_admin/permissions/branch/update', []); | |
25 | pyroutes.register('admin_permissions_global', '/_admin/permissions/global', []); |
|
25 | pyroutes.register('admin_permissions_global', '/_admin/permissions/global', []); | |
26 | pyroutes.register('admin_permissions_global_update', '/_admin/permissions/global/update', []); |
|
26 | pyroutes.register('admin_permissions_global_update', '/_admin/permissions/global/update', []); | |
27 | pyroutes.register('admin_permissions_ips', '/_admin/permissions/ips', []); |
|
27 | pyroutes.register('admin_permissions_ips', '/_admin/permissions/ips', []); | |
28 | pyroutes.register('admin_permissions_object', '/_admin/permissions/object', []); |
|
28 | pyroutes.register('admin_permissions_object', '/_admin/permissions/object', []); | |
29 | pyroutes.register('admin_permissions_object_update', '/_admin/permissions/object/update', []); |
|
29 | pyroutes.register('admin_permissions_object_update', '/_admin/permissions/object/update', []); | |
30 | pyroutes.register('admin_permissions_overview', '/_admin/permissions/overview', []); |
|
30 | pyroutes.register('admin_permissions_overview', '/_admin/permissions/overview', []); | |
31 | pyroutes.register('admin_permissions_ssh_keys', '/_admin/permissions/ssh_keys', []); |
|
31 | pyroutes.register('admin_permissions_ssh_keys', '/_admin/permissions/ssh_keys', []); | |
32 | pyroutes.register('admin_permissions_ssh_keys_data', '/_admin/permissions/ssh_keys/data', []); |
|
32 | pyroutes.register('admin_permissions_ssh_keys_data', '/_admin/permissions/ssh_keys/data', []); | |
33 | pyroutes.register('admin_permissions_ssh_keys_update', '/_admin/permissions/ssh_keys/update', []); |
|
33 | pyroutes.register('admin_permissions_ssh_keys_update', '/_admin/permissions/ssh_keys/update', []); | |
34 | pyroutes.register('admin_settings', '/_admin/settings', []); |
|
34 | pyroutes.register('admin_settings', '/_admin/settings', []); | |
35 | pyroutes.register('admin_settings_automation', '/_admin/settings/automation', []); |
|
35 | pyroutes.register('admin_settings_automation', '/_admin/settings/automation', []); | |
36 | pyroutes.register('admin_settings_automation_update', '/_admin/settings/automation/%(entry_id)s/update', ['entry_id']); |
|
36 | pyroutes.register('admin_settings_automation_update', '/_admin/settings/automation/%(entry_id)s/update', ['entry_id']); | |
37 | pyroutes.register('admin_settings_email', '/_admin/settings/email', []); |
|
37 | pyroutes.register('admin_settings_email', '/_admin/settings/email', []); | |
38 | pyroutes.register('admin_settings_email_update', '/_admin/settings/email/update', []); |
|
38 | pyroutes.register('admin_settings_email_update', '/_admin/settings/email/update', []); | |
39 | pyroutes.register('admin_settings_exception_tracker', '/_admin/settings/exceptions', []); |
|
39 | pyroutes.register('admin_settings_exception_tracker', '/_admin/settings/exceptions', []); | |
40 | pyroutes.register('admin_settings_exception_tracker_delete', '/_admin/settings/exceptions/%(exception_id)s/delete', ['exception_id']); |
|
40 | pyroutes.register('admin_settings_exception_tracker_delete', '/_admin/settings/exceptions/%(exception_id)s/delete', ['exception_id']); | |
41 | pyroutes.register('admin_settings_exception_tracker_delete_all', '/_admin/settings/exceptions_delete_all', []); |
|
41 | pyroutes.register('admin_settings_exception_tracker_delete_all', '/_admin/settings/exceptions_delete_all', []); | |
42 | pyroutes.register('admin_settings_exception_tracker_show', '/_admin/settings/exceptions/%(exception_id)s', ['exception_id']); |
|
42 | pyroutes.register('admin_settings_exception_tracker_show', '/_admin/settings/exceptions/%(exception_id)s', ['exception_id']); | |
43 | pyroutes.register('admin_settings_global', '/_admin/settings/global', []); |
|
43 | pyroutes.register('admin_settings_global', '/_admin/settings/global', []); | |
44 | pyroutes.register('admin_settings_global_update', '/_admin/settings/global/update', []); |
|
44 | pyroutes.register('admin_settings_global_update', '/_admin/settings/global/update', []); | |
45 | pyroutes.register('admin_settings_hooks', '/_admin/settings/hooks', []); |
|
45 | pyroutes.register('admin_settings_hooks', '/_admin/settings/hooks', []); | |
46 | pyroutes.register('admin_settings_hooks_delete', '/_admin/settings/hooks/delete', []); |
|
46 | pyroutes.register('admin_settings_hooks_delete', '/_admin/settings/hooks/delete', []); | |
47 | pyroutes.register('admin_settings_hooks_update', '/_admin/settings/hooks/update', []); |
|
47 | pyroutes.register('admin_settings_hooks_update', '/_admin/settings/hooks/update', []); | |
48 | pyroutes.register('admin_settings_issuetracker', '/_admin/settings/issue-tracker', []); |
|
48 | pyroutes.register('admin_settings_issuetracker', '/_admin/settings/issue-tracker', []); | |
49 | pyroutes.register('admin_settings_issuetracker_delete', '/_admin/settings/issue-tracker/delete', []); |
|
49 | pyroutes.register('admin_settings_issuetracker_delete', '/_admin/settings/issue-tracker/delete', []); | |
50 | pyroutes.register('admin_settings_issuetracker_test', '/_admin/settings/issue-tracker/test', []); |
|
50 | pyroutes.register('admin_settings_issuetracker_test', '/_admin/settings/issue-tracker/test', []); | |
51 | pyroutes.register('admin_settings_issuetracker_update', '/_admin/settings/issue-tracker/update', []); |
|
51 | pyroutes.register('admin_settings_issuetracker_update', '/_admin/settings/issue-tracker/update', []); | |
52 | pyroutes.register('admin_settings_labs', '/_admin/settings/labs', []); |
|
52 | pyroutes.register('admin_settings_labs', '/_admin/settings/labs', []); | |
53 | pyroutes.register('admin_settings_labs_update', '/_admin/settings/labs/update', []); |
|
53 | pyroutes.register('admin_settings_labs_update', '/_admin/settings/labs/update', []); | |
54 | pyroutes.register('admin_settings_license', '/_admin/settings/license', []); |
|
54 | pyroutes.register('admin_settings_license', '/_admin/settings/license', []); | |
55 | pyroutes.register('admin_settings_license_unlock', '/_admin/settings/license_unlock', []); |
|
55 | pyroutes.register('admin_settings_license_unlock', '/_admin/settings/license_unlock', []); | |
56 | pyroutes.register('admin_settings_mapping', '/_admin/settings/mapping', []); |
|
56 | pyroutes.register('admin_settings_mapping', '/_admin/settings/mapping', []); | |
57 | pyroutes.register('admin_settings_mapping_update', '/_admin/settings/mapping/update', []); |
|
57 | pyroutes.register('admin_settings_mapping_update', '/_admin/settings/mapping/update', []); | |
58 | pyroutes.register('admin_settings_open_source', '/_admin/settings/open_source', []); |
|
58 | pyroutes.register('admin_settings_open_source', '/_admin/settings/open_source', []); | |
59 | pyroutes.register('admin_settings_process_management', '/_admin/settings/process_management', []); |
|
59 | pyroutes.register('admin_settings_process_management', '/_admin/settings/process_management', []); | |
60 | pyroutes.register('admin_settings_process_management_data', '/_admin/settings/process_management/data', []); |
|
60 | pyroutes.register('admin_settings_process_management_data', '/_admin/settings/process_management/data', []); | |
61 | pyroutes.register('admin_settings_process_management_master_signal', '/_admin/settings/process_management/master_signal', []); |
|
61 | pyroutes.register('admin_settings_process_management_master_signal', '/_admin/settings/process_management/master_signal', []); | |
62 | pyroutes.register('admin_settings_process_management_signal', '/_admin/settings/process_management/signal', []); |
|
62 | pyroutes.register('admin_settings_process_management_signal', '/_admin/settings/process_management/signal', []); | |
63 | pyroutes.register('admin_settings_scheduler_create', '/_admin/settings/scheduler/create', []); |
|
63 | pyroutes.register('admin_settings_scheduler_create', '/_admin/settings/scheduler/create', []); | |
64 | pyroutes.register('admin_settings_scheduler_delete', '/_admin/settings/scheduler/%(schedule_id)s/delete', ['schedule_id']); |
|
64 | pyroutes.register('admin_settings_scheduler_delete', '/_admin/settings/scheduler/%(schedule_id)s/delete', ['schedule_id']); | |
65 | pyroutes.register('admin_settings_scheduler_edit', '/_admin/settings/scheduler/%(schedule_id)s', ['schedule_id']); |
|
65 | pyroutes.register('admin_settings_scheduler_edit', '/_admin/settings/scheduler/%(schedule_id)s', ['schedule_id']); | |
66 | pyroutes.register('admin_settings_scheduler_execute', '/_admin/settings/scheduler/%(schedule_id)s/execute', ['schedule_id']); |
|
66 | pyroutes.register('admin_settings_scheduler_execute', '/_admin/settings/scheduler/%(schedule_id)s/execute', ['schedule_id']); | |
67 | pyroutes.register('admin_settings_scheduler_new', '/_admin/settings/scheduler/new', []); |
|
67 | pyroutes.register('admin_settings_scheduler_new', '/_admin/settings/scheduler/new', []); | |
68 | pyroutes.register('admin_settings_scheduler_show_all', '/_admin/settings/scheduler', []); |
|
68 | pyroutes.register('admin_settings_scheduler_show_all', '/_admin/settings/scheduler', []); | |
69 | pyroutes.register('admin_settings_scheduler_show_tasks', '/_admin/settings/scheduler/_tasks', []); |
|
69 | pyroutes.register('admin_settings_scheduler_show_tasks', '/_admin/settings/scheduler/_tasks', []); | |
70 | pyroutes.register('admin_settings_scheduler_update', '/_admin/settings/scheduler/%(schedule_id)s/update', ['schedule_id']); |
|
70 | pyroutes.register('admin_settings_scheduler_update', '/_admin/settings/scheduler/%(schedule_id)s/update', ['schedule_id']); | |
71 | pyroutes.register('admin_settings_search', '/_admin/settings/search', []); |
|
71 | pyroutes.register('admin_settings_search', '/_admin/settings/search', []); | |
72 | pyroutes.register('admin_settings_sessions', '/_admin/settings/sessions', []); |
|
72 | pyroutes.register('admin_settings_sessions', '/_admin/settings/sessions', []); | |
73 | pyroutes.register('admin_settings_sessions_cleanup', '/_admin/settings/sessions/cleanup', []); |
|
73 | pyroutes.register('admin_settings_sessions_cleanup', '/_admin/settings/sessions/cleanup', []); | |
74 | pyroutes.register('admin_settings_system', '/_admin/settings/system', []); |
|
74 | pyroutes.register('admin_settings_system', '/_admin/settings/system', []); | |
75 | pyroutes.register('admin_settings_system_update', '/_admin/settings/system/updates', []); |
|
75 | pyroutes.register('admin_settings_system_update', '/_admin/settings/system/updates', []); | |
76 | pyroutes.register('admin_settings_update', '/_admin/settings/update', []); |
|
76 | pyroutes.register('admin_settings_update', '/_admin/settings/update', []); | |
77 | pyroutes.register('admin_settings_vcs', '/_admin/settings/vcs', []); |
|
77 | pyroutes.register('admin_settings_vcs', '/_admin/settings/vcs', []); | |
78 | pyroutes.register('admin_settings_vcs_svn_generate_cfg', '/_admin/settings/vcs/svn_generate_cfg', []); |
|
78 | pyroutes.register('admin_settings_vcs_svn_generate_cfg', '/_admin/settings/vcs/svn_generate_cfg', []); | |
79 | pyroutes.register('admin_settings_vcs_svn_pattern_delete', '/_admin/settings/vcs/svn_pattern_delete', []); |
|
79 | pyroutes.register('admin_settings_vcs_svn_pattern_delete', '/_admin/settings/vcs/svn_pattern_delete', []); | |
80 | pyroutes.register('admin_settings_vcs_update', '/_admin/settings/vcs/update', []); |
|
80 | pyroutes.register('admin_settings_vcs_update', '/_admin/settings/vcs/update', []); | |
81 | pyroutes.register('admin_settings_visual', '/_admin/settings/visual', []); |
|
81 | pyroutes.register('admin_settings_visual', '/_admin/settings/visual', []); | |
82 | pyroutes.register('admin_settings_visual_update', '/_admin/settings/visual/update', []); |
|
82 | pyroutes.register('admin_settings_visual_update', '/_admin/settings/visual/update', []); | |
83 | pyroutes.register('apiv2', '/_admin/api', []); |
|
83 | pyroutes.register('apiv2', '/_admin/api', []); | |
84 | pyroutes.register('atom_feed_home', '/%(repo_name)s/feed-atom', ['repo_name']); |
|
84 | pyroutes.register('atom_feed_home', '/%(repo_name)s/feed-atom', ['repo_name']); | |
85 | pyroutes.register('atom_feed_home_old', '/%(repo_name)s/feed/atom', ['repo_name']); |
|
85 | pyroutes.register('atom_feed_home_old', '/%(repo_name)s/feed/atom', ['repo_name']); | |
86 | pyroutes.register('auth_home', '/_admin/auth*traverse', []); |
|
86 | pyroutes.register('auth_home', '/_admin/auth*traverse', []); | |
87 | pyroutes.register('bookmarks_home', '/%(repo_name)s/bookmarks', ['repo_name']); |
|
87 | pyroutes.register('bookmarks_home', '/%(repo_name)s/bookmarks', ['repo_name']); | |
88 | pyroutes.register('branches_home', '/%(repo_name)s/branches', ['repo_name']); |
|
88 | pyroutes.register('branches_home', '/%(repo_name)s/branches', ['repo_name']); | |
89 | pyroutes.register('channelstream_connect', '/_admin/channelstream/connect', []); |
|
89 | pyroutes.register('channelstream_connect', '/_admin/channelstream/connect', []); | |
90 | pyroutes.register('channelstream_proxy', '/_channelstream', []); |
|
90 | pyroutes.register('channelstream_proxy', '/_channelstream', []); | |
91 | pyroutes.register('channelstream_subscribe', '/_admin/channelstream/subscribe', []); |
|
91 | pyroutes.register('channelstream_subscribe', '/_admin/channelstream/subscribe', []); | |
92 | pyroutes.register('commit_draft_comments_submit', '/%(repo_name)s/changeset/%(commit_id)s/draft_comments_submit', ['repo_name', 'commit_id']); |
|
92 | pyroutes.register('commit_draft_comments_submit', '/%(repo_name)s/changeset/%(commit_id)s/draft_comments_submit', ['repo_name', 'commit_id']); | |
93 | pyroutes.register('debug_style_email', '/_admin/debug_style/email/%(email_id)s', ['email_id']); |
|
93 | pyroutes.register('debug_style_email', '/_admin/debug_style/email/%(email_id)s', ['email_id']); | |
94 | pyroutes.register('debug_style_email_plain_rendered', '/_admin/debug_style/email-rendered/%(email_id)s', ['email_id']); |
|
94 | pyroutes.register('debug_style_email_plain_rendered', '/_admin/debug_style/email-rendered/%(email_id)s', ['email_id']); | |
95 | pyroutes.register('debug_style_home', '/_admin/debug_style', []); |
|
95 | pyroutes.register('debug_style_home', '/_admin/debug_style', []); | |
96 | pyroutes.register('debug_style_template', '/_admin/debug_style/t/%(t_path)s', ['t_path']); |
|
96 | pyroutes.register('debug_style_template', '/_admin/debug_style/t/%(t_path)s', ['t_path']); | |
97 | pyroutes.register('download_file', '/_file_store/download/%(fid)s', ['fid']); |
|
97 | pyroutes.register('download_file', '/_file_store/download/%(fid)s', ['fid']); | |
98 | pyroutes.register('download_file_by_token', '/_file_store/token-download/%(_auth_token)s/%(fid)s', ['_auth_token', 'fid']); |
|
98 | pyroutes.register('download_file_by_token', '/_file_store/token-download/%(_auth_token)s/%(fid)s', ['_auth_token', 'fid']); | |
99 | pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']); |
|
99 | pyroutes.register('edit_repo', '/%(repo_name)s/settings', ['repo_name']); | |
100 | pyroutes.register('edit_repo_advanced', '/%(repo_name)s/settings/advanced', ['repo_name']); |
|
100 | pyroutes.register('edit_repo_advanced', '/%(repo_name)s/settings/advanced', ['repo_name']); | |
101 | pyroutes.register('edit_repo_advanced_archive', '/%(repo_name)s/settings/advanced/archive', ['repo_name']); |
|
101 | pyroutes.register('edit_repo_advanced_archive', '/%(repo_name)s/settings/advanced/archive', ['repo_name']); | |
102 | pyroutes.register('edit_repo_advanced_delete', '/%(repo_name)s/settings/advanced/delete', ['repo_name']); |
|
102 | pyroutes.register('edit_repo_advanced_delete', '/%(repo_name)s/settings/advanced/delete', ['repo_name']); | |
103 | pyroutes.register('edit_repo_advanced_fork', '/%(repo_name)s/settings/advanced/fork', ['repo_name']); |
|
103 | pyroutes.register('edit_repo_advanced_fork', '/%(repo_name)s/settings/advanced/fork', ['repo_name']); | |
104 | pyroutes.register('edit_repo_advanced_hooks', '/%(repo_name)s/settings/advanced/hooks', ['repo_name']); |
|
104 | pyroutes.register('edit_repo_advanced_hooks', '/%(repo_name)s/settings/advanced/hooks', ['repo_name']); | |
105 | pyroutes.register('edit_repo_advanced_journal', '/%(repo_name)s/settings/advanced/journal', ['repo_name']); |
|
105 | pyroutes.register('edit_repo_advanced_journal', '/%(repo_name)s/settings/advanced/journal', ['repo_name']); | |
106 | pyroutes.register('edit_repo_advanced_locking', '/%(repo_name)s/settings/advanced/locking', ['repo_name']); |
|
106 | pyroutes.register('edit_repo_advanced_locking', '/%(repo_name)s/settings/advanced/locking', ['repo_name']); | |
107 | pyroutes.register('edit_repo_audit_logs', '/%(repo_name)s/settings/audit_logs', ['repo_name']); |
|
107 | pyroutes.register('edit_repo_audit_logs', '/%(repo_name)s/settings/audit_logs', ['repo_name']); | |
108 | pyroutes.register('edit_repo_caches', '/%(repo_name)s/settings/caches', ['repo_name']); |
|
108 | pyroutes.register('edit_repo_caches', '/%(repo_name)s/settings/caches', ['repo_name']); | |
109 | pyroutes.register('edit_repo_fields', '/%(repo_name)s/settings/fields', ['repo_name']); |
|
109 | pyroutes.register('edit_repo_fields', '/%(repo_name)s/settings/fields', ['repo_name']); | |
110 | pyroutes.register('edit_repo_fields_create', '/%(repo_name)s/settings/fields/create', ['repo_name']); |
|
110 | pyroutes.register('edit_repo_fields_create', '/%(repo_name)s/settings/fields/create', ['repo_name']); | |
111 | pyroutes.register('edit_repo_fields_delete', '/%(repo_name)s/settings/fields/%(field_id)s/delete', ['repo_name', 'field_id']); |
|
111 | pyroutes.register('edit_repo_fields_delete', '/%(repo_name)s/settings/fields/%(field_id)s/delete', ['repo_name', 'field_id']); | |
112 | pyroutes.register('edit_repo_group', '/%(repo_group_name)s/_edit', ['repo_group_name']); |
|
112 | pyroutes.register('edit_repo_group', '/%(repo_group_name)s/_edit', ['repo_group_name']); | |
113 | pyroutes.register('edit_repo_group_advanced', '/%(repo_group_name)s/_settings/advanced', ['repo_group_name']); |
|
113 | pyroutes.register('edit_repo_group_advanced', '/%(repo_group_name)s/_settings/advanced', ['repo_group_name']); | |
114 | pyroutes.register('edit_repo_group_advanced_delete', '/%(repo_group_name)s/_settings/advanced/delete', ['repo_group_name']); |
|
114 | pyroutes.register('edit_repo_group_advanced_delete', '/%(repo_group_name)s/_settings/advanced/delete', ['repo_group_name']); | |
115 | pyroutes.register('edit_repo_group_perms', '/%(repo_group_name)s/_settings/permissions', ['repo_group_name']); |
|
115 | pyroutes.register('edit_repo_group_perms', '/%(repo_group_name)s/_settings/permissions', ['repo_group_name']); | |
116 | pyroutes.register('edit_repo_group_perms_update', '/%(repo_group_name)s/_settings/permissions/update', ['repo_group_name']); |
|
116 | pyroutes.register('edit_repo_group_perms_update', '/%(repo_group_name)s/_settings/permissions/update', ['repo_group_name']); | |
117 | pyroutes.register('edit_repo_issuetracker', '/%(repo_name)s/settings/issue_trackers', ['repo_name']); |
|
117 | pyroutes.register('edit_repo_issuetracker', '/%(repo_name)s/settings/issue_trackers', ['repo_name']); | |
118 | pyroutes.register('edit_repo_issuetracker_delete', '/%(repo_name)s/settings/issue_trackers/delete', ['repo_name']); |
|
118 | pyroutes.register('edit_repo_issuetracker_delete', '/%(repo_name)s/settings/issue_trackers/delete', ['repo_name']); | |
119 | pyroutes.register('edit_repo_issuetracker_test', '/%(repo_name)s/settings/issue_trackers/test', ['repo_name']); |
|
119 | pyroutes.register('edit_repo_issuetracker_test', '/%(repo_name)s/settings/issue_trackers/test', ['repo_name']); | |
120 | pyroutes.register('edit_repo_issuetracker_update', '/%(repo_name)s/settings/issue_trackers/update', ['repo_name']); |
|
120 | pyroutes.register('edit_repo_issuetracker_update', '/%(repo_name)s/settings/issue_trackers/update', ['repo_name']); | |
121 | pyroutes.register('edit_repo_maintenance', '/%(repo_name)s/settings/maintenance', ['repo_name']); |
|
121 | pyroutes.register('edit_repo_maintenance', '/%(repo_name)s/settings/maintenance', ['repo_name']); | |
122 | pyroutes.register('edit_repo_maintenance_execute', '/%(repo_name)s/settings/maintenance/execute', ['repo_name']); |
|
122 | pyroutes.register('edit_repo_maintenance_execute', '/%(repo_name)s/settings/maintenance/execute', ['repo_name']); | |
123 | pyroutes.register('edit_repo_perms', '/%(repo_name)s/settings/permissions', ['repo_name']); |
|
123 | pyroutes.register('edit_repo_perms', '/%(repo_name)s/settings/permissions', ['repo_name']); | |
124 | pyroutes.register('edit_repo_perms_branch', '/%(repo_name)s/settings/branch_permissions', ['repo_name']); |
|
124 | pyroutes.register('edit_repo_perms_branch', '/%(repo_name)s/settings/branch_permissions', ['repo_name']); | |
125 | pyroutes.register('edit_repo_perms_branch_delete', '/%(repo_name)s/settings/branch_permissions/%(rule_id)s/delete', ['repo_name', 'rule_id']); |
|
125 | pyroutes.register('edit_repo_perms_branch_delete', '/%(repo_name)s/settings/branch_permissions/%(rule_id)s/delete', ['repo_name', 'rule_id']); | |
126 | pyroutes.register('edit_repo_perms_set_private', '/%(repo_name)s/settings/permissions/set_private', ['repo_name']); |
|
126 | pyroutes.register('edit_repo_perms_set_private', '/%(repo_name)s/settings/permissions/set_private', ['repo_name']); | |
127 | pyroutes.register('edit_repo_remote', '/%(repo_name)s/settings/remote', ['repo_name']); |
|
127 | pyroutes.register('edit_repo_remote', '/%(repo_name)s/settings/remote', ['repo_name']); | |
128 | pyroutes.register('edit_repo_remote_pull', '/%(repo_name)s/settings/remote/pull', ['repo_name']); |
|
128 | pyroutes.register('edit_repo_remote_pull', '/%(repo_name)s/settings/remote/pull', ['repo_name']); | |
129 | pyroutes.register('edit_repo_remote_push', '/%(repo_name)s/settings/remote/push', ['repo_name']); |
|
129 | pyroutes.register('edit_repo_remote_push', '/%(repo_name)s/settings/remote/push', ['repo_name']); | |
130 | pyroutes.register('edit_repo_statistics', '/%(repo_name)s/settings/statistics', ['repo_name']); |
|
130 | pyroutes.register('edit_repo_statistics', '/%(repo_name)s/settings/statistics', ['repo_name']); | |
131 | pyroutes.register('edit_repo_statistics_reset', '/%(repo_name)s/settings/statistics/update', ['repo_name']); |
|
131 | pyroutes.register('edit_repo_statistics_reset', '/%(repo_name)s/settings/statistics/update', ['repo_name']); | |
132 | pyroutes.register('edit_repo_strip', '/%(repo_name)s/settings/strip', ['repo_name']); |
|
132 | pyroutes.register('edit_repo_strip', '/%(repo_name)s/settings/strip', ['repo_name']); | |
133 | pyroutes.register('edit_repo_vcs', '/%(repo_name)s/settings/vcs', ['repo_name']); |
|
133 | pyroutes.register('edit_repo_vcs', '/%(repo_name)s/settings/vcs', ['repo_name']); | |
134 | pyroutes.register('edit_repo_vcs_svn_pattern_delete', '/%(repo_name)s/settings/vcs/svn_pattern/delete', ['repo_name']); |
|
134 | pyroutes.register('edit_repo_vcs_svn_pattern_delete', '/%(repo_name)s/settings/vcs/svn_pattern/delete', ['repo_name']); | |
135 | pyroutes.register('edit_repo_vcs_update', '/%(repo_name)s/settings/vcs/update', ['repo_name']); |
|
135 | pyroutes.register('edit_repo_vcs_update', '/%(repo_name)s/settings/vcs/update', ['repo_name']); | |
136 | pyroutes.register('edit_user_audit_logs', '/_admin/users/%(user_id)s/edit/audit', ['user_id']); |
|
136 | pyroutes.register('edit_user_audit_logs', '/_admin/users/%(user_id)s/edit/audit', ['user_id']); | |
137 | pyroutes.register('edit_user_audit_logs_download', '/_admin/users/%(user_id)s/edit/audit/download', ['user_id']); |
|
137 | pyroutes.register('edit_user_audit_logs_download', '/_admin/users/%(user_id)s/edit/audit/download', ['user_id']); | |
138 | pyroutes.register('edit_user_auth_tokens', '/_admin/users/%(user_id)s/edit/auth_tokens', ['user_id']); |
|
138 | pyroutes.register('edit_user_auth_tokens', '/_admin/users/%(user_id)s/edit/auth_tokens', ['user_id']); | |
139 | pyroutes.register('edit_user_auth_tokens_add', '/_admin/users/%(user_id)s/edit/auth_tokens/new', ['user_id']); |
|
139 | pyroutes.register('edit_user_auth_tokens_add', '/_admin/users/%(user_id)s/edit/auth_tokens/new', ['user_id']); | |
140 | pyroutes.register('edit_user_auth_tokens_delete', '/_admin/users/%(user_id)s/edit/auth_tokens/delete', ['user_id']); |
|
140 | pyroutes.register('edit_user_auth_tokens_delete', '/_admin/users/%(user_id)s/edit/auth_tokens/delete', ['user_id']); | |
141 | pyroutes.register('edit_user_auth_tokens_view', '/_admin/users/%(user_id)s/edit/auth_tokens/view', ['user_id']); |
|
141 | pyroutes.register('edit_user_auth_tokens_view', '/_admin/users/%(user_id)s/edit/auth_tokens/view', ['user_id']); | |
142 | pyroutes.register('edit_user_caches', '/_admin/users/%(user_id)s/edit/caches', ['user_id']); |
|
142 | pyroutes.register('edit_user_caches', '/_admin/users/%(user_id)s/edit/caches', ['user_id']); | |
143 | pyroutes.register('edit_user_caches_update', '/_admin/users/%(user_id)s/edit/caches/update', ['user_id']); |
|
143 | pyroutes.register('edit_user_caches_update', '/_admin/users/%(user_id)s/edit/caches/update', ['user_id']); | |
144 | pyroutes.register('edit_user_emails', '/_admin/users/%(user_id)s/edit/emails', ['user_id']); |
|
144 | pyroutes.register('edit_user_emails', '/_admin/users/%(user_id)s/edit/emails', ['user_id']); | |
145 | pyroutes.register('edit_user_emails_add', '/_admin/users/%(user_id)s/edit/emails/new', ['user_id']); |
|
145 | pyroutes.register('edit_user_emails_add', '/_admin/users/%(user_id)s/edit/emails/new', ['user_id']); | |
146 | pyroutes.register('edit_user_emails_delete', '/_admin/users/%(user_id)s/edit/emails/delete', ['user_id']); |
|
146 | pyroutes.register('edit_user_emails_delete', '/_admin/users/%(user_id)s/edit/emails/delete', ['user_id']); | |
147 | pyroutes.register('edit_user_group', '/_admin/user_groups/%(user_group_id)s/edit', ['user_group_id']); |
|
147 | pyroutes.register('edit_user_group', '/_admin/user_groups/%(user_group_id)s/edit', ['user_group_id']); | |
148 | pyroutes.register('edit_user_group_advanced', '/_admin/user_groups/%(user_group_id)s/edit/advanced', ['user_group_id']); |
|
148 | pyroutes.register('edit_user_group_advanced', '/_admin/user_groups/%(user_group_id)s/edit/advanced', ['user_group_id']); | |
149 | pyroutes.register('edit_user_group_advanced_sync', '/_admin/user_groups/%(user_group_id)s/edit/advanced/sync', ['user_group_id']); |
|
149 | pyroutes.register('edit_user_group_advanced_sync', '/_admin/user_groups/%(user_group_id)s/edit/advanced/sync', ['user_group_id']); | |
150 | pyroutes.register('edit_user_group_global_perms', '/_admin/user_groups/%(user_group_id)s/edit/global_permissions', ['user_group_id']); |
|
150 | pyroutes.register('edit_user_group_global_perms', '/_admin/user_groups/%(user_group_id)s/edit/global_permissions', ['user_group_id']); | |
151 | pyroutes.register('edit_user_group_global_perms_update', '/_admin/user_groups/%(user_group_id)s/edit/global_permissions/update', ['user_group_id']); |
|
151 | pyroutes.register('edit_user_group_global_perms_update', '/_admin/user_groups/%(user_group_id)s/edit/global_permissions/update', ['user_group_id']); | |
152 | pyroutes.register('edit_user_group_perms', '/_admin/user_groups/%(user_group_id)s/edit/permissions', ['user_group_id']); |
|
152 | pyroutes.register('edit_user_group_perms', '/_admin/user_groups/%(user_group_id)s/edit/permissions', ['user_group_id']); | |
153 | pyroutes.register('edit_user_group_perms_summary', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary', ['user_group_id']); |
|
153 | pyroutes.register('edit_user_group_perms_summary', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary', ['user_group_id']); | |
154 | pyroutes.register('edit_user_group_perms_summary_json', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary/json', ['user_group_id']); |
|
154 | pyroutes.register('edit_user_group_perms_summary_json', '/_admin/user_groups/%(user_group_id)s/edit/permissions_summary/json', ['user_group_id']); | |
155 | pyroutes.register('edit_user_group_perms_update', '/_admin/user_groups/%(user_group_id)s/edit/permissions/update', ['user_group_id']); |
|
155 | pyroutes.register('edit_user_group_perms_update', '/_admin/user_groups/%(user_group_id)s/edit/permissions/update', ['user_group_id']); | |
156 | pyroutes.register('edit_user_groups_management', '/_admin/users/%(user_id)s/edit/groups_management', ['user_id']); |
|
156 | pyroutes.register('edit_user_groups_management', '/_admin/users/%(user_id)s/edit/groups_management', ['user_id']); | |
157 | pyroutes.register('edit_user_groups_management_updates', '/_admin/users/%(user_id)s/edit/edit_user_groups_management/updates', ['user_id']); |
|
157 | pyroutes.register('edit_user_groups_management_updates', '/_admin/users/%(user_id)s/edit/edit_user_groups_management/updates', ['user_id']); | |
158 | pyroutes.register('edit_user_ips', '/_admin/users/%(user_id)s/edit/ips', ['user_id']); |
|
158 | pyroutes.register('edit_user_ips', '/_admin/users/%(user_id)s/edit/ips', ['user_id']); | |
159 | pyroutes.register('edit_user_ips_add', '/_admin/users/%(user_id)s/edit/ips/new', ['user_id']); |
|
159 | pyroutes.register('edit_user_ips_add', '/_admin/users/%(user_id)s/edit/ips/new', ['user_id']); | |
160 | pyroutes.register('edit_user_ips_delete', '/_admin/users/%(user_id)s/edit/ips/delete', ['user_id']); |
|
160 | pyroutes.register('edit_user_ips_delete', '/_admin/users/%(user_id)s/edit/ips/delete', ['user_id']); | |
161 | pyroutes.register('edit_user_perms_summary', '/_admin/users/%(user_id)s/edit/permissions_summary', ['user_id']); |
|
161 | pyroutes.register('edit_user_perms_summary', '/_admin/users/%(user_id)s/edit/permissions_summary', ['user_id']); | |
162 | pyroutes.register('edit_user_perms_summary_json', '/_admin/users/%(user_id)s/edit/permissions_summary/json', ['user_id']); |
|
162 | pyroutes.register('edit_user_perms_summary_json', '/_admin/users/%(user_id)s/edit/permissions_summary/json', ['user_id']); | |
163 | pyroutes.register('edit_user_ssh_keys', '/_admin/users/%(user_id)s/edit/ssh_keys', ['user_id']); |
|
163 | pyroutes.register('edit_user_ssh_keys', '/_admin/users/%(user_id)s/edit/ssh_keys', ['user_id']); | |
164 | pyroutes.register('edit_user_ssh_keys_add', '/_admin/users/%(user_id)s/edit/ssh_keys/new', ['user_id']); |
|
164 | pyroutes.register('edit_user_ssh_keys_add', '/_admin/users/%(user_id)s/edit/ssh_keys/new', ['user_id']); | |
165 | pyroutes.register('edit_user_ssh_keys_delete', '/_admin/users/%(user_id)s/edit/ssh_keys/delete', ['user_id']); |
|
165 | pyroutes.register('edit_user_ssh_keys_delete', '/_admin/users/%(user_id)s/edit/ssh_keys/delete', ['user_id']); | |
166 | pyroutes.register('edit_user_ssh_keys_generate_keypair', '/_admin/users/%(user_id)s/edit/ssh_keys/generate', ['user_id']); |
|
166 | pyroutes.register('edit_user_ssh_keys_generate_keypair', '/_admin/users/%(user_id)s/edit/ssh_keys/generate', ['user_id']); | |
167 | pyroutes.register('favicon', '/favicon.ico', []); |
|
167 | pyroutes.register('favicon', '/favicon.ico', []); | |
168 | pyroutes.register('file_preview', '/_file_preview', []); |
|
168 | pyroutes.register('file_preview', '/_file_preview', []); | |
169 | pyroutes.register('gist_delete', '/_admin/gists/%(gist_id)s/delete', ['gist_id']); |
|
169 | pyroutes.register('gist_delete', '/_admin/gists/%(gist_id)s/delete', ['gist_id']); | |
170 | pyroutes.register('gist_edit', '/_admin/gists/%(gist_id)s/edit', ['gist_id']); |
|
170 | pyroutes.register('gist_edit', '/_admin/gists/%(gist_id)s/edit', ['gist_id']); | |
171 | pyroutes.register('gist_edit_check_revision', '/_admin/gists/%(gist_id)s/edit/check_revision', ['gist_id']); |
|
171 | pyroutes.register('gist_edit_check_revision', '/_admin/gists/%(gist_id)s/edit/check_revision', ['gist_id']); | |
172 | pyroutes.register('gist_show', '/_admin/gists/%(gist_id)s', ['gist_id']); |
|
172 | pyroutes.register('gist_show', '/_admin/gists/%(gist_id)s', ['gist_id']); | |
173 | pyroutes.register('gist_show_formatted', '/_admin/gists/%(gist_id)s/rev/%(revision)s/%(format)s', ['gist_id', 'revision', 'format']); |
|
173 | pyroutes.register('gist_show_formatted', '/_admin/gists/%(gist_id)s/rev/%(revision)s/%(format)s', ['gist_id', 'revision', 'format']); | |
174 | pyroutes.register('gist_show_formatted_path', '/_admin/gists/%(gist_id)s/rev/%(revision)s/%(format)s/%(f_path)s', ['gist_id', 'revision', 'format', 'f_path']); |
|
174 | pyroutes.register('gist_show_formatted_path', '/_admin/gists/%(gist_id)s/rev/%(revision)s/%(format)s/%(f_path)s', ['gist_id', 'revision', 'format', 'f_path']); | |
175 | pyroutes.register('gist_show_rev', '/_admin/gists/%(gist_id)s/rev/%(revision)s', ['gist_id', 'revision']); |
|
175 | pyroutes.register('gist_show_rev', '/_admin/gists/%(gist_id)s/rev/%(revision)s', ['gist_id', 'revision']); | |
176 | pyroutes.register('gist_update', '/_admin/gists/%(gist_id)s/update', ['gist_id']); |
|
176 | pyroutes.register('gist_update', '/_admin/gists/%(gist_id)s/update', ['gist_id']); | |
177 | pyroutes.register('gists_create', '/_admin/gists/create', []); |
|
177 | pyroutes.register('gists_create', '/_admin/gists/create', []); | |
178 | pyroutes.register('gists_new', '/_admin/gists/new', []); |
|
178 | pyroutes.register('gists_new', '/_admin/gists/new', []); | |
179 | pyroutes.register('gists_show', '/_admin/gists', []); |
|
179 | pyroutes.register('gists_show', '/_admin/gists', []); | |
180 | pyroutes.register('global_integrations_create', '/_admin/integrations/%(integration)s/new', ['integration']); |
|
180 | pyroutes.register('global_integrations_create', '/_admin/integrations/%(integration)s/new', ['integration']); | |
181 | pyroutes.register('global_integrations_edit', '/_admin/integrations/%(integration)s/%(integration_id)s', ['integration', 'integration_id']); |
|
181 | pyroutes.register('global_integrations_edit', '/_admin/integrations/%(integration)s/%(integration_id)s', ['integration', 'integration_id']); | |
182 | pyroutes.register('global_integrations_home', '/_admin/integrations', []); |
|
182 | pyroutes.register('global_integrations_home', '/_admin/integrations', []); | |
183 | pyroutes.register('global_integrations_list', '/_admin/integrations/%(integration)s', ['integration']); |
|
183 | pyroutes.register('global_integrations_list', '/_admin/integrations/%(integration)s', ['integration']); | |
184 | pyroutes.register('global_integrations_new', '/_admin/integrations/new', []); |
|
184 | pyroutes.register('global_integrations_new', '/_admin/integrations/new', []); | |
185 | pyroutes.register('goto_switcher_data', '/_goto_data', []); |
|
185 | pyroutes.register('goto_switcher_data', '/_goto_data', []); | |
186 | pyroutes.register('home', '/', []); |
|
186 | pyroutes.register('home', '/', []); | |
187 | pyroutes.register('hovercard_pull_request', '/_hovercard/pull_request/%(pull_request_id)s', ['pull_request_id']); |
|
187 | pyroutes.register('hovercard_pull_request', '/_hovercard/pull_request/%(pull_request_id)s', ['pull_request_id']); | |
188 | pyroutes.register('hovercard_repo_commit', '/_hovercard/commit/%(repo_name)s/%(commit_id)s', ['repo_name', 'commit_id']); |
|
188 | pyroutes.register('hovercard_repo_commit', '/_hovercard/commit/%(repo_name)s/%(commit_id)s', ['repo_name', 'commit_id']); | |
189 | pyroutes.register('hovercard_user', '/_hovercard/user/%(user_id)s', ['user_id']); |
|
189 | pyroutes.register('hovercard_user', '/_hovercard/user/%(user_id)s', ['user_id']); | |
190 | pyroutes.register('hovercard_user_group', '/_hovercard/user_group/%(user_group_id)s', ['user_group_id']); |
|
190 | pyroutes.register('hovercard_user_group', '/_hovercard/user_group/%(user_group_id)s', ['user_group_id']); | |
191 | pyroutes.register('hovercard_username', '/_hovercard/username/%(username)s', ['username']); |
|
191 | pyroutes.register('hovercard_username', '/_hovercard/username/%(username)s', ['username']); | |
192 | pyroutes.register('journal', '/_admin/journal', []); |
|
192 | pyroutes.register('journal', '/_admin/journal', []); | |
193 | pyroutes.register('journal_atom', '/_admin/journal/atom', []); |
|
193 | pyroutes.register('journal_atom', '/_admin/journal/atom', []); | |
194 | pyroutes.register('journal_public', '/_admin/public_journal', []); |
|
194 | pyroutes.register('journal_public', '/_admin/public_journal', []); | |
195 | pyroutes.register('journal_public_atom', '/_admin/public_journal/atom', []); |
|
195 | pyroutes.register('journal_public_atom', '/_admin/public_journal/atom', []); | |
196 | pyroutes.register('journal_public_atom_old', '/_admin/public_journal_atom', []); |
|
196 | pyroutes.register('journal_public_atom_old', '/_admin/public_journal_atom', []); | |
197 | pyroutes.register('journal_public_rss', '/_admin/public_journal/rss', []); |
|
197 | pyroutes.register('journal_public_rss', '/_admin/public_journal/rss', []); | |
198 | pyroutes.register('journal_public_rss_old', '/_admin/public_journal_rss', []); |
|
198 | pyroutes.register('journal_public_rss_old', '/_admin/public_journal_rss', []); | |
199 | pyroutes.register('journal_rss', '/_admin/journal/rss', []); |
|
199 | pyroutes.register('journal_rss', '/_admin/journal/rss', []); | |
200 | pyroutes.register('login', '/_admin/login', []); |
|
200 | pyroutes.register('login', '/_admin/login', []); | |
201 | pyroutes.register('logout', '/_admin/logout', []); |
|
201 | pyroutes.register('logout', '/_admin/logout', []); | |
202 | pyroutes.register('main_page_repo_groups_data', '/_home_repo_groups', []); |
|
202 | pyroutes.register('main_page_repo_groups_data', '/_home_repo_groups', []); | |
203 | pyroutes.register('main_page_repos_data', '/_home_repos', []); |
|
203 | pyroutes.register('main_page_repos_data', '/_home_repos', []); | |
204 | pyroutes.register('markup_preview', '/_markup_preview', []); |
|
204 | pyroutes.register('markup_preview', '/_markup_preview', []); | |
205 | pyroutes.register('my_account_auth_tokens', '/_admin/my_account/auth_tokens', []); |
|
205 | pyroutes.register('my_account_auth_tokens', '/_admin/my_account/auth_tokens', []); | |
206 | pyroutes.register('my_account_auth_tokens_add', '/_admin/my_account/auth_tokens/new', []); |
|
206 | pyroutes.register('my_account_auth_tokens_add', '/_admin/my_account/auth_tokens/new', []); | |
207 | pyroutes.register('my_account_auth_tokens_delete', '/_admin/my_account/auth_tokens/delete', []); |
|
207 | pyroutes.register('my_account_auth_tokens_delete', '/_admin/my_account/auth_tokens/delete', []); | |
208 | pyroutes.register('my_account_auth_tokens_view', '/_admin/my_account/auth_tokens/view', []); |
|
208 | pyroutes.register('my_account_auth_tokens_view', '/_admin/my_account/auth_tokens/view', []); | |
209 | pyroutes.register('my_account_bookmarks', '/_admin/my_account/bookmarks', []); |
|
209 | pyroutes.register('my_account_bookmarks', '/_admin/my_account/bookmarks', []); | |
210 | pyroutes.register('my_account_bookmarks_update', '/_admin/my_account/bookmarks/update', []); |
|
210 | pyroutes.register('my_account_bookmarks_update', '/_admin/my_account/bookmarks/update', []); | |
211 | pyroutes.register('my_account_edit', '/_admin/my_account/edit', []); |
|
211 | pyroutes.register('my_account_edit', '/_admin/my_account/edit', []); | |
212 | pyroutes.register('my_account_emails', '/_admin/my_account/emails', []); |
|
212 | pyroutes.register('my_account_emails', '/_admin/my_account/emails', []); | |
213 | pyroutes.register('my_account_emails_add', '/_admin/my_account/emails/new', []); |
|
213 | pyroutes.register('my_account_emails_add', '/_admin/my_account/emails/new', []); | |
214 | pyroutes.register('my_account_emails_delete', '/_admin/my_account/emails/delete', []); |
|
214 | pyroutes.register('my_account_emails_delete', '/_admin/my_account/emails/delete', []); | |
215 | pyroutes.register('my_account_external_identity', '/_admin/my_account/external-identity', []); |
|
215 | pyroutes.register('my_account_external_identity', '/_admin/my_account/external-identity', []); | |
216 | pyroutes.register('my_account_external_identity_delete', '/_admin/my_account/external-identity/delete', []); |
|
216 | pyroutes.register('my_account_external_identity_delete', '/_admin/my_account/external-identity/delete', []); | |
217 | pyroutes.register('my_account_goto_bookmark', '/_admin/my_account/bookmark/%(bookmark_id)s', ['bookmark_id']); |
|
217 | pyroutes.register('my_account_goto_bookmark', '/_admin/my_account/bookmark/%(bookmark_id)s', ['bookmark_id']); | |
218 | pyroutes.register('my_account_notifications', '/_admin/my_account/notifications', []); |
|
218 | pyroutes.register('my_account_notifications', '/_admin/my_account/notifications', []); | |
219 | pyroutes.register('my_account_notifications_test_channelstream', '/_admin/my_account/test_channelstream', []); |
|
219 | pyroutes.register('my_account_notifications_test_channelstream', '/_admin/my_account/test_channelstream', []); | |
220 | pyroutes.register('my_account_notifications_toggle_visibility', '/_admin/my_account/toggle_visibility', []); |
|
220 | pyroutes.register('my_account_notifications_toggle_visibility', '/_admin/my_account/toggle_visibility', []); | |
221 | pyroutes.register('my_account_password', '/_admin/my_account/password', []); |
|
221 | pyroutes.register('my_account_password', '/_admin/my_account/password', []); | |
222 | pyroutes.register('my_account_password_update', '/_admin/my_account/password/update', []); |
|
222 | pyroutes.register('my_account_password_update', '/_admin/my_account/password/update', []); | |
223 | pyroutes.register('my_account_perms', '/_admin/my_account/perms', []); |
|
223 | pyroutes.register('my_account_perms', '/_admin/my_account/perms', []); | |
224 | pyroutes.register('my_account_profile', '/_admin/my_account/profile', []); |
|
224 | pyroutes.register('my_account_profile', '/_admin/my_account/profile', []); | |
225 | pyroutes.register('my_account_pullrequests', '/_admin/my_account/pull_requests', []); |
|
225 | pyroutes.register('my_account_pullrequests', '/_admin/my_account/pull_requests', []); | |
226 | pyroutes.register('my_account_pullrequests_data', '/_admin/my_account/pull_requests/data', []); |
|
226 | pyroutes.register('my_account_pullrequests_data', '/_admin/my_account/pull_requests/data', []); | |
227 | pyroutes.register('my_account_repos', '/_admin/my_account/repos', []); |
|
227 | pyroutes.register('my_account_repos', '/_admin/my_account/repos', []); | |
228 | pyroutes.register('my_account_ssh_keys', '/_admin/my_account/ssh_keys', []); |
|
228 | pyroutes.register('my_account_ssh_keys', '/_admin/my_account/ssh_keys', []); | |
229 | pyroutes.register('my_account_ssh_keys_add', '/_admin/my_account/ssh_keys/new', []); |
|
229 | pyroutes.register('my_account_ssh_keys_add', '/_admin/my_account/ssh_keys/new', []); | |
230 | pyroutes.register('my_account_ssh_keys_delete', '/_admin/my_account/ssh_keys/delete', []); |
|
230 | pyroutes.register('my_account_ssh_keys_delete', '/_admin/my_account/ssh_keys/delete', []); | |
231 | pyroutes.register('my_account_ssh_keys_generate', '/_admin/my_account/ssh_keys/generate', []); |
|
231 | pyroutes.register('my_account_ssh_keys_generate', '/_admin/my_account/ssh_keys/generate', []); | |
232 | pyroutes.register('my_account_update', '/_admin/my_account/update', []); |
|
232 | pyroutes.register('my_account_update', '/_admin/my_account/update', []); | |
233 | pyroutes.register('my_account_user_group_membership', '/_admin/my_account/user_group_membership', []); |
|
233 | pyroutes.register('my_account_user_group_membership', '/_admin/my_account/user_group_membership', []); | |
234 | pyroutes.register('my_account_watched', '/_admin/my_account/watched', []); |
|
234 | pyroutes.register('my_account_watched', '/_admin/my_account/watched', []); | |
235 | pyroutes.register('notifications_delete', '/_admin/notifications/%(notification_id)s/delete', ['notification_id']); |
|
235 | pyroutes.register('notifications_delete', '/_admin/notifications/%(notification_id)s/delete', ['notification_id']); | |
236 | pyroutes.register('notifications_mark_all_read', '/_admin/notifications_mark_all_read', []); |
|
236 | pyroutes.register('notifications_mark_all_read', '/_admin/notifications_mark_all_read', []); | |
237 | pyroutes.register('notifications_show', '/_admin/notifications/%(notification_id)s', ['notification_id']); |
|
237 | pyroutes.register('notifications_show', '/_admin/notifications/%(notification_id)s', ['notification_id']); | |
238 | pyroutes.register('notifications_show_all', '/_admin/notifications', []); |
|
238 | pyroutes.register('notifications_show_all', '/_admin/notifications', []); | |
239 | pyroutes.register('notifications_update', '/_admin/notifications/%(notification_id)s/update', ['notification_id']); |
|
239 | pyroutes.register('notifications_update', '/_admin/notifications/%(notification_id)s/update', ['notification_id']); | |
240 | pyroutes.register('ops_error_test', '/_admin/ops/error', []); |
|
240 | pyroutes.register('ops_error_test', '/_admin/ops/error', []); | |
241 | pyroutes.register('ops_ping', '/_admin/ops/ping', []); |
|
241 | pyroutes.register('ops_ping', '/_admin/ops/ping', []); | |
242 | pyroutes.register('ops_redirect_test', '/_admin/ops/redirect', []); |
|
242 | pyroutes.register('ops_redirect_test', '/_admin/ops/redirect', []); | |
243 | pyroutes.register('plugin_admin_chat', '/_admin/plugin_admin_chat/%(action)s', ['action']); |
|
243 | pyroutes.register('plugin_admin_chat', '/_admin/plugin_admin_chat/%(action)s', ['action']); | |
244 | pyroutes.register('pull_requests_global', '/_admin/pull-request/%(pull_request_id)s', ['pull_request_id']); |
|
244 | pyroutes.register('pull_requests_global', '/_admin/pull-request/%(pull_request_id)s', ['pull_request_id']); | |
245 | pyroutes.register('pull_requests_global_0', '/_admin/pull_requests/%(pull_request_id)s', ['pull_request_id']); |
|
245 | pyroutes.register('pull_requests_global_0', '/_admin/pull_requests/%(pull_request_id)s', ['pull_request_id']); | |
246 | pyroutes.register('pull_requests_global_1', '/_admin/pull-requests/%(pull_request_id)s', ['pull_request_id']); |
|
246 | pyroutes.register('pull_requests_global_1', '/_admin/pull-requests/%(pull_request_id)s', ['pull_request_id']); | |
247 | pyroutes.register('pullrequest_comment_create', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment', ['repo_name', 'pull_request_id']); |
|
247 | pyroutes.register('pullrequest_comment_create', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment', ['repo_name', 'pull_request_id']); | |
248 | pyroutes.register('pullrequest_comment_delete', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment/%(comment_id)s/delete', ['repo_name', 'pull_request_id', 'comment_id']); |
|
248 | pyroutes.register('pullrequest_comment_delete', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment/%(comment_id)s/delete', ['repo_name', 'pull_request_id', 'comment_id']); | |
249 | pyroutes.register('pullrequest_comment_edit', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment/%(comment_id)s/edit', ['repo_name', 'pull_request_id', 'comment_id']); |
|
249 | pyroutes.register('pullrequest_comment_edit', '/%(repo_name)s/pull-request/%(pull_request_id)s/comment/%(comment_id)s/edit', ['repo_name', 'pull_request_id', 'comment_id']); | |
250 | pyroutes.register('pullrequest_comments', '/%(repo_name)s/pull-request/%(pull_request_id)s/comments', ['repo_name', 'pull_request_id']); |
|
250 | pyroutes.register('pullrequest_comments', '/%(repo_name)s/pull-request/%(pull_request_id)s/comments', ['repo_name', 'pull_request_id']); | |
251 | pyroutes.register('pullrequest_create', '/%(repo_name)s/pull-request/create', ['repo_name']); |
|
251 | pyroutes.register('pullrequest_create', '/%(repo_name)s/pull-request/create', ['repo_name']); | |
252 | pyroutes.register('pullrequest_delete', '/%(repo_name)s/pull-request/%(pull_request_id)s/delete', ['repo_name', 'pull_request_id']); |
|
252 | pyroutes.register('pullrequest_delete', '/%(repo_name)s/pull-request/%(pull_request_id)s/delete', ['repo_name', 'pull_request_id']); | |
253 | pyroutes.register('pullrequest_draft_comments_submit', '/%(repo_name)s/pull-request/%(pull_request_id)s/draft_comments_submit', ['repo_name', 'pull_request_id']); |
|
253 | pyroutes.register('pullrequest_draft_comments_submit', '/%(repo_name)s/pull-request/%(pull_request_id)s/draft_comments_submit', ['repo_name', 'pull_request_id']); | |
254 | pyroutes.register('pullrequest_drafts', '/%(repo_name)s/pull-request/%(pull_request_id)s/drafts', ['repo_name', 'pull_request_id']); |
|
254 | pyroutes.register('pullrequest_drafts', '/%(repo_name)s/pull-request/%(pull_request_id)s/drafts', ['repo_name', 'pull_request_id']); | |
255 | pyroutes.register('pullrequest_merge', '/%(repo_name)s/pull-request/%(pull_request_id)s/merge', ['repo_name', 'pull_request_id']); |
|
255 | pyroutes.register('pullrequest_merge', '/%(repo_name)s/pull-request/%(pull_request_id)s/merge', ['repo_name', 'pull_request_id']); | |
256 | pyroutes.register('pullrequest_new', '/%(repo_name)s/pull-request/new', ['repo_name']); |
|
256 | pyroutes.register('pullrequest_new', '/%(repo_name)s/pull-request/new', ['repo_name']); | |
257 | pyroutes.register('pullrequest_repo_refs', '/%(repo_name)s/pull-request/refs/%(target_repo_name)s', ['repo_name', 'target_repo_name']); |
|
257 | pyroutes.register('pullrequest_repo_refs', '/%(repo_name)s/pull-request/refs/%(target_repo_name)s', ['repo_name', 'target_repo_name']); | |
258 | pyroutes.register('pullrequest_repo_targets', '/%(repo_name)s/pull-request/repo-targets', ['repo_name']); |
|
258 | pyroutes.register('pullrequest_repo_targets', '/%(repo_name)s/pull-request/repo-targets', ['repo_name']); | |
259 | pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']); |
|
259 | pyroutes.register('pullrequest_show', '/%(repo_name)s/pull-request/%(pull_request_id)s', ['repo_name', 'pull_request_id']); | |
260 | pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']); |
|
260 | pyroutes.register('pullrequest_show_all', '/%(repo_name)s/pull-request', ['repo_name']); | |
261 | pyroutes.register('pullrequest_show_all_data', '/%(repo_name)s/pull-request-data', ['repo_name']); |
|
261 | pyroutes.register('pullrequest_show_all_data', '/%(repo_name)s/pull-request-data', ['repo_name']); | |
262 | pyroutes.register('pullrequest_todos', '/%(repo_name)s/pull-request/%(pull_request_id)s/todos', ['repo_name', 'pull_request_id']); |
|
262 | pyroutes.register('pullrequest_todos', '/%(repo_name)s/pull-request/%(pull_request_id)s/todos', ['repo_name', 'pull_request_id']); | |
263 | pyroutes.register('pullrequest_update', '/%(repo_name)s/pull-request/%(pull_request_id)s/update', ['repo_name', 'pull_request_id']); |
|
263 | pyroutes.register('pullrequest_update', '/%(repo_name)s/pull-request/%(pull_request_id)s/update', ['repo_name', 'pull_request_id']); | |
264 | pyroutes.register('register', '/_admin/register', []); |
|
264 | pyroutes.register('register', '/_admin/register', []); | |
265 | pyroutes.register('repo_archivefile', '/%(repo_name)s/archive/%(fname)s', ['repo_name', 'fname']); |
|
265 | pyroutes.register('repo_archivefile', '/%(repo_name)s/archive/%(fname)s', ['repo_name', 'fname']); | |
266 | pyroutes.register('repo_artifacts_data', '/%(repo_name)s/artifacts_data', ['repo_name']); |
|
266 | pyroutes.register('repo_artifacts_data', '/%(repo_name)s/artifacts_data', ['repo_name']); | |
267 | pyroutes.register('repo_artifacts_delete', '/%(repo_name)s/artifacts/delete/%(uid)s', ['repo_name', 'uid']); |
|
267 | pyroutes.register('repo_artifacts_delete', '/%(repo_name)s/artifacts/delete/%(uid)s', ['repo_name', 'uid']); | |
268 | pyroutes.register('repo_artifacts_get', '/%(repo_name)s/artifacts/download/%(uid)s', ['repo_name', 'uid']); |
|
268 | pyroutes.register('repo_artifacts_get', '/%(repo_name)s/artifacts/download/%(uid)s', ['repo_name', 'uid']); | |
269 | pyroutes.register('repo_artifacts_info', '/%(repo_name)s/artifacts/info/%(uid)s', ['repo_name', 'uid']); |
|
269 | pyroutes.register('repo_artifacts_info', '/%(repo_name)s/artifacts/info/%(uid)s', ['repo_name', 'uid']); | |
270 | pyroutes.register('repo_artifacts_list', '/%(repo_name)s/artifacts', ['repo_name']); |
|
270 | pyroutes.register('repo_artifacts_list', '/%(repo_name)s/artifacts', ['repo_name']); | |
271 | pyroutes.register('repo_artifacts_new', '/%(repo_name)s/artifacts/new', ['repo_name']); |
|
271 | pyroutes.register('repo_artifacts_new', '/%(repo_name)s/artifacts/new', ['repo_name']); | |
272 | pyroutes.register('repo_artifacts_store', '/%(repo_name)s/artifacts/store', ['repo_name']); |
|
272 | pyroutes.register('repo_artifacts_store', '/%(repo_name)s/artifacts/store', ['repo_name']); | |
|
273 | pyroutes.register('repo_artifacts_stream_script', '/_file_store/stream-upload-script', []); | |||
|
274 | pyroutes.register('repo_artifacts_stream_store', '/_file_store/stream-upload', []); | |||
273 | pyroutes.register('repo_artifacts_update', '/%(repo_name)s/artifacts/update/%(uid)s', ['repo_name', 'uid']); |
|
275 | pyroutes.register('repo_artifacts_update', '/%(repo_name)s/artifacts/update/%(uid)s', ['repo_name', 'uid']); | |
274 | pyroutes.register('repo_automation', '/%(repo_name)s/settings/automation', ['repo_name']); |
|
276 | pyroutes.register('repo_automation', '/%(repo_name)s/settings/automation', ['repo_name']); | |
275 | pyroutes.register('repo_automation_update', '/%(repo_name)s/settings/automation/%(entry_id)s/update', ['repo_name', 'entry_id']); |
|
277 | pyroutes.register('repo_automation_update', '/%(repo_name)s/settings/automation/%(entry_id)s/update', ['repo_name', 'entry_id']); | |
276 | pyroutes.register('repo_changelog', '/%(repo_name)s/changelog', ['repo_name']); |
|
278 | pyroutes.register('repo_changelog', '/%(repo_name)s/changelog', ['repo_name']); | |
277 | pyroutes.register('repo_changelog_file', '/%(repo_name)s/changelog/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
279 | pyroutes.register('repo_changelog_file', '/%(repo_name)s/changelog/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
278 | pyroutes.register('repo_commit', '/%(repo_name)s/changeset/%(commit_id)s', ['repo_name', 'commit_id']); |
|
280 | pyroutes.register('repo_commit', '/%(repo_name)s/changeset/%(commit_id)s', ['repo_name', 'commit_id']); | |
279 | pyroutes.register('repo_commit_children', '/%(repo_name)s/changeset_children/%(commit_id)s', ['repo_name', 'commit_id']); |
|
281 | pyroutes.register('repo_commit_children', '/%(repo_name)s/changeset_children/%(commit_id)s', ['repo_name', 'commit_id']); | |
280 | pyroutes.register('repo_commit_comment_attachment_upload', '/%(repo_name)s/changeset/%(commit_id)s/comment/attachment_upload', ['repo_name', 'commit_id']); |
|
282 | pyroutes.register('repo_commit_comment_attachment_upload', '/%(repo_name)s/changeset/%(commit_id)s/comment/attachment_upload', ['repo_name', 'commit_id']); | |
281 | pyroutes.register('repo_commit_comment_create', '/%(repo_name)s/changeset/%(commit_id)s/comment/create', ['repo_name', 'commit_id']); |
|
283 | pyroutes.register('repo_commit_comment_create', '/%(repo_name)s/changeset/%(commit_id)s/comment/create', ['repo_name', 'commit_id']); | |
282 | pyroutes.register('repo_commit_comment_delete', '/%(repo_name)s/changeset/%(commit_id)s/comment/%(comment_id)s/delete', ['repo_name', 'commit_id', 'comment_id']); |
|
284 | pyroutes.register('repo_commit_comment_delete', '/%(repo_name)s/changeset/%(commit_id)s/comment/%(comment_id)s/delete', ['repo_name', 'commit_id', 'comment_id']); | |
283 | pyroutes.register('repo_commit_comment_edit', '/%(repo_name)s/changeset/%(commit_id)s/comment/%(comment_id)s/edit', ['repo_name', 'commit_id', 'comment_id']); |
|
285 | pyroutes.register('repo_commit_comment_edit', '/%(repo_name)s/changeset/%(commit_id)s/comment/%(comment_id)s/edit', ['repo_name', 'commit_id', 'comment_id']); | |
284 | pyroutes.register('repo_commit_comment_history_view', '/%(repo_name)s/changeset/%(commit_id)s/comment/%(comment_history_id)s/history_view', ['repo_name', 'commit_id', 'comment_history_id']); |
|
286 | pyroutes.register('repo_commit_comment_history_view', '/%(repo_name)s/changeset/%(commit_id)s/comment/%(comment_history_id)s/history_view', ['repo_name', 'commit_id', 'comment_history_id']); | |
285 | pyroutes.register('repo_commit_comment_preview', '/%(repo_name)s/changeset/%(commit_id)s/comment/preview', ['repo_name', 'commit_id']); |
|
287 | pyroutes.register('repo_commit_comment_preview', '/%(repo_name)s/changeset/%(commit_id)s/comment/preview', ['repo_name', 'commit_id']); | |
286 | pyroutes.register('repo_commit_data', '/%(repo_name)s/changeset-data/%(commit_id)s', ['repo_name', 'commit_id']); |
|
288 | pyroutes.register('repo_commit_data', '/%(repo_name)s/changeset-data/%(commit_id)s', ['repo_name', 'commit_id']); | |
287 | pyroutes.register('repo_commit_download', '/%(repo_name)s/changeset-download/%(commit_id)s', ['repo_name', 'commit_id']); |
|
289 | pyroutes.register('repo_commit_download', '/%(repo_name)s/changeset-download/%(commit_id)s', ['repo_name', 'commit_id']); | |
288 | pyroutes.register('repo_commit_parents', '/%(repo_name)s/changeset_parents/%(commit_id)s', ['repo_name', 'commit_id']); |
|
290 | pyroutes.register('repo_commit_parents', '/%(repo_name)s/changeset_parents/%(commit_id)s', ['repo_name', 'commit_id']); | |
289 | pyroutes.register('repo_commit_patch', '/%(repo_name)s/changeset-patch/%(commit_id)s', ['repo_name', 'commit_id']); |
|
291 | pyroutes.register('repo_commit_patch', '/%(repo_name)s/changeset-patch/%(commit_id)s', ['repo_name', 'commit_id']); | |
290 | pyroutes.register('repo_commit_raw', '/%(repo_name)s/changeset-diff/%(commit_id)s', ['repo_name', 'commit_id']); |
|
292 | pyroutes.register('repo_commit_raw', '/%(repo_name)s/changeset-diff/%(commit_id)s', ['repo_name', 'commit_id']); | |
291 | pyroutes.register('repo_commit_raw_deprecated', '/%(repo_name)s/raw-changeset/%(commit_id)s', ['repo_name', 'commit_id']); |
|
293 | pyroutes.register('repo_commit_raw_deprecated', '/%(repo_name)s/raw-changeset/%(commit_id)s', ['repo_name', 'commit_id']); | |
292 | pyroutes.register('repo_commits', '/%(repo_name)s/commits', ['repo_name']); |
|
294 | pyroutes.register('repo_commits', '/%(repo_name)s/commits', ['repo_name']); | |
293 | pyroutes.register('repo_commits_elements', '/%(repo_name)s/commits_elements', ['repo_name']); |
|
295 | pyroutes.register('repo_commits_elements', '/%(repo_name)s/commits_elements', ['repo_name']); | |
294 | pyroutes.register('repo_commits_elements_file', '/%(repo_name)s/commits_elements/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
296 | pyroutes.register('repo_commits_elements_file', '/%(repo_name)s/commits_elements/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
295 | pyroutes.register('repo_commits_file', '/%(repo_name)s/commits/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
297 | pyroutes.register('repo_commits_file', '/%(repo_name)s/commits/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
296 | pyroutes.register('repo_compare', '/%(repo_name)s/compare/%(source_ref_type)s@%(source_ref)s...%(target_ref_type)s@%(target_ref)s', ['repo_name', 'source_ref_type', 'source_ref', 'target_ref_type', 'target_ref']); |
|
298 | pyroutes.register('repo_compare', '/%(repo_name)s/compare/%(source_ref_type)s@%(source_ref)s...%(target_ref_type)s@%(target_ref)s', ['repo_name', 'source_ref_type', 'source_ref', 'target_ref_type', 'target_ref']); | |
297 | pyroutes.register('repo_compare_select', '/%(repo_name)s/compare', ['repo_name']); |
|
299 | pyroutes.register('repo_compare_select', '/%(repo_name)s/compare', ['repo_name']); | |
298 | pyroutes.register('repo_create', '/_admin/repos/create', []); |
|
300 | pyroutes.register('repo_create', '/_admin/repos/create', []); | |
299 | pyroutes.register('repo_creating', '/%(repo_name)s/repo_creating', ['repo_name']); |
|
301 | pyroutes.register('repo_creating', '/%(repo_name)s/repo_creating', ['repo_name']); | |
300 | pyroutes.register('repo_creating_check', '/%(repo_name)s/repo_creating_check', ['repo_name']); |
|
302 | pyroutes.register('repo_creating_check', '/%(repo_name)s/repo_creating_check', ['repo_name']); | |
301 | pyroutes.register('repo_default_reviewers_data', '/%(repo_name)s/settings/review/default-reviewers', ['repo_name']); |
|
303 | pyroutes.register('repo_default_reviewers_data', '/%(repo_name)s/settings/review/default-reviewers', ['repo_name']); | |
302 | pyroutes.register('repo_edit_toggle_locking', '/%(repo_name)s/settings/toggle_locking', ['repo_name']); |
|
304 | pyroutes.register('repo_edit_toggle_locking', '/%(repo_name)s/settings/toggle_locking', ['repo_name']); | |
303 | pyroutes.register('repo_file_authors', '/%(repo_name)s/authors/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
305 | pyroutes.register('repo_file_authors', '/%(repo_name)s/authors/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
304 | pyroutes.register('repo_file_download', '/%(repo_name)s/download/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
306 | pyroutes.register('repo_file_download', '/%(repo_name)s/download/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
305 | pyroutes.register('repo_file_download:legacy', '/%(repo_name)s/rawfile/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
307 | pyroutes.register('repo_file_download:legacy', '/%(repo_name)s/rawfile/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
306 | pyroutes.register('repo_file_history', '/%(repo_name)s/history/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
308 | pyroutes.register('repo_file_history', '/%(repo_name)s/history/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
307 | pyroutes.register('repo_file_raw', '/%(repo_name)s/raw/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
309 | pyroutes.register('repo_file_raw', '/%(repo_name)s/raw/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
308 | pyroutes.register('repo_files', '/%(repo_name)s/files/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
310 | pyroutes.register('repo_files', '/%(repo_name)s/files/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
309 | pyroutes.register('repo_files:annotated', '/%(repo_name)s/annotate/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
311 | pyroutes.register('repo_files:annotated', '/%(repo_name)s/annotate/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
310 | pyroutes.register('repo_files:annotated_previous', '/%(repo_name)s/annotate-previous/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
312 | pyroutes.register('repo_files:annotated_previous', '/%(repo_name)s/annotate-previous/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
311 | pyroutes.register('repo_files:default_commit', '/%(repo_name)s/files', ['repo_name']); |
|
313 | pyroutes.register('repo_files:default_commit', '/%(repo_name)s/files', ['repo_name']); | |
312 | pyroutes.register('repo_files:default_path', '/%(repo_name)s/files/%(commit_id)s/', ['repo_name', 'commit_id']); |
|
314 | pyroutes.register('repo_files:default_path', '/%(repo_name)s/files/%(commit_id)s/', ['repo_name', 'commit_id']); | |
313 | pyroutes.register('repo_files:rendered', '/%(repo_name)s/render/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
315 | pyroutes.register('repo_files:rendered', '/%(repo_name)s/render/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
314 | pyroutes.register('repo_files_add_file', '/%(repo_name)s/add_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
316 | pyroutes.register('repo_files_add_file', '/%(repo_name)s/add_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
315 | pyroutes.register('repo_files_check_head', '/%(repo_name)s/check_head/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
317 | pyroutes.register('repo_files_check_head', '/%(repo_name)s/check_head/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
316 | pyroutes.register('repo_files_create_file', '/%(repo_name)s/create_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
318 | pyroutes.register('repo_files_create_file', '/%(repo_name)s/create_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
317 | pyroutes.register('repo_files_delete_file', '/%(repo_name)s/delete_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
319 | pyroutes.register('repo_files_delete_file', '/%(repo_name)s/delete_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
318 | pyroutes.register('repo_files_diff', '/%(repo_name)s/diff/%(f_path)s', ['repo_name', 'f_path']); |
|
320 | pyroutes.register('repo_files_diff', '/%(repo_name)s/diff/%(f_path)s', ['repo_name', 'f_path']); | |
319 | pyroutes.register('repo_files_diff_2way_redirect', '/%(repo_name)s/diff-2way/%(f_path)s', ['repo_name', 'f_path']); |
|
321 | pyroutes.register('repo_files_diff_2way_redirect', '/%(repo_name)s/diff-2way/%(f_path)s', ['repo_name', 'f_path']); | |
320 | pyroutes.register('repo_files_edit_file', '/%(repo_name)s/edit_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
322 | pyroutes.register('repo_files_edit_file', '/%(repo_name)s/edit_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
321 | pyroutes.register('repo_files_nodelist', '/%(repo_name)s/nodelist/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
323 | pyroutes.register('repo_files_nodelist', '/%(repo_name)s/nodelist/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
322 | pyroutes.register('repo_files_remove_file', '/%(repo_name)s/remove_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
324 | pyroutes.register('repo_files_remove_file', '/%(repo_name)s/remove_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
323 | pyroutes.register('repo_files_update_file', '/%(repo_name)s/update_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
325 | pyroutes.register('repo_files_update_file', '/%(repo_name)s/update_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
324 | pyroutes.register('repo_files_upload_file', '/%(repo_name)s/upload_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
326 | pyroutes.register('repo_files_upload_file', '/%(repo_name)s/upload_file/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
325 | pyroutes.register('repo_fork_create', '/%(repo_name)s/fork/create', ['repo_name']); |
|
327 | pyroutes.register('repo_fork_create', '/%(repo_name)s/fork/create', ['repo_name']); | |
326 | pyroutes.register('repo_fork_new', '/%(repo_name)s/fork', ['repo_name']); |
|
328 | pyroutes.register('repo_fork_new', '/%(repo_name)s/fork', ['repo_name']); | |
327 | pyroutes.register('repo_forks_data', '/%(repo_name)s/forks/data', ['repo_name']); |
|
329 | pyroutes.register('repo_forks_data', '/%(repo_name)s/forks/data', ['repo_name']); | |
328 | pyroutes.register('repo_forks_show_all', '/%(repo_name)s/forks', ['repo_name']); |
|
330 | pyroutes.register('repo_forks_show_all', '/%(repo_name)s/forks', ['repo_name']); | |
329 | pyroutes.register('repo_group_create', '/_admin/repo_group/create', []); |
|
331 | pyroutes.register('repo_group_create', '/_admin/repo_group/create', []); | |
330 | pyroutes.register('repo_group_home', '/%(repo_group_name)s', ['repo_group_name']); |
|
332 | pyroutes.register('repo_group_home', '/%(repo_group_name)s', ['repo_group_name']); | |
331 | pyroutes.register('repo_group_home_slash', '/%(repo_group_name)s/', ['repo_group_name']); |
|
333 | pyroutes.register('repo_group_home_slash', '/%(repo_group_name)s/', ['repo_group_name']); | |
332 | pyroutes.register('repo_group_integrations_create', '/%(repo_group_name)s/_settings/integrations/%(integration)s/new', ['repo_group_name', 'integration']); |
|
334 | pyroutes.register('repo_group_integrations_create', '/%(repo_group_name)s/_settings/integrations/%(integration)s/new', ['repo_group_name', 'integration']); | |
333 | pyroutes.register('repo_group_integrations_edit', '/%(repo_group_name)s/_settings/integrations/%(integration)s/%(integration_id)s', ['repo_group_name', 'integration', 'integration_id']); |
|
335 | pyroutes.register('repo_group_integrations_edit', '/%(repo_group_name)s/_settings/integrations/%(integration)s/%(integration_id)s', ['repo_group_name', 'integration', 'integration_id']); | |
334 | pyroutes.register('repo_group_integrations_home', '/%(repo_group_name)s/_settings/integrations', ['repo_group_name']); |
|
336 | pyroutes.register('repo_group_integrations_home', '/%(repo_group_name)s/_settings/integrations', ['repo_group_name']); | |
335 | pyroutes.register('repo_group_integrations_list', '/%(repo_group_name)s/_settings/integrations/%(integration)s', ['repo_group_name', 'integration']); |
|
337 | pyroutes.register('repo_group_integrations_list', '/%(repo_group_name)s/_settings/integrations/%(integration)s', ['repo_group_name', 'integration']); | |
336 | pyroutes.register('repo_group_integrations_new', '/%(repo_group_name)s/_settings/integrations/new', ['repo_group_name']); |
|
338 | pyroutes.register('repo_group_integrations_new', '/%(repo_group_name)s/_settings/integrations/new', ['repo_group_name']); | |
337 | pyroutes.register('repo_group_list_data', '/_repo_groups', []); |
|
339 | pyroutes.register('repo_group_list_data', '/_repo_groups', []); | |
338 | pyroutes.register('repo_group_new', '/_admin/repo_group/new', []); |
|
340 | pyroutes.register('repo_group_new', '/_admin/repo_group/new', []); | |
339 | pyroutes.register('repo_groups', '/_admin/repo_groups', []); |
|
341 | pyroutes.register('repo_groups', '/_admin/repo_groups', []); | |
340 | pyroutes.register('repo_groups_data', '/_admin/repo_groups_data', []); |
|
342 | pyroutes.register('repo_groups_data', '/_admin/repo_groups_data', []); | |
341 | pyroutes.register('repo_integrations_create', '/%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']); |
|
343 | pyroutes.register('repo_integrations_create', '/%(repo_name)s/settings/integrations/%(integration)s/new', ['repo_name', 'integration']); | |
342 | pyroutes.register('repo_integrations_edit', '/%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']); |
|
344 | pyroutes.register('repo_integrations_edit', '/%(repo_name)s/settings/integrations/%(integration)s/%(integration_id)s', ['repo_name', 'integration', 'integration_id']); | |
343 | pyroutes.register('repo_integrations_home', '/%(repo_name)s/settings/integrations', ['repo_name']); |
|
345 | pyroutes.register('repo_integrations_home', '/%(repo_name)s/settings/integrations', ['repo_name']); | |
344 | pyroutes.register('repo_integrations_list', '/%(repo_name)s/settings/integrations/%(integration)s', ['repo_name', 'integration']); |
|
346 | pyroutes.register('repo_integrations_list', '/%(repo_name)s/settings/integrations/%(integration)s', ['repo_name', 'integration']); | |
345 | pyroutes.register('repo_integrations_new', '/%(repo_name)s/settings/integrations/new', ['repo_name']); |
|
347 | pyroutes.register('repo_integrations_new', '/%(repo_name)s/settings/integrations/new', ['repo_name']); | |
346 | pyroutes.register('repo_list_data', '/_repos', []); |
|
348 | pyroutes.register('repo_list_data', '/_repos', []); | |
347 | pyroutes.register('repo_new', '/_admin/repos/new', []); |
|
349 | pyroutes.register('repo_new', '/_admin/repos/new', []); | |
348 | pyroutes.register('repo_nodetree_full', '/%(repo_name)s/nodetree_full/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); |
|
350 | pyroutes.register('repo_nodetree_full', '/%(repo_name)s/nodetree_full/%(commit_id)s/%(f_path)s', ['repo_name', 'commit_id', 'f_path']); | |
349 | pyroutes.register('repo_nodetree_full:default_path', '/%(repo_name)s/nodetree_full/%(commit_id)s/', ['repo_name', 'commit_id']); |
|
351 | pyroutes.register('repo_nodetree_full:default_path', '/%(repo_name)s/nodetree_full/%(commit_id)s/', ['repo_name', 'commit_id']); | |
350 | pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']); |
|
352 | pyroutes.register('repo_refs_changelog_data', '/%(repo_name)s/refs-data-changelog', ['repo_name']); | |
351 | pyroutes.register('repo_refs_data', '/%(repo_name)s/refs-data', ['repo_name']); |
|
353 | pyroutes.register('repo_refs_data', '/%(repo_name)s/refs-data', ['repo_name']); | |
352 | pyroutes.register('repo_reviewers', '/%(repo_name)s/settings/review/rules', ['repo_name']); |
|
354 | pyroutes.register('repo_reviewers', '/%(repo_name)s/settings/review/rules', ['repo_name']); | |
353 | pyroutes.register('repo_reviewers_review_rule_delete', '/%(repo_name)s/settings/review/rules/%(rule_id)s/delete', ['repo_name', 'rule_id']); |
|
355 | pyroutes.register('repo_reviewers_review_rule_delete', '/%(repo_name)s/settings/review/rules/%(rule_id)s/delete', ['repo_name', 'rule_id']); | |
354 | pyroutes.register('repo_reviewers_review_rule_edit', '/%(repo_name)s/settings/review/rules/%(rule_id)s', ['repo_name', 'rule_id']); |
|
356 | pyroutes.register('repo_reviewers_review_rule_edit', '/%(repo_name)s/settings/review/rules/%(rule_id)s', ['repo_name', 'rule_id']); | |
355 | pyroutes.register('repo_reviewers_review_rule_new', '/%(repo_name)s/settings/review/rules/new', ['repo_name']); |
|
357 | pyroutes.register('repo_reviewers_review_rule_new', '/%(repo_name)s/settings/review/rules/new', ['repo_name']); | |
356 | pyroutes.register('repo_stats', '/%(repo_name)s/repo_stats/%(commit_id)s', ['repo_name', 'commit_id']); |
|
358 | pyroutes.register('repo_stats', '/%(repo_name)s/repo_stats/%(commit_id)s', ['repo_name', 'commit_id']); | |
357 | pyroutes.register('repo_summary', '/%(repo_name)s', ['repo_name']); |
|
359 | pyroutes.register('repo_summary', '/%(repo_name)s', ['repo_name']); | |
358 | pyroutes.register('repo_summary_commits', '/%(repo_name)s/summary-commits', ['repo_name']); |
|
360 | pyroutes.register('repo_summary_commits', '/%(repo_name)s/summary-commits', ['repo_name']); | |
359 | pyroutes.register('repo_summary_explicit', '/%(repo_name)s/summary', ['repo_name']); |
|
361 | pyroutes.register('repo_summary_explicit', '/%(repo_name)s/summary', ['repo_name']); | |
360 | pyroutes.register('repo_summary_slash', '/%(repo_name)s/', ['repo_name']); |
|
362 | pyroutes.register('repo_summary_slash', '/%(repo_name)s/', ['repo_name']); | |
361 | pyroutes.register('repos', '/_admin/repos', []); |
|
363 | pyroutes.register('repos', '/_admin/repos', []); | |
362 | pyroutes.register('repos_data', '/_admin/repos_data', []); |
|
364 | pyroutes.register('repos_data', '/_admin/repos_data', []); | |
363 | pyroutes.register('reset_password', '/_admin/password_reset', []); |
|
365 | pyroutes.register('reset_password', '/_admin/password_reset', []); | |
364 | pyroutes.register('reset_password_confirmation', '/_admin/password_reset_confirmation', []); |
|
366 | pyroutes.register('reset_password_confirmation', '/_admin/password_reset_confirmation', []); | |
365 | pyroutes.register('robots', '/robots.txt', []); |
|
367 | pyroutes.register('robots', '/robots.txt', []); | |
366 | pyroutes.register('rss_feed_home', '/%(repo_name)s/feed-rss', ['repo_name']); |
|
368 | pyroutes.register('rss_feed_home', '/%(repo_name)s/feed-rss', ['repo_name']); | |
367 | pyroutes.register('rss_feed_home_old', '/%(repo_name)s/feed/rss', ['repo_name']); |
|
369 | pyroutes.register('rss_feed_home_old', '/%(repo_name)s/feed/rss', ['repo_name']); | |
368 | pyroutes.register('search', '/_admin/search', []); |
|
370 | pyroutes.register('search', '/_admin/search', []); | |
369 | pyroutes.register('search_repo', '/%(repo_name)s/_search', ['repo_name']); |
|
371 | pyroutes.register('search_repo', '/%(repo_name)s/_search', ['repo_name']); | |
370 | pyroutes.register('search_repo_alt', '/%(repo_name)s/search', ['repo_name']); |
|
372 | pyroutes.register('search_repo_alt', '/%(repo_name)s/search', ['repo_name']); | |
371 | pyroutes.register('search_repo_group', '/%(repo_group_name)s/_search', ['repo_group_name']); |
|
373 | pyroutes.register('search_repo_group', '/%(repo_group_name)s/_search', ['repo_group_name']); | |
372 | pyroutes.register('store_user_session_value', '/_store_session_attr', []); |
|
374 | pyroutes.register('store_user_session_value', '/_store_session_attr', []); | |
373 | pyroutes.register('strip_check', '/%(repo_name)s/settings/strip_check', ['repo_name']); |
|
375 | pyroutes.register('strip_check', '/%(repo_name)s/settings/strip_check', ['repo_name']); | |
374 | pyroutes.register('strip_execute', '/%(repo_name)s/settings/strip_execute', ['repo_name']); |
|
376 | pyroutes.register('strip_execute', '/%(repo_name)s/settings/strip_execute', ['repo_name']); | |
375 | pyroutes.register('tags_home', '/%(repo_name)s/tags', ['repo_name']); |
|
377 | pyroutes.register('tags_home', '/%(repo_name)s/tags', ['repo_name']); | |
376 | pyroutes.register('toggle_following', '/_admin/toggle_following', []); |
|
378 | pyroutes.register('toggle_following', '/_admin/toggle_following', []); | |
377 | pyroutes.register('upload_file', '/_file_store/upload', []); |
|
379 | pyroutes.register('upload_file', '/_file_store/upload', []); | |
378 | pyroutes.register('user_autocomplete_data', '/_users', []); |
|
380 | pyroutes.register('user_autocomplete_data', '/_users', []); | |
379 | pyroutes.register('user_create_personal_repo_group', '/_admin/users/%(user_id)s/create_repo_group', ['user_id']); |
|
381 | pyroutes.register('user_create_personal_repo_group', '/_admin/users/%(user_id)s/create_repo_group', ['user_id']); | |
380 | pyroutes.register('user_delete', '/_admin/users/%(user_id)s/delete', ['user_id']); |
|
382 | pyroutes.register('user_delete', '/_admin/users/%(user_id)s/delete', ['user_id']); | |
381 | pyroutes.register('user_disable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_disable', ['user_id']); |
|
383 | pyroutes.register('user_disable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_disable', ['user_id']); | |
382 | pyroutes.register('user_edit', '/_admin/users/%(user_id)s/edit', ['user_id']); |
|
384 | pyroutes.register('user_edit', '/_admin/users/%(user_id)s/edit', ['user_id']); | |
383 | pyroutes.register('user_edit_advanced', '/_admin/users/%(user_id)s/edit/advanced', ['user_id']); |
|
385 | pyroutes.register('user_edit_advanced', '/_admin/users/%(user_id)s/edit/advanced', ['user_id']); | |
384 | pyroutes.register('user_edit_global_perms', '/_admin/users/%(user_id)s/edit/global_permissions', ['user_id']); |
|
386 | pyroutes.register('user_edit_global_perms', '/_admin/users/%(user_id)s/edit/global_permissions', ['user_id']); | |
385 | pyroutes.register('user_edit_global_perms_update', '/_admin/users/%(user_id)s/edit/global_permissions/update', ['user_id']); |
|
387 | pyroutes.register('user_edit_global_perms_update', '/_admin/users/%(user_id)s/edit/global_permissions/update', ['user_id']); | |
386 | pyroutes.register('user_enable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_enable', ['user_id']); |
|
388 | pyroutes.register('user_enable_force_password_reset', '/_admin/users/%(user_id)s/password_reset_enable', ['user_id']); | |
387 | pyroutes.register('user_group_autocomplete_data', '/_user_groups', []); |
|
389 | pyroutes.register('user_group_autocomplete_data', '/_user_groups', []); | |
388 | pyroutes.register('user_group_members_data', '/_admin/user_groups/%(user_group_id)s/members', ['user_group_id']); |
|
390 | pyroutes.register('user_group_members_data', '/_admin/user_groups/%(user_group_id)s/members', ['user_group_id']); | |
389 | pyroutes.register('user_group_profile', '/_profile_user_group/%(user_group_name)s', ['user_group_name']); |
|
391 | pyroutes.register('user_group_profile', '/_profile_user_group/%(user_group_name)s', ['user_group_name']); | |
390 | pyroutes.register('user_groups', '/_admin/user_groups', []); |
|
392 | pyroutes.register('user_groups', '/_admin/user_groups', []); | |
391 | pyroutes.register('user_groups_create', '/_admin/user_groups/create', []); |
|
393 | pyroutes.register('user_groups_create', '/_admin/user_groups/create', []); | |
392 | pyroutes.register('user_groups_data', '/_admin/user_groups_data', []); |
|
394 | pyroutes.register('user_groups_data', '/_admin/user_groups_data', []); | |
393 | pyroutes.register('user_groups_delete', '/_admin/user_groups/%(user_group_id)s/delete', ['user_group_id']); |
|
395 | pyroutes.register('user_groups_delete', '/_admin/user_groups/%(user_group_id)s/delete', ['user_group_id']); | |
394 | pyroutes.register('user_groups_new', '/_admin/user_groups/new', []); |
|
396 | pyroutes.register('user_groups_new', '/_admin/user_groups/new', []); | |
395 | pyroutes.register('user_groups_update', '/_admin/user_groups/%(user_group_id)s/update', ['user_group_id']); |
|
397 | pyroutes.register('user_groups_update', '/_admin/user_groups/%(user_group_id)s/update', ['user_group_id']); | |
396 | pyroutes.register('user_notice_dismiss', '/_admin/users/%(user_id)s/notice_dismiss', ['user_id']); |
|
398 | pyroutes.register('user_notice_dismiss', '/_admin/users/%(user_id)s/notice_dismiss', ['user_id']); | |
397 | pyroutes.register('user_profile', '/_profiles/%(username)s', ['username']); |
|
399 | pyroutes.register('user_profile', '/_profiles/%(username)s', ['username']); | |
398 | pyroutes.register('user_update', '/_admin/users/%(user_id)s/update', ['user_id']); |
|
400 | pyroutes.register('user_update', '/_admin/users/%(user_id)s/update', ['user_id']); | |
399 | pyroutes.register('users', '/_admin/users', []); |
|
401 | pyroutes.register('users', '/_admin/users', []); | |
400 | pyroutes.register('users_create', '/_admin/users/create', []); |
|
402 | pyroutes.register('users_create', '/_admin/users/create', []); | |
401 | pyroutes.register('users_data', '/_admin/users_data', []); |
|
403 | pyroutes.register('users_data', '/_admin/users_data', []); | |
402 | pyroutes.register('users_new', '/_admin/users/new', []); |
|
404 | pyroutes.register('users_new', '/_admin/users/new', []); | |
403 | } |
|
405 | } |
General Comments 0
You need to be logged in to leave comments.
Login now