Show More
@@ -1,183 +1,183 b'' | |||||
1 | # -*- coding: utf-8 -*- |
|
1 | # -*- coding: utf-8 -*- | |
2 |
|
2 | |||
3 | # Copyright (C) 2016-2016 RhodeCode GmbH |
|
3 | # Copyright (C) 2016-2016 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 |
|
22 | |||
23 | import colander |
|
23 | import colander | |
24 |
|
24 | |||
25 | from rhodecode.translation import _ |
|
25 | from rhodecode.translation import _ | |
26 | from rhodecode.model.validation_schema import preparers |
|
26 | from rhodecode.model.validation_schema import preparers | |
27 |
|
27 | |||
28 |
|
28 | |||
29 | def nodes_to_sequence(nodes, colander_node=None): |
|
29 | def nodes_to_sequence(nodes, colander_node=None): | |
30 | """ |
|
30 | """ | |
31 | Converts old style dict nodes to new list of dicts |
|
31 | Converts old style dict nodes to new list of dicts | |
32 |
|
32 | |||
33 | :param nodes: dict with key beeing name of the file |
|
33 | :param nodes: dict with key beeing name of the file | |
34 |
|
34 | |||
35 | """ |
|
35 | """ | |
36 | if not isinstance(nodes, dict): |
|
36 | if not isinstance(nodes, dict): | |
37 | msg = 'Nodes needs to be a dict, got {}'.format(type(nodes)) |
|
37 | msg = 'Nodes needs to be a dict, got {}'.format(type(nodes)) | |
38 | raise colander.Invalid(colander_node, msg) |
|
38 | raise colander.Invalid(colander_node, msg) | |
39 | out = [] |
|
39 | out = [] | |
40 |
|
40 | |||
41 | for key, val in nodes.items(): |
|
41 | for key, val in nodes.items(): | |
42 | val = (isinstance(val, dict) and val) or {} |
|
42 | val = (isinstance(val, dict) and val) or {} | |
43 | out.append(dict( |
|
43 | out.append(dict( | |
44 | filename=key, |
|
44 | filename=key, | |
45 | content=val.get('content'), |
|
45 | content=val.get('content'), | |
46 | mimetype=val.get('mimetype') |
|
46 | mimetype=val.get('mimetype') | |
47 | )) |
|
47 | )) | |
48 |
|
48 | |||
49 | out = Nodes().deserialize(out) |
|
49 | out = Nodes().deserialize(out) | |
50 | return out |
|
50 | return out | |
51 |
|
51 | |||
52 |
|
52 | |||
53 | def sequence_to_nodes(nodes, colander_node=None): |
|
53 | def sequence_to_nodes(nodes, colander_node=None): | |
54 | if not isinstance(nodes, list): |
|
54 | if not isinstance(nodes, list): | |
55 | msg = 'Nodes needs to be a list, got {}'.format(type(nodes)) |
|
55 | msg = 'Nodes needs to be a list, got {}'.format(type(nodes)) | |
56 | raise colander.Invalid(colander_node, msg) |
|
56 | raise colander.Invalid(colander_node, msg) | |
57 | nodes = Nodes().deserialize(nodes) |
|
57 | nodes = Nodes().deserialize(nodes) | |
58 |
|
58 | |||
59 | out = {} |
|
59 | out = {} | |
60 | try: |
|
60 | try: | |
61 | for file_data in nodes: |
|
61 | for file_data in nodes: | |
62 | file_data_skip = file_data.copy() |
|
62 | file_data_skip = file_data.copy() | |
63 | # if we got filename_org we use it as a key so we keep old |
|
63 | # if we got filename_org we use it as a key so we keep old | |
64 | # name as input and rename is-reflected inside the values as |
|
64 | # name as input and rename is-reflected inside the values as | |
65 | # filename and filename_org differences. |
|
65 | # filename and filename_org differences. | |
66 | filename_org = file_data.get('filename_org') |
|
66 | filename_org = file_data.get('filename_org') | |
67 | filename = filename_org or file_data['filename'] |
|
67 | filename = filename_org or file_data['filename'] | |
68 | out[filename] = {} |
|
68 | out[filename] = {} | |
69 | out[filename].update(file_data_skip) |
|
69 | out[filename].update(file_data_skip) | |
70 |
|
70 | |||
71 | except Exception as e: |
|
71 | except Exception as e: | |
72 | msg = 'Invalid data format org_exc:`{}`'.format(repr(e)) |
|
72 | msg = 'Invalid data format org_exc:`{}`'.format(repr(e)) | |
73 | raise colander.Invalid(colander_node, msg) |
|
73 | raise colander.Invalid(colander_node, msg) | |
74 | return out |
|
74 | return out | |
75 |
|
75 | |||
76 |
|
76 | |||
77 | @colander.deferred |
|
77 | @colander.deferred | |
78 | def deferred_lifetime_validator(node, kw): |
|
78 | def deferred_lifetime_validator(node, kw): | |
79 | options = kw.get('lifetime_options', []) |
|
79 | options = kw.get('lifetime_options', []) | |
80 | return colander.All( |
|
80 | return colander.All( | |
81 | colander.Range(min=-1, max=60 * 24 * 30 * 12), |
|
81 | colander.Range(min=-1, max=60 * 24 * 30 * 12), | |
82 | colander.OneOf([x for x in options])) |
|
82 | colander.OneOf([x for x in options])) | |
83 |
|
83 | |||
84 |
|
84 | |||
85 | def unique_gist_validator(node, value): |
|
85 | def unique_gist_validator(node, value): | |
86 | from rhodecode.model.db import Gist |
|
86 | from rhodecode.model.db import Gist | |
87 | existing = Gist.get_by_access_id(value) |
|
87 | existing = Gist.get_by_access_id(value) | |
88 | if existing: |
|
88 | if existing: | |
89 | msg = _(u'Gist with name {} already exists').format(value) |
|
89 | msg = _(u'Gist with name {} already exists').format(value) | |
90 | raise colander.Invalid(node, msg) |
|
90 | raise colander.Invalid(node, msg) | |
91 |
|
91 | |||
92 |
|
92 | |||
93 | def filename_validator(node, value): |
|
93 | def filename_validator(node, value): | |
94 | if value != os.path.basename(value): |
|
94 | if value != os.path.basename(value): | |
95 | msg = _(u'Filename {} cannot be inside a directory').format(value) |
|
95 | msg = _(u'Filename {} cannot be inside a directory').format(value) | |
96 | raise colander.Invalid(node, msg) |
|
96 | raise colander.Invalid(node, msg) | |
97 |
|
97 | |||
98 |
|
98 | |||
99 | class NodeSchema(colander.MappingSchema): |
|
99 | class NodeSchema(colander.MappingSchema): | |
100 | # if we perform rename this will be org filename |
|
100 | # if we perform rename this will be org filename | |
101 | filename_org = colander.SchemaNode( |
|
101 | filename_org = colander.SchemaNode( | |
102 | colander.String(), |
|
102 | colander.String(), | |
103 | preparer=[preparers.strip_preparer, |
|
103 | preparer=[preparers.strip_preparer, | |
104 | preparers.non_ascii_strip_preparer], |
|
104 | preparers.non_ascii_strip_preparer], | |
105 | validator=filename_validator, |
|
105 | validator=filename_validator, | |
106 | missing=None) |
|
106 | missing=None) | |
107 |
|
107 | |||
108 | filename = colander.SchemaNode( |
|
108 | filename = colander.SchemaNode( | |
109 | colander.String(), |
|
109 | colander.String(), | |
110 | preparer=[preparers.strip_preparer, |
|
110 | preparer=[preparers.strip_preparer, | |
111 | preparers.non_ascii_strip_preparer], |
|
111 | preparers.non_ascii_strip_preparer], | |
112 | validator=filename_validator) |
|
112 | validator=filename_validator) | |
113 |
|
113 | |||
114 | content = colander.SchemaNode( |
|
114 | content = colander.SchemaNode( | |
115 | colander.String()) |
|
115 | colander.String()) | |
116 | mimetype = colander.SchemaNode( |
|
116 | mimetype = colander.SchemaNode( | |
117 | colander.String(), |
|
117 | colander.String(), | |
118 | missing=None) |
|
118 | missing=None) | |
119 |
|
119 | |||
120 |
|
120 | |||
121 | class Nodes(colander.SequenceSchema): |
|
121 | class Nodes(colander.SequenceSchema): | |
122 | filenames = NodeSchema() |
|
122 | filenames = NodeSchema() | |
123 |
|
123 | |||
124 | def validator(self, node, cstruct): |
|
124 | def validator(self, node, cstruct): | |
125 | if not isinstance(cstruct, list): |
|
125 | if not isinstance(cstruct, list): | |
126 | return |
|
126 | return | |
127 |
|
127 | |||
128 | found_filenames = [] |
|
128 | found_filenames = [] | |
129 | for data in cstruct: |
|
129 | for data in cstruct: | |
130 | filename = data['filename'] |
|
130 | filename = data['filename'] | |
131 | if filename in found_filenames: |
|
131 | if filename in found_filenames: | |
132 | msg = _('Duplicated value for filename found: `{}`').format( |
|
132 | msg = _('Duplicated value for filename found: `{}`').format( | |
133 | filename) |
|
133 | filename) | |
134 | raise colander.Invalid(node, msg) |
|
134 | raise colander.Invalid(node, msg) | |
135 | found_filenames.append(filename) |
|
135 | found_filenames.append(filename) | |
136 |
|
136 | |||
137 |
|
137 | |||
138 | class GistSchema(colander.MappingSchema): |
|
138 | class GistSchema(colander.MappingSchema): | |
139 | """ |
|
139 | """ | |
140 | schema = GistSchema() |
|
140 | schema = GistSchema() | |
141 | schema.bind( |
|
141 | schema.bind( | |
142 | lifetime_options = [1,2,3] |
|
142 | lifetime_options = [1,2,3] | |
143 | ) |
|
143 | ) | |
144 | out = schema.deserialize(dict( |
|
144 | out = schema.deserialize(dict( | |
145 | nodes=[ |
|
145 | nodes=[ | |
146 | {'filename': 'x', 'content': 'xxx', }, |
|
146 | {'filename': 'x', 'content': 'xxx', }, | |
147 | {'filename': 'docs/Z', 'content': 'xxx', 'mimetype': 'x'}, |
|
147 | {'filename': 'docs/Z', 'content': 'xxx', 'mimetype': 'x'}, | |
148 | ] |
|
148 | ] | |
149 | )) |
|
149 | )) | |
150 | """ |
|
150 | """ | |
151 |
|
151 | |||
152 | from rhodecode.model.db import Gist |
|
152 | from rhodecode.model.db import Gist | |
153 |
|
153 | |||
154 | gistid = colander.SchemaNode( |
|
154 | gistid = colander.SchemaNode( | |
155 | colander.String(), |
|
155 | colander.String(), | |
156 | missing=None, |
|
156 | missing=None, | |
157 | preparer=[preparers.strip_preparer, |
|
157 | preparer=[preparers.strip_preparer, | |
158 | preparers.non_ascii_strip_preparer, |
|
158 | preparers.non_ascii_strip_preparer, | |
159 | preparers.slugify_preparer], |
|
159 | preparers.slugify_preparer], | |
160 | validator=colander.All( |
|
160 | validator=colander.All( | |
161 | colander.Length(min=3), |
|
161 | colander.Length(min=3), | |
162 | unique_gist_validator |
|
162 | unique_gist_validator | |
163 | )) |
|
163 | )) | |
164 |
|
164 | |||
165 | description = colander.SchemaNode( |
|
165 | description = colander.SchemaNode( | |
166 | colander.String(), |
|
166 | colander.String(), | |
167 | missing=u'') |
|
167 | missing=u'') | |
168 |
|
168 | |||
169 | lifetime = colander.SchemaNode( |
|
169 | lifetime = colander.SchemaNode( | |
170 | colander.Integer(), |
|
170 | colander.Integer(), | |
171 | validator=deferred_lifetime_validator) |
|
171 | validator=deferred_lifetime_validator) | |
172 |
|
172 | |||
173 | gist_acl_level = colander.SchemaNode( |
|
173 | gist_acl_level = colander.SchemaNode( | |
174 | colander.String(), |
|
174 | colander.String(), | |
175 | validator=colander.OneOf([Gist.ACL_LEVEL_PUBLIC, |
|
175 | validator=colander.OneOf([Gist.ACL_LEVEL_PUBLIC, | |
176 | Gist.ACL_LEVEL_PRIVATE])) |
|
176 | Gist.ACL_LEVEL_PRIVATE])) | |
177 |
|
177 | |||
178 | gist_type = colander.SchemaNode( |
|
178 | gist_type = colander.SchemaNode( | |
179 | colander.String(), |
|
179 | colander.String(), | |
180 |
missing=Gist. |
|
180 | missing=Gist.GIST_PUBLIC, | |
181 | validator=colander.OneOf([Gist.GIST_PRIVATE, Gist.GIST_PUBLIC])) |
|
181 | validator=colander.OneOf([Gist.GIST_PRIVATE, Gist.GIST_PUBLIC])) | |
182 |
|
182 | |||
183 | nodes = Nodes() |
|
183 | nodes = Nodes() |
General Comments 0
You need to be logged in to leave comments.
Login now